1 import { literal, OrderItem, Sequelize } from 'sequelize'
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)
7 let finalField: string | ReturnType<typeof Sequelize.col>
9 if (field.toLowerCase() === 'match') { // Search
10 finalField = Sequelize.col('similarity')
15 return [ [ finalField, direction ], lastSort ]
18 function getAdminUsersSort (value: string): OrderItem[] {
19 const { direction, field } = buildSortDirectionAndField(value)
21 let finalField: string | ReturnType<typeof Sequelize.col>
23 if (field === 'videoQuotaUsed') { // Users list
24 finalField = Sequelize.col('videoQuotaUsed')
29 const nullPolicy = direction === 'ASC'
34 return [ [ finalField as any, direction, nullPolicy ], [ 'id', 'ASC' ] ]
37 function getPlaylistSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
38 const { direction, field } = buildSortDirectionAndField(value)
40 if (field.toLowerCase() === 'name') {
41 return [ [ 'displayName', direction ], lastSort ]
44 return getSort(value, lastSort)
47 function getCommentSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
48 const { direction, field } = buildSortDirectionAndField(value)
50 if (field === 'totalReplies') {
52 [ Sequelize.literal('"totalReplies"'), direction ],
57 return getSort(value, lastSort)
60 function getVideoSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
61 const { direction, field } = buildSortDirectionAndField(value)
63 if (field.toLowerCase() === 'trending') { // Sort by aggregation
65 [ Sequelize.fn('COALESCE', Sequelize.fn('SUM', Sequelize.col('VideoViews.views')), '0'), direction ],
67 [ Sequelize.col('VideoModel.views'), direction ],
71 } else if (field === 'publishedAt') {
73 [ 'ScheduleVideoUpdate', 'updateAt', direction + ' NULLS LAST' ],
75 [ Sequelize.col('VideoModel.publishedAt'), direction ],
81 let finalField: string | ReturnType<typeof Sequelize.col>
84 if (field.toLowerCase() === 'match') { // Search
85 finalField = Sequelize.col('similarity')
90 const firstSort: OrderItem = typeof finalField === 'string'
91 ? finalField.split('.').concat([ direction ]) as OrderItem
92 : [ finalField, direction ]
94 return [ firstSort, lastSort ]
97 function getBlacklistSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
98 const { direction, field } = buildSortDirectionAndField(value)
100 const videoFields = new Set([ 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid' ])
102 if (videoFields.has(field)) {
104 [ literal(`"Video.${field}" ${direction}`) ],
109 return getSort(value, lastSort)
112 function getInstanceFollowsSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]): OrderItem[] {
113 const { direction, field } = buildSortDirectionAndField(value)
115 if (field === 'redundancyAllowed') {
117 [ 'ActorFollowing.Server.redundancyAllowed', direction ],
122 return getSort(value, lastSort)
125 function getChannelSyncSort (value: string): OrderItem[] {
126 const { direction, field } = buildSortDirectionAndField(value)
127 if (field.toLowerCase() === 'videochannel') {
129 [ literal('"VideoChannel.name"'), direction ]
132 return [ [ field, direction ] ]
135 function buildSortDirectionAndField (value: string) {
137 let direction: 'ASC' | 'DESC'
139 if (value.substring(0, 1) === '-') {
141 field = value.substring(1)
147 return { direction, field }
151 buildSortDirectionAndField,
159 getInstanceFollowsSort