Use video abuse filters on client side
[oweals/peertube.git] / client / src / app / shared / rest / rest.service.ts
1 import { SortMeta } from 'primeng/api'
2 import { HttpParams } from '@angular/common/http'
3 import { Injectable } from '@angular/core'
4 import { ComponentPaginationLight } from './component-pagination.model'
5 import { RestPagination } from './rest-pagination'
6
7 interface QueryStringFilterPrefixes {
8   [key: string]: {
9     prefix: string
10     handler?: (v: string) => string | number
11     multiple?: boolean
12   }
13 }
14
15 type ParseQueryStringFilterResult = {
16   [key: string]: string | number | (string | number)[]
17 }
18
19 @Injectable()
20 export class RestService {
21
22   addRestGetParams (params: HttpParams, pagination?: RestPagination, sort?: SortMeta | string) {
23     let newParams = params
24
25     if (pagination !== undefined) {
26       newParams = newParams.set('start', pagination.start.toString())
27                            .set('count', pagination.count.toString())
28     }
29
30     if (sort !== undefined) {
31       let sortString = ''
32
33       if (typeof sort === 'string') {
34         sortString = sort
35       } else {
36         const sortPrefix = sort.order === 1 ? '' : '-'
37         sortString = sortPrefix + sort.field
38       }
39
40       newParams = newParams.set('sort', sortString)
41     }
42
43     return newParams
44   }
45
46   addObjectParams (params: HttpParams, object: { [ name: string ]: any }) {
47     for (const name of Object.keys(object)) {
48       const value = object[name]
49       if (!value) continue
50
51       if (Array.isArray(value) && value.length !== 0) {
52         for (const v of value) params = params.append(name, v)
53       } else {
54         params = params.append(name, value)
55       }
56     }
57
58     return params
59   }
60
61   componentPaginationToRestPagination (componentPagination: ComponentPaginationLight): RestPagination {
62     const start: number = (componentPagination.currentPage - 1) * componentPagination.itemsPerPage
63     const count: number = componentPagination.itemsPerPage
64
65     return { start, count }
66   }
67
68   parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes): ParseQueryStringFilterResult {
69     if (!q) return {}
70
71     // Tokenize the strings using spaces
72     const tokens = q.split(' ').filter(token => !!token)
73
74     // Build prefix array
75     const prefixeStrings = Object.values(prefixes)
76                            .map(p => p.prefix)
77
78     // Search is the querystring minus defined filters
79     const searchTokens = tokens.filter(t => {
80       return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false)
81     })
82
83     const additionalFilters: ParseQueryStringFilterResult = {}
84
85     for (const prefixKey of Object.keys(prefixes)) {
86       const prefixObj = prefixes[prefixKey]
87       const prefix = prefixObj.prefix
88
89       const matchedTokens = tokens.filter(t => t.startsWith(prefix))
90                                   .map(t => t.slice(prefix.length)) // Keep the value filter
91                                   .map(t => {
92                                     if (prefixObj.handler) return prefixObj.handler(t)
93
94                                     return t
95                                   })
96                                   .filter(t => !!t)
97
98       if (matchedTokens.length === 0) continue
99
100       additionalFilters[prefixKey] = prefixObj.multiple === true
101         ? matchedTokens
102         : matchedTokens[0]
103     }
104
105     return {
106       search: searchTokens.join(' '),
107
108       ...additionalFilters
109     }
110   }
111 }