]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/shared/sort.ts
Refactor model utils
[github/Chocobozzz/PeerTube.git] / server / models / shared / sort.ts
1 import { literal, OrderItem, Sequelize } from 'sequelize'
2
3 // Translate for example "-name" to [ [ 'name', 'DESC' ], [ 'id', 'ASC' ] ]
4 function getSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
5 const { direction, field } = buildSortDirectionAndField(value)
6
7 let finalField: string | ReturnType<typeof Sequelize.col>
8
9 if (field.toLowerCase() === 'match') { // Search
10 finalField = Sequelize.col('similarity')
11 } else {
12 finalField = field
13 }
14
15 return [ [ finalField, direction ], lastSort ]
16 }
17
18 function getAdminUsersSort (value: string): OrderItem[] {
19 const { direction, field } = buildSortDirectionAndField(value)
20
21 let finalField: string | ReturnType<typeof Sequelize.col>
22
23 if (field === 'videoQuotaUsed') { // Users list
24 finalField = Sequelize.col('videoQuotaUsed')
25 } else {
26 finalField = field
27 }
28
29 const nullPolicy = direction === 'ASC'
30 ? 'NULLS FIRST'
31 : 'NULLS LAST'
32
33 // FIXME: typings
34 return [ [ finalField as any, direction, nullPolicy ], [ 'id', 'ASC' ] ]
35 }
36
37 function getPlaylistSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
38 const { direction, field } = buildSortDirectionAndField(value)
39
40 if (field.toLowerCase() === 'name') {
41 return [ [ 'displayName', direction ], lastSort ]
42 }
43
44 return getSort(value, lastSort)
45 }
46
47 function getCommentSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
48 const { direction, field } = buildSortDirectionAndField(value)
49
50 if (field === 'totalReplies') {
51 return [
52 [ Sequelize.literal('"totalReplies"'), direction ],
53 lastSort
54 ]
55 }
56
57 return getSort(value, lastSort)
58 }
59
60 function getVideoSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
61 const { direction, field } = buildSortDirectionAndField(value)
62
63 if (field.toLowerCase() === 'trending') { // Sort by aggregation
64 return [
65 [ Sequelize.fn('COALESCE', Sequelize.fn('SUM', Sequelize.col('VideoViews.views')), '0'), direction ],
66
67 [ Sequelize.col('VideoModel.views'), direction ],
68
69 lastSort
70 ]
71 } else if (field === 'publishedAt') {
72 return [
73 [ 'ScheduleVideoUpdate', 'updateAt', direction + ' NULLS LAST' ],
74
75 [ Sequelize.col('VideoModel.publishedAt'), direction ],
76
77 lastSort
78 ]
79 }
80
81 let finalField: string | ReturnType<typeof Sequelize.col>
82
83 // Alias
84 if (field.toLowerCase() === 'match') { // Search
85 finalField = Sequelize.col('similarity')
86 } else {
87 finalField = field
88 }
89
90 const firstSort: OrderItem = typeof finalField === 'string'
91 ? finalField.split('.').concat([ direction ]) as OrderItem
92 : [ finalField, direction ]
93
94 return [ firstSort, lastSort ]
95 }
96
97 function getBlacklistSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
98 const { direction, field } = buildSortDirectionAndField(value)
99
100 const videoFields = new Set([ 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid' ])
101
102 if (videoFields.has(field)) {
103 return [
104 [ literal(`"Video.${field}" ${direction}`) ],
105 lastSort
106 ] as OrderItem[]
107 }
108
109 return getSort(value, lastSort)
110 }
111
112 function getInstanceFollowsSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
113 const { direction, field } = buildSortDirectionAndField(value)
114
115 if (field === 'redundancyAllowed') {
116 return [
117 [ 'ActorFollowing.Server.redundancyAllowed', direction ],
118 lastSort
119 ]
120 }
121
122 return getSort(value, lastSort)
123 }
124
125 function getChannelSyncSort (value: string): OrderItem[] {
126 const { direction, field } = buildSortDirectionAndField(value)
127 if (field.toLowerCase() === 'videochannel') {
128 return [
129 [ literal('"VideoChannel.name"'), direction ]
130 ]
131 }
132 return [ [ field, direction ] ]
133 }
134
135 function buildSortDirectionAndField (value: string) {
136 let field: string
137 let direction: 'ASC' | 'DESC'
138
139 if (value.substring(0, 1) === '-') {
140 direction = 'DESC'
141 field = value.substring(1)
142 } else {
143 direction = 'ASC'
144 field = value
145 }
146
147 return { direction, field }
148 }
149
150 export {
151 buildSortDirectionAndField,
152 getPlaylistSort,
153 getSort,
154 getCommentSort,
155 getAdminUsersSort,
156 getVideoSort,
157 getBlacklistSort,
158 getChannelSyncSort,
159 getInstanceFollowsSort
160 }