aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/activitypub
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/activitypub')
-rw-r--r--server/models/activitypub/actor-follow.ts79
-rw-r--r--server/models/activitypub/actor.ts13
2 files changed, 82 insertions, 10 deletions
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 5fcc3449d..78a65a0ff 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -1,8 +1,14 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { values } from 'lodash' 2import { values } from 'lodash'
3import * as Sequelize from 'sequelize' 3import * as Sequelize from 'sequelize'
4import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 4import {
5 AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, IsInt, Max, Model, Table,
6 UpdatedAt
7} from 'sequelize-typescript'
5import { FollowState } from '../../../shared/models/actors' 8import { FollowState } from '../../../shared/models/actors'
9import { AccountFollow } from '../../../shared/models/actors/follow.model'
10import { logger } from '../../helpers/logger'
11import { ACTOR_FOLLOW_SCORE } from '../../initializers'
6import { FOLLOW_STATES } from '../../initializers/constants' 12import { FOLLOW_STATES } from '../../initializers/constants'
7import { ServerModel } from '../server/server' 13import { ServerModel } from '../server/server'
8import { getSort } from '../utils' 14import { getSort } from '../utils'
@@ -20,6 +26,9 @@ import { ActorModel } from './actor'
20 { 26 {
21 fields: [ 'actorId', 'targetActorId' ], 27 fields: [ 'actorId', 'targetActorId' ],
22 unique: true 28 unique: true
29 },
30 {
31 fields: [ 'score' ]
23 } 32 }
24 ] 33 ]
25}) 34})
@@ -29,6 +38,13 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
29 @Column(DataType.ENUM(values(FOLLOW_STATES))) 38 @Column(DataType.ENUM(values(FOLLOW_STATES)))
30 state: FollowState 39 state: FollowState
31 40
41 @AllowNull(false)
42 @Default(ACTOR_FOLLOW_SCORE.BASE)
43 @IsInt
44 @Max(ACTOR_FOLLOW_SCORE.MAX)
45 @Column
46 score: number
47
32 @CreatedAt 48 @CreatedAt
33 createdAt: Date 49 createdAt: Date
34 50
@@ -63,6 +79,34 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
63 }) 79 })
64 ActorFollowing: ActorModel 80 ActorFollowing: ActorModel
65 81
82 // Remove actor follows with a score of 0 (too many requests where they were unreachable)
83 static async removeBadActorFollows () {
84 const actorFollows = await ActorFollowModel.listBadActorFollows()
85
86 const actorFollowsRemovePromises = actorFollows.map(actorFollow => actorFollow.destroy())
87 await Promise.all(actorFollowsRemovePromises)
88
89 const numberOfActorFollowsRemoved = actorFollows.length
90
91 if (numberOfActorFollowsRemoved) logger.info('Removed bad %d actor follows.', numberOfActorFollowsRemoved)
92 }
93
94 static updateActorFollowsScoreAndRemoveBadOnes (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction) {
95 if (goodInboxes.length === 0 && badInboxes.length === 0) return
96
97 logger.info('Updating %d good actor follows and %d bad actor follows scores.', goodInboxes.length, badInboxes.length)
98
99 if (goodInboxes.length !== 0) {
100 ActorFollowModel.incrementScores(goodInboxes, ACTOR_FOLLOW_SCORE.BONUS, t)
101 .catch(err => logger.error('Cannot increment scores of good actor follows.', err))
102 }
103
104 if (badInboxes.length !== 0) {
105 ActorFollowModel.incrementScores(badInboxes, ACTOR_FOLLOW_SCORE.PENALTY, t)
106 .catch(err => logger.error('Cannot decrement scores of bad actor follows.', err))
107 }
108 }
109
66 static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Sequelize.Transaction) { 110 static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Sequelize.Transaction) {
67 const query = { 111 const query = {
68 where: { 112 where: {
@@ -260,7 +304,37 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
260 } 304 }
261 } 305 }
262 306
263 toFormattedJSON () { 307 private static incrementScores (inboxUrls: string[], value: number, t: Sequelize.Transaction) {
308 const inboxUrlsString = inboxUrls.map(url => `'${url}'`).join(',')
309
310 const query = 'UPDATE "actorFollow" SET "score" = "score" +' + value + ' ' +
311 'WHERE id IN (' +
312 'SELECT "actorFollow"."id" FROM "actorFollow" ' +
313 'INNER JOIN "actor" ON "actor"."id" = "actorFollow"."actorId" ' +
314 'WHERE "actor"."inboxUrl" IN (' + inboxUrlsString + ') OR "actor"."sharedInboxUrl" IN (' + inboxUrlsString + ')' +
315 ')'
316
317 const options = {
318 type: Sequelize.QueryTypes.BULKUPDATE,
319 transaction: t
320 }
321
322 return ActorFollowModel.sequelize.query(query, options)
323 }
324
325 private static listBadActorFollows () {
326 const query = {
327 where: {
328 score: {
329 [Sequelize.Op.lte]: 0
330 }
331 }
332 }
333
334 return ActorFollowModel.findAll(query)
335 }
336
337 toFormattedJSON (): AccountFollow {
264 const follower = this.ActorFollower.toFormattedJSON() 338 const follower = this.ActorFollower.toFormattedJSON()
265 const following = this.ActorFollowing.toFormattedJSON() 339 const following = this.ActorFollowing.toFormattedJSON()
266 340
@@ -268,6 +342,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
268 id: this.id, 342 id: this.id,
269 follower, 343 follower,
270 following, 344 following,
345 score: this.score,
271 state: this.state, 346 state: this.state,
272 createdAt: this.createdAt, 347 createdAt: this.createdAt,
273 updatedAt: this.updatedAt 348 updatedAt: this.updatedAt
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts
index b88e06b41..912d8d748 100644
--- a/server/models/activitypub/actor.ts
+++ b/server/models/activitypub/actor.ts
@@ -204,7 +204,7 @@ export class ActorModel extends Model<ActorModel> {
204 VideoChannel: VideoChannelModel 204 VideoChannel: VideoChannelModel
205 205
206 static load (id: number) { 206 static load (id: number) {
207 return ActorModel.scope(ScopeNames.FULL).findById(id) 207 return ActorModel.unscoped().findById(id)
208 } 208 }
209 209
210 static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) { 210 static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) {
@@ -267,20 +267,17 @@ export class ActorModel extends Model<ActorModel> {
267 avatar = this.Avatar.toFormattedJSON() 267 avatar = this.Avatar.toFormattedJSON()
268 } 268 }
269 269
270 let score: number
271 if (this.Server) {
272 score = this.Server.score
273 }
274
275 return { 270 return {
276 id: this.id, 271 id: this.id,
277 url: this.url, 272 url: this.url,
278 uuid: this.uuid, 273 uuid: this.uuid,
274 name: this.preferredUsername,
279 host: this.getHost(), 275 host: this.getHost(),
280 score,
281 followingCount: this.followingCount, 276 followingCount: this.followingCount,
282 followersCount: this.followersCount, 277 followersCount: this.followersCount,
283 avatar 278 avatar,
279 createdAt: this.createdAt,
280 updatedAt: this.updatedAt
284 } 281 }
285 } 282 }
286 283