aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/notifier/shared/follow
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/lib/notifier/shared/follow
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/lib/notifier/shared/follow')
-rw-r--r--server/lib/notifier/shared/follow/auto-follow-for-instance.ts51
-rw-r--r--server/lib/notifier/shared/follow/follow-for-instance.ts68
-rw-r--r--server/lib/notifier/shared/follow/follow-for-user.ts82
-rw-r--r--server/lib/notifier/shared/follow/index.ts3
4 files changed, 0 insertions, 204 deletions
diff --git a/server/lib/notifier/shared/follow/auto-follow-for-instance.ts b/server/lib/notifier/shared/follow/auto-follow-for-instance.ts
deleted file mode 100644
index ab9747ba8..000000000
--- a/server/lib/notifier/shared/follow/auto-follow-for-instance.ts
+++ /dev/null
@@ -1,51 +0,0 @@
1import { logger } from '@server/helpers/logger'
2import { UserModel } from '@server/models/user/user'
3import { UserNotificationModel } from '@server/models/user/user-notification'
4import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models'
5import { UserNotificationType, UserRight } from '@shared/models'
6import { AbstractNotification } from '../common/abstract-notification'
7
8export class AutoFollowForInstance extends AbstractNotification <MActorFollowFull> {
9 private admins: MUserDefault[]
10
11 async prepare () {
12 this.admins = await UserModel.listWithRight(UserRight.MANAGE_SERVER_FOLLOW)
13 }
14
15 log () {
16 logger.info('Notifying %d administrators of auto instance following: %s.', this.admins.length, this.actorFollow.ActorFollowing.url)
17 }
18
19 getSetting (user: MUserWithNotificationSetting) {
20 return user.NotificationSetting.autoInstanceFollowing
21 }
22
23 getTargetUsers () {
24 return this.admins
25 }
26
27 createNotification (user: MUserWithNotificationSetting) {
28 const notification = UserNotificationModel.build<UserNotificationModelForApi>({
29 type: UserNotificationType.AUTO_INSTANCE_FOLLOWING,
30 userId: user.id,
31 actorFollowId: this.actorFollow.id
32 })
33 notification.ActorFollow = this.actorFollow
34
35 return notification
36 }
37
38 createEmail (to: string) {
39 const instanceUrl = this.actorFollow.ActorFollowing.url
40
41 return {
42 to,
43 subject: 'Auto instance following',
44 text: `Your instance automatically followed a new instance: <a href="${instanceUrl}">${instanceUrl}</a>.`
45 }
46 }
47
48 private get actorFollow () {
49 return this.payload
50 }
51}
diff --git a/server/lib/notifier/shared/follow/follow-for-instance.ts b/server/lib/notifier/shared/follow/follow-for-instance.ts
deleted file mode 100644
index 777a12ef4..000000000
--- a/server/lib/notifier/shared/follow/follow-for-instance.ts
+++ /dev/null
@@ -1,68 +0,0 @@
1import { logger } from '@server/helpers/logger'
2import { WEBSERVER } from '@server/initializers/constants'
3import { isBlockedByServerOrAccount } from '@server/lib/blocklist'
4import { UserModel } from '@server/models/user/user'
5import { UserNotificationModel } from '@server/models/user/user-notification'
6import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models'
7import { UserNotificationType, UserRight } from '@shared/models'
8import { AbstractNotification } from '../common/abstract-notification'
9
10export class FollowForInstance extends AbstractNotification <MActorFollowFull> {
11 private admins: MUserDefault[]
12
13 async prepare () {
14 this.admins = await UserModel.listWithRight(UserRight.MANAGE_SERVER_FOLLOW)
15 }
16
17 isDisabled () {
18 const follower = Object.assign(this.actorFollow.ActorFollower.Account, { Actor: this.actorFollow.ActorFollower })
19
20 return isBlockedByServerOrAccount(follower)
21 }
22
23 log () {
24 logger.info('Notifying %d administrators of new instance follower: %s.', this.admins.length, this.actorFollow.ActorFollower.url)
25 }
26
27 getSetting (user: MUserWithNotificationSetting) {
28 return user.NotificationSetting.newInstanceFollower
29 }
30
31 getTargetUsers () {
32 return this.admins
33 }
34
35 createNotification (user: MUserWithNotificationSetting) {
36 const notification = UserNotificationModel.build<UserNotificationModelForApi>({
37 type: UserNotificationType.NEW_INSTANCE_FOLLOWER,
38 userId: user.id,
39 actorFollowId: this.actorFollow.id
40 })
41 notification.ActorFollow = this.actorFollow
42
43 return notification
44 }
45
46 createEmail (to: string) {
47 const awaitingApproval = this.actorFollow.state === 'pending'
48 ? ' awaiting manual approval.'
49 : ''
50
51 return {
52 to,
53 subject: 'New instance follower',
54 text: `Your instance has a new follower: ${this.actorFollow.ActorFollower.url}${awaitingApproval}.`,
55 locals: {
56 title: 'New instance follower',
57 action: {
58 text: 'Review followers',
59 url: WEBSERVER.URL + '/admin/follows/followers-list'
60 }
61 }
62 }
63 }
64
65 private get actorFollow () {
66 return this.payload
67 }
68}
diff --git a/server/lib/notifier/shared/follow/follow-for-user.ts b/server/lib/notifier/shared/follow/follow-for-user.ts
deleted file mode 100644
index 697c82cdd..000000000
--- a/server/lib/notifier/shared/follow/follow-for-user.ts
+++ /dev/null
@@ -1,82 +0,0 @@
1import { logger } from '@server/helpers/logger'
2import { isBlockedByServerOrAccount } from '@server/lib/blocklist'
3import { UserModel } from '@server/models/user/user'
4import { UserNotificationModel } from '@server/models/user/user-notification'
5import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models'
6import { UserNotificationType } from '@shared/models'
7import { AbstractNotification } from '../common/abstract-notification'
8
9export class FollowForUser extends AbstractNotification <MActorFollowFull> {
10 private followType: 'account' | 'channel'
11 private user: MUserDefault
12
13 async prepare () {
14 // Account follows one of our account?
15 this.followType = 'channel'
16 this.user = await UserModel.loadByChannelActorId(this.actorFollow.ActorFollowing.id)
17
18 // Account follows one of our channel?
19 if (!this.user) {
20 this.user = await UserModel.loadByAccountActorId(this.actorFollow.ActorFollowing.id)
21 this.followType = 'account'
22 }
23 }
24
25 async isDisabled () {
26 if (this.payload.ActorFollowing.isOwned() === false) return true
27
28 const followerAccount = this.actorFollow.ActorFollower.Account
29 const followerAccountWithActor = Object.assign(followerAccount, { Actor: this.actorFollow.ActorFollower })
30
31 return isBlockedByServerOrAccount(followerAccountWithActor, this.user.Account)
32 }
33
34 log () {
35 logger.info('Notifying user %s of new follower: %s.', this.user.username, this.actorFollow.ActorFollower.Account.getDisplayName())
36 }
37
38 getSetting (user: MUserWithNotificationSetting) {
39 return user.NotificationSetting.newFollow
40 }
41
42 getTargetUsers () {
43 if (!this.user) return []
44
45 return [ this.user ]
46 }
47
48 createNotification (user: MUserWithNotificationSetting) {
49 const notification = UserNotificationModel.build<UserNotificationModelForApi>({
50 type: UserNotificationType.NEW_FOLLOW,
51 userId: user.id,
52 actorFollowId: this.actorFollow.id
53 })
54 notification.ActorFollow = this.actorFollow
55
56 return notification
57 }
58
59 createEmail (to: string) {
60 const following = this.actorFollow.ActorFollowing
61 const follower = this.actorFollow.ActorFollower
62
63 const followingName = (following.VideoChannel || following.Account).getDisplayName()
64
65 return {
66 template: 'follower-on-channel',
67 to,
68 subject: `New follower on your channel ${followingName}`,
69 locals: {
70 followerName: follower.Account.getDisplayName(),
71 followerUrl: follower.url,
72 followingName,
73 followingUrl: following.url,
74 followType: this.followType
75 }
76 }
77 }
78
79 private get actorFollow () {
80 return this.payload
81 }
82}
diff --git a/server/lib/notifier/shared/follow/index.ts b/server/lib/notifier/shared/follow/index.ts
deleted file mode 100644
index 27f5289d9..000000000
--- a/server/lib/notifier/shared/follow/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
1export * from './auto-follow-for-instance'
2export * from './follow-for-instance'
3export * from './follow-for-user'