]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/utils.ts
parseQueryStringFilter cleanup
[github/Chocobozzz/PeerTube.git] / server / models / utils.ts
index 7137419a2e3d34b2543befb5e5d7012e162c06e1..fe4596d31b5ff5818033a5ce8a2448ce0eed3748 100644 (file)
@@ -208,13 +208,60 @@ function buildDirectionAndField (value: string) {
 }
 
 function searchAttribute (sourceField, targetField) {
-  return sourceField
-    ? {
+  if (sourceField) {
+    return {
       [targetField]: {
         [Op.iLike]: `%${sourceField}%`
       }
     }
-    : {}
+  } else {
+    return {}
+  }
+}
+
+interface QueryStringFilterPrefixes {
+  [key: string]: string | { prefix: string, handler: Function, multiple?: boolean }
+}
+
+function parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes): {
+  search: string
+  [key: string]: string | number | string[] | number[]
+} {
+  const tokens = q // tokenize only if we have a querystring
+    ? [].concat.apply([], q.split('"').map((v, i) => i % 2 ? v : v.split(' '))).filter(Boolean) // split by space unless using double quotes
+    : []
+
+  const objectMap = (obj, fn) => Object.fromEntries(
+    Object.entries(obj).map(
+      ([ k, v ], i) => [ k, fn(v, k, i) ]
+    )
+  )
+
+  return {
+    // search is the querystring minus defined filters
+    search: tokens.filter(e => !Object.values(prefixes).some(p => {
+      if (typeof p === 'string') {
+        return e.startsWith(p)
+      } else {
+        return e.startsWith(p.prefix)
+      }
+    })).join(' '),
+    // filters defined in prefixes are added under their own name
+    ...objectMap(prefixes, p => {
+      if (typeof p === 'string') {
+        return tokens.filter(e => e.startsWith(p)).map(e => e.slice(p.length)) // we keep the matched item, and remove its prefix
+      } else {
+        const _tokens = tokens.filter(e => e.startsWith(p.prefix)).map(e => e.slice(p.prefix.length)).map(p.handler)
+        // multiple is false by default, meaning we usually just keep the first occurence of a given prefix
+        if (!p.multiple && _tokens.length > 0) {
+          return _tokens[0]
+        } else if (!p.multiple) {
+          return ''
+        }
+        return _tokens
+      }
+    })
+  }
 }
 
 // ---------------------------------------------------------------------------
@@ -239,7 +286,8 @@ export {
   getFollowsSort,
   buildDirectionAndField,
   createSafeIn,
-  searchAttribute
+  searchAttribute,
+  parseQueryStringFilter
 }
 
 // ---------------------------------------------------------------------------