]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/activitypub/actor-follow.ts
Run videojs outside angular
[github/Chocobozzz/PeerTube.git] / server / models / activitypub / actor-follow.ts
CommitLineData
50d6de9c
C
1import * as Bluebird from 'bluebird'
2import { values } from 'lodash'
3import * as Sequelize from 'sequelize'
4import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
5import { FollowState } from '../../../shared/models/actors'
6import { FOLLOW_STATES } from '../../initializers/constants'
7import { ServerModel } from '../server/server'
8import { getSort } from '../utils'
9import { ActorModel } from './actor'
10
11@Table({
12 tableName: 'actorFollow',
13 indexes: [
14 {
15 fields: [ 'actorId' ]
16 },
17 {
18 fields: [ 'targetActorId' ]
19 },
20 {
21 fields: [ 'actorId', 'targetActorId' ],
22 unique: true
23 }
24 ]
25})
26export class ActorFollowModel extends Model<ActorFollowModel> {
27
28 @AllowNull(false)
29 @Column(DataType.ENUM(values(FOLLOW_STATES)))
30 state: FollowState
31
32 @CreatedAt
33 createdAt: Date
34
35 @UpdatedAt
36 updatedAt: Date
37
38 @ForeignKey(() => ActorModel)
39 @Column
40 actorId: number
41
42 @BelongsTo(() => ActorModel, {
43 foreignKey: {
44 name: 'actorId',
45 allowNull: false
46 },
47 as: 'ActorFollower',
48 onDelete: 'CASCADE'
49 })
50 ActorFollower: ActorModel
51
52 @ForeignKey(() => ActorModel)
53 @Column
54 targetActorId: number
55
56 @BelongsTo(() => ActorModel, {
57 foreignKey: {
58 name: 'targetActorId',
59 allowNull: false
60 },
61 as: 'ActorFollowing',
62 onDelete: 'CASCADE'
63 })
64 ActorFollowing: ActorModel
65
66 static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Sequelize.Transaction) {
67 const query = {
68 where: {
69 actorId,
70 targetActorId: targetActorId
71 },
72 include: [
73 {
74 model: ActorModel,
75 required: true,
76 as: 'ActorFollower'
77 },
78 {
79 model: ActorModel,
80 required: true,
81 as: 'ActorFollowing'
82 }
83 ],
84 transaction: t
85 }
86
87 return ActorFollowModel.findOne(query)
88 }
89
90 static loadByActorAndTargetHost (actorId: number, targetHost: string, t?: Sequelize.Transaction) {
91 const query = {
92 where: {
93 actorId
94 },
95 include: [
96 {
97 model: ActorModel,
98 required: true,
99 as: 'ActorFollower'
100 },
101 {
102 model: ActorModel,
103 required: true,
104 as: 'ActorFollowing',
105 include: [
106 {
107 model: ServerModel,
108 required: true,
109 where: {
110 host: targetHost
111 }
112 }
113 ]
114 }
115 ],
116 transaction: t
117 }
118
119 return ActorFollowModel.findOne(query)
120 }
121
122 static listFollowingForApi (id: number, start: number, count: number, sort: string) {
123 const query = {
124 distinct: true,
125 offset: start,
126 limit: count,
127 order: [ getSort(sort) ],
128 include: [
129 {
130 model: ActorModel,
131 required: true,
132 as: 'ActorFollower',
133 where: {
134 id
135 }
136 },
137 {
138 model: ActorModel,
139 as: 'ActorFollowing',
140 required: true,
141 include: [ ServerModel ]
142 }
143 ]
144 }
145
146 return ActorFollowModel.findAndCountAll(query)
147 .then(({ rows, count }) => {
148 return {
149 data: rows,
150 total: count
151 }
152 })
153 }
154
155 static listFollowersForApi (id: number, start: number, count: number, sort: string) {
156 const query = {
157 distinct: true,
158 offset: start,
159 limit: count,
160 order: [ getSort(sort) ],
161 include: [
162 {
163 model: ActorModel,
164 required: true,
165 as: 'ActorFollower',
166 include: [ ServerModel ]
167 },
168 {
169 model: ActorModel,
170 as: 'ActorFollowing',
171 required: true,
172 where: {
173 id
174 }
175 }
176 ]
177 }
178
179 return ActorFollowModel.findAndCountAll(query)
180 .then(({ rows, count }) => {
181 return {
182 data: rows,
183 total: count
184 }
185 })
186 }
187
188 static listAcceptedFollowerUrlsForApi (actorIds: number[], t: Sequelize.Transaction, start?: number, count?: number) {
189 return ActorFollowModel.createListAcceptedFollowForApiQuery('followers', actorIds, t, start, count)
190 }
191
192 static listAcceptedFollowerSharedInboxUrls (actorIds: number[], t: Sequelize.Transaction) {
ca309a9f 193 return ActorFollowModel.createListAcceptedFollowForApiQuery(
759f8a29 194 'followers',
ca309a9f
C
195 actorIds,
196 t,
197 undefined,
198 undefined,
759f8a29
C
199 'sharedInboxUrl',
200 true
ca309a9f 201 )
50d6de9c
C
202 }
203
204 static listAcceptedFollowingUrlsForApi (actorIds: number[], t: Sequelize.Transaction, start?: number, count?: number) {
205 return ActorFollowModel.createListAcceptedFollowForApiQuery('following', actorIds, t, start, count)
206 }
207
759f8a29
C
208 private static async createListAcceptedFollowForApiQuery (
209 type: 'followers' | 'following',
210 actorIds: number[],
211 t: Sequelize.Transaction,
212 start?: number,
213 count?: number,
214 columnUrl = 'url',
215 distinct = false
216 ) {
50d6de9c
C
217 let firstJoin: string
218 let secondJoin: string
219
220 if (type === 'followers') {
221 firstJoin = 'targetActorId'
222 secondJoin = 'actorId'
223 } else {
224 firstJoin = 'actorId'
225 secondJoin = 'targetActorId'
226 }
227
759f8a29
C
228 const selections: string[] = []
229 if (distinct === true) selections.push('DISTINCT("Follows"."' + columnUrl + '") AS "url"')
230 else selections.push('"Follows"."' + columnUrl + '" AS "url"')
231
232 selections.push('COUNT(*) AS "total"')
233
50d6de9c
C
234 const tasks: Bluebird<any>[] = []
235
759f8a29 236 for (let selection of selections) {
50d6de9c
C
237 let query = 'SELECT ' + selection + ' FROM "actor" ' +
238 'INNER JOIN "actorFollow" ON "actorFollow"."' + firstJoin + '" = "actor"."id" ' +
239 'INNER JOIN "actor" AS "Follows" ON "actorFollow"."' + secondJoin + '" = "Follows"."id" ' +
240 'WHERE "actor"."id" = ANY ($actorIds) AND "actorFollow"."state" = \'accepted\' '
241
242 if (count !== undefined) query += 'LIMIT ' + count
243 if (start !== undefined) query += ' OFFSET ' + start
244
245 const options = {
246 bind: { actorIds },
247 type: Sequelize.QueryTypes.SELECT,
248 transaction: t
249 }
250 tasks.push(ActorFollowModel.sequelize.query(query, options))
251 }
252
253 const [ followers, [ { total } ] ] = await
254 Promise.all(tasks)
255 const urls: string[] = followers.map(f => f.url)
256
257 return {
258 data: urls,
259 total: parseInt(total, 10)
260 }
261 }
262
263 toFormattedJSON () {
264 const follower = this.ActorFollower.toFormattedJSON()
265 const following = this.ActorFollowing.toFormattedJSON()
266
267 return {
268 id: this.id,
269 follower,
270 following,
271 state: this.state,
272 createdAt: this.createdAt,
273 updatedAt: this.updatedAt
274 }
275 }
276}