aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-08-06 17:19:53 +0200
committerChocobozzz <me@florianbigard.com>2019-08-06 17:26:51 +0200
commit6b9c966f6428c9e47bead3410a0401e8ebd744bf (patch)
tree282218ec56725b0e2e878b0471cd08a54fd91998 /server/models
parent466e3f20a537f1eff4b4fd03297df11ba371d049 (diff)
downloadPeerTube-6b9c966f6428c9e47bead3410a0401e8ebd744bf.tar.gz
PeerTube-6b9c966f6428c9e47bead3410a0401e8ebd744bf.tar.zst
PeerTube-6b9c966f6428c9e47bead3410a0401e8ebd744bf.zip
Automatically remove bad followings
Diffstat (limited to 'server/models')
-rw-r--r--server/models/account/account-video-rate.ts24
-rw-r--r--server/models/activitypub/actor-follow.ts26
-rw-r--r--server/models/utils.ts20
-rw-r--r--server/models/video/video-comment.ts38
-rw-r--r--server/models/video/video-share.ts18
5 files changed, 66 insertions, 60 deletions
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts
index d5c214ecb..4bd8114cf 100644
--- a/server/models/account/account-video-rate.ts
+++ b/server/models/account/account-video-rate.ts
@@ -6,7 +6,7 @@ import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constan
6import { VideoModel } from '../video/video' 6import { VideoModel } from '../video/video'
7import { AccountModel } from './account' 7import { AccountModel } from './account'
8import { ActorModel } from '../activitypub/actor' 8import { ActorModel } from '../activitypub/actor'
9import { getSort, throwIfNotValid } from '../utils' 9import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
10import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 10import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
11import { AccountVideoRate } from '../../../shared' 11import { AccountVideoRate } from '../../../shared'
12import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' 12import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
@@ -219,25 +219,11 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
219 [Op.lt]: beforeUpdatedAt 219 [Op.lt]: beforeUpdatedAt
220 }, 220 },
221 videoId, 221 videoId,
222 type 222 type,
223 }, 223 accountId: {
224 include: [ 224 [Op.notIn]: buildLocalAccountIdsIn()
225 {
226 model: AccountModel.unscoped(),
227 required: true,
228 include: [
229 {
230 model: ActorModel.unscoped(),
231 required: true,
232 where: {
233 serverId: {
234 [Op.ne]: null
235 }
236 }
237 }
238 ]
239 } 225 }
240 ], 226 },
241 transaction: t 227 transaction: t
242 } 228 }
243 229
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 3039b90c7..99a5fd117 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -23,7 +23,7 @@ import { logger } from '../../helpers/logger'
23import { getServerActor } from '../../helpers/utils' 23import { getServerActor } from '../../helpers/utils'
24import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES } from '../../initializers/constants' 24import { ACTOR_FOLLOW_SCORE, FOLLOW_STATES } from '../../initializers/constants'
25import { ServerModel } from '../server/server' 25import { ServerModel } from '../server/server'
26import { getSort } from '../utils' 26import { createSafeIn, getSort } from '../utils'
27import { ActorModel, unusedActorAttributesForAPI } from './actor' 27import { ActorModel, unusedActorAttributesForAPI } from './actor'
28import { VideoChannelModel } from '../video/video-channel' 28import { VideoChannelModel } from '../video/video-channel'
29import { AccountModel } from '../account/account' 29import { AccountModel } from '../account/account'
@@ -464,7 +464,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
464 } 464 }
465 } 465 }
466 466
467 static updateFollowScore (inboxUrl: string, value: number, t?: Transaction) { 467 static updateScore (inboxUrl: string, value: number, t?: Transaction) {
468 const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` + 468 const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` +
469 'WHERE id IN (' + 469 'WHERE id IN (' +
470 'SELECT "actorFollow"."id" FROM "actorFollow" ' + 470 'SELECT "actorFollow"."id" FROM "actorFollow" ' +
@@ -480,6 +480,28 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
480 return ActorFollowModel.sequelize.query(query, options) 480 return ActorFollowModel.sequelize.query(query, options)
481 } 481 }
482 482
483 static async updateScoreByFollowingServers (serverIds: number[], value: number, t?: Transaction) {
484 if (serverIds.length === 0) return
485
486 const me = await getServerActor()
487 const serverIdsString = createSafeIn(ActorFollowModel, serverIds)
488
489 const query = `UPDATE "actorFollow" SET "score" = "score" + ${value} ` +
490 'WHERE id IN (' +
491 'SELECT "actorFollow"."id" FROM "actorFollow" ' +
492 'INNER JOIN "actor" ON "actor"."id" = "actorFollow"."targetActorId" ' +
493 `WHERE "actorFollow"."actorId" = ${me.Account.actorId} ` + // I'm the follower
494 `AND "actor"."serverId" IN (${serverIdsString})` + // Criteria on followings
495 ')'
496
497 const options = {
498 type: QueryTypes.BULKUPDATE,
499 transaction: t
500 }
501
502 return ActorFollowModel.sequelize.query(query, options)
503 }
504
483 private static async createListAcceptedFollowForApiQuery ( 505 private static async createListAcceptedFollowForApiQuery (
484 type: 'followers' | 'following', 506 type: 'followers' | 'following',
485 actorIds: number[], 507 actorIds: number[],
diff --git a/server/models/utils.ts b/server/models/utils.ts
index 30de91e1d..24890f961 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -1,7 +1,7 @@
1import { Model, Sequelize } from 'sequelize-typescript' 1import { Model, Sequelize } from 'sequelize-typescript'
2import * as validator from 'validator' 2import * as validator from 'validator'
3import { Col } from 'sequelize/types/lib/utils' 3import { Col } from 'sequelize/types/lib/utils'
4import { OrderItem } from 'sequelize/types' 4import { OrderItem, literal } from 'sequelize'
5 5
6type SortType = { sortModel: any, sortValue: string } 6type SortType = { sortModel: any, sortValue: string }
7 7
@@ -129,16 +129,30 @@ function parseAggregateResult (result: any) {
129 return total 129 return total
130} 130}
131 131
132const createSafeIn = (model: typeof Model, stringArr: string[]) => { 132const createSafeIn = (model: typeof Model, stringArr: (string | number)[]) => {
133 return stringArr.map(t => model.sequelize.escape(t)) 133 return stringArr.map(t => model.sequelize.escape('' + t))
134 .join(', ') 134 .join(', ')
135} 135}
136 136
137function buildLocalAccountIdsIn () {
138 return literal(
139 '(SELECT "account"."id" FROM "account" INNER JOIN "actor" ON "actor"."id" = "account"."actorId" AND "actor"."serverId" IS NULL)'
140 )
141}
142
143function buildLocalActorIdsIn () {
144 return literal(
145 '(SELECT "actor"."id" FROM "actor" WHERE "actor"."serverId" IS NULL)'
146 )
147}
148
137// --------------------------------------------------------------------------- 149// ---------------------------------------------------------------------------
138 150
139export { 151export {
140 buildBlockedAccountSQL, 152 buildBlockedAccountSQL,
153 buildLocalActorIdsIn,
141 SortType, 154 SortType,
155 buildLocalAccountIdsIn,
142 getSort, 156 getSort,
143 getVideoSort, 157 getVideoSort,
144 getSortOnModel, 158 getSortOnModel,
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index 28e5818cd..6eda32f05 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -22,7 +22,7 @@ import { AccountModel } from '../account/account'
22import { ActorModel } from '../activitypub/actor' 22import { ActorModel } from '../activitypub/actor'
23import { AvatarModel } from '../avatar/avatar' 23import { AvatarModel } from '../avatar/avatar'
24import { ServerModel } from '../server/server' 24import { ServerModel } from '../server/server'
25import { buildBlockedAccountSQL, getSort, throwIfNotValid } from '../utils' 25import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
26import { VideoModel } from './video' 26import { VideoModel } from './video'
27import { VideoChannelModel } from './video-channel' 27import { VideoChannelModel } from './video-channel'
28import { getServerActor } from '../../helpers/utils' 28import { getServerActor } from '../../helpers/utils'
@@ -30,7 +30,7 @@ import { UserModel } from '../account/user'
30import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor' 30import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor'
31import { regexpCapture } from '../../helpers/regexp' 31import { regexpCapture } from '../../helpers/regexp'
32import { uniq } from 'lodash' 32import { uniq } from 'lodash'
33import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize' 33import { FindOptions, literal, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
34 34
35enum ScopeNames { 35enum ScopeNames {
36 WITH_ACCOUNT = 'WITH_ACCOUNT', 36 WITH_ACCOUNT = 'WITH_ACCOUNT',
@@ -281,16 +281,22 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
281 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT ]).findOne(query) 281 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT ]).findOne(query)
282 } 282 }
283 283
284 static loadByUrlAndPopulateReplyAndVideo (url: string, t?: Transaction) { 284 static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction) {
285 const query: FindOptions = { 285 const query: FindOptions = {
286 where: { 286 where: {
287 url 287 url
288 } 288 },
289 include: [
290 {
291 attributes: [ 'id', 'url' ],
292 model: VideoModel.unscoped()
293 }
294 ]
289 } 295 }
290 296
291 if (t !== undefined) query.transaction = t 297 if (t !== undefined) query.transaction = t
292 298
293 return VideoCommentModel.scope([ ScopeNames.WITH_IN_REPLY_TO, ScopeNames.WITH_VIDEO ]).findOne(query) 299 return VideoCommentModel.scope([ ScopeNames.WITH_IN_REPLY_TO, ScopeNames.WITH_ACCOUNT ]).findOne(query)
294 } 300 }
295 301
296 static async listThreadsForApi (parameters: { 302 static async listThreadsForApi (parameters: {
@@ -471,25 +477,11 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
471 updatedAt: { 477 updatedAt: {
472 [Op.lt]: beforeUpdatedAt 478 [Op.lt]: beforeUpdatedAt
473 }, 479 },
474 videoId 480 videoId,
475 }, 481 accountId: {
476 include: [ 482 [Op.notIn]: buildLocalAccountIdsIn()
477 {
478 required: true,
479 model: AccountModel.unscoped(),
480 include: [
481 {
482 required: true,
483 model: ActorModel.unscoped(),
484 where: {
485 serverId: {
486 [Op.ne]: null
487 }
488 }
489 }
490 ]
491 } 483 }
492 ] 484 }
493 } 485 }
494 486
495 return VideoCommentModel.destroy(query) 487 return VideoCommentModel.destroy(query)
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts
index 3bab3c027..d8ed64557 100644
--- a/server/models/video/video-share.ts
+++ b/server/models/video/video-share.ts
@@ -4,7 +4,7 @@ import { isActivityPubUrlValid } from '../../helpers/custom-validators/activityp
4import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 4import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
5import { AccountModel } from '../account/account' 5import { AccountModel } from '../account/account'
6import { ActorModel } from '../activitypub/actor' 6import { ActorModel } from '../activitypub/actor'
7import { throwIfNotValid } from '../utils' 7import { buildLocalActorIdsIn, throwIfNotValid } from '../utils'
8import { VideoModel } from './video' 8import { VideoModel } from './video'
9import { VideoChannelModel } from './video-channel' 9import { VideoChannelModel } from './video-channel'
10import { Op, Transaction } from 'sequelize' 10import { Op, Transaction } from 'sequelize'
@@ -207,19 +207,11 @@ export class VideoShareModel extends Model<VideoShareModel> {
207 updatedAt: { 207 updatedAt: {
208 [Op.lt]: beforeUpdatedAt 208 [Op.lt]: beforeUpdatedAt
209 }, 209 },
210 videoId 210 videoId,
211 }, 211 actorId: {
212 include: [ 212 [Op.notIn]: buildLocalActorIdsIn()
213 {
214 model: ActorModel.unscoped(),
215 required: true,
216 where: {
217 serverId: {
218 [ Op.ne ]: null
219 }
220 }
221 } 213 }
222 ] 214 }
223 } 215 }
224 216
225 return VideoShareModel.destroy(query) 217 return VideoShareModel.destroy(query)