aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/notifier/shared/comment
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/comment
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/comment')
-rw-r--r--server/lib/notifier/shared/comment/comment-mention.ts111
-rw-r--r--server/lib/notifier/shared/comment/index.ts2
-rw-r--r--server/lib/notifier/shared/comment/new-comment-for-video-owner.ts76
3 files changed, 0 insertions, 189 deletions
diff --git a/server/lib/notifier/shared/comment/comment-mention.ts b/server/lib/notifier/shared/comment/comment-mention.ts
deleted file mode 100644
index 3074e97db..000000000
--- a/server/lib/notifier/shared/comment/comment-mention.ts
+++ /dev/null
@@ -1,111 +0,0 @@
1import { logger } from '@server/helpers/logger'
2import { toSafeHtml } from '@server/helpers/markdown'
3import { WEBSERVER } from '@server/initializers/constants'
4import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
5import { getServerActor } from '@server/models/application/application'
6import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
7import { UserModel } from '@server/models/user/user'
8import { UserNotificationModel } from '@server/models/user/user-notification'
9import {
10 MCommentOwnerVideo,
11 MUserDefault,
12 MUserNotifSettingAccount,
13 MUserWithNotificationSetting,
14 UserNotificationModelForApi
15} from '@server/types/models'
16import { UserNotificationSettingValue, UserNotificationType } from '@shared/models'
17import { AbstractNotification } from '../common'
18
19export class CommentMention extends AbstractNotification <MCommentOwnerVideo, MUserNotifSettingAccount> {
20 private users: MUserDefault[]
21
22 private serverAccountId: number
23
24 private accountMutedHash: { [ id: number ]: boolean }
25 private instanceMutedHash: { [ id: number ]: boolean }
26
27 async prepare () {
28 const extractedUsernames = this.payload.extractMentions()
29 logger.debug(
30 'Extracted %d username from comment %s.', extractedUsernames.length, this.payload.url,
31 { usernames: extractedUsernames, text: this.payload.text }
32 )
33
34 this.users = await UserModel.listByUsernames(extractedUsernames)
35
36 if (this.payload.Video.isOwned()) {
37 const userException = await UserModel.loadByVideoId(this.payload.videoId)
38 this.users = this.users.filter(u => u.id !== userException.id)
39 }
40
41 // Don't notify if I mentioned myself
42 this.users = this.users.filter(u => u.Account.id !== this.payload.accountId)
43
44 if (this.users.length === 0) return
45
46 this.serverAccountId = (await getServerActor()).Account.id
47
48 const sourceAccounts = this.users.map(u => u.Account.id).concat([ this.serverAccountId ])
49
50 this.accountMutedHash = await AccountBlocklistModel.isAccountMutedByAccounts(sourceAccounts, this.payload.accountId)
51 this.instanceMutedHash = await ServerBlocklistModel.isServerMutedByAccounts(sourceAccounts, this.payload.Account.Actor.serverId)
52 }
53
54 log () {
55 logger.info('Notifying %d users of new comment %s.', this.users.length, this.payload.url)
56 }
57
58 getSetting (user: MUserNotifSettingAccount) {
59 const accountId = user.Account.id
60 if (
61 this.accountMutedHash[accountId] === true || this.instanceMutedHash[accountId] === true ||
62 this.accountMutedHash[this.serverAccountId] === true || this.instanceMutedHash[this.serverAccountId] === true
63 ) {
64 return UserNotificationSettingValue.NONE
65 }
66
67 return user.NotificationSetting.commentMention
68 }
69
70 getTargetUsers () {
71 return this.users
72 }
73
74 createNotification (user: MUserWithNotificationSetting) {
75 const notification = UserNotificationModel.build<UserNotificationModelForApi>({
76 type: UserNotificationType.COMMENT_MENTION,
77 userId: user.id,
78 commentId: this.payload.id
79 })
80 notification.VideoComment = this.payload
81
82 return notification
83 }
84
85 createEmail (to: string) {
86 const comment = this.payload
87
88 const accountName = comment.Account.getDisplayName()
89 const video = comment.Video
90 const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath()
91 const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
92 const commentHtml = toSafeHtml(comment.text)
93
94 return {
95 template: 'video-comment-mention',
96 to,
97 subject: 'Mention on video ' + video.name,
98 locals: {
99 comment,
100 commentHtml,
101 video,
102 videoUrl,
103 accountName,
104 action: {
105 text: 'View comment',
106 url: commentUrl
107 }
108 }
109 }
110 }
111}
diff --git a/server/lib/notifier/shared/comment/index.ts b/server/lib/notifier/shared/comment/index.ts
deleted file mode 100644
index ae01a9646..000000000
--- a/server/lib/notifier/shared/comment/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
1export * from './comment-mention'
2export * from './new-comment-for-video-owner'
diff --git a/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts b/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts
deleted file mode 100644
index 4f96439a3..000000000
--- a/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts
+++ /dev/null
@@ -1,76 +0,0 @@
1import { logger } from '@server/helpers/logger'
2import { toSafeHtml } from '@server/helpers/markdown'
3import { WEBSERVER } from '@server/initializers/constants'
4import { isBlockedByServerOrAccount } from '@server/lib/blocklist'
5import { UserModel } from '@server/models/user/user'
6import { UserNotificationModel } from '@server/models/user/user-notification'
7import { MCommentOwnerVideo, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models'
8import { UserNotificationType } from '@shared/models'
9import { AbstractNotification } from '../common/abstract-notification'
10
11export class NewCommentForVideoOwner extends AbstractNotification <MCommentOwnerVideo> {
12 private user: MUserDefault
13
14 async prepare () {
15 this.user = await UserModel.loadByVideoId(this.payload.videoId)
16 }
17
18 log () {
19 logger.info('Notifying owner of a video %s of new comment %s.', this.user.username, this.payload.url)
20 }
21
22 isDisabled () {
23 if (this.payload.Video.isOwned() === false) return true
24
25 // Not our user or user comments its own video
26 if (!this.user || this.payload.Account.userId === this.user.id) return true
27
28 return isBlockedByServerOrAccount(this.payload.Account, this.user.Account)
29 }
30
31 getSetting (user: MUserWithNotificationSetting) {
32 return user.NotificationSetting.newCommentOnMyVideo
33 }
34
35 getTargetUsers () {
36 if (!this.user) return []
37
38 return [ this.user ]
39 }
40
41 createNotification (user: MUserWithNotificationSetting) {
42 const notification = UserNotificationModel.build<UserNotificationModelForApi>({
43 type: UserNotificationType.NEW_COMMENT_ON_MY_VIDEO,
44 userId: user.id,
45 commentId: this.payload.id
46 })
47 notification.VideoComment = this.payload
48
49 return notification
50 }
51
52 createEmail (to: string) {
53 const video = this.payload.Video
54 const videoUrl = WEBSERVER.URL + this.payload.Video.getWatchStaticPath()
55 const commentUrl = WEBSERVER.URL + this.payload.getCommentStaticPath()
56 const commentHtml = toSafeHtml(this.payload.text)
57
58 return {
59 template: 'video-comment-new',
60 to,
61 subject: 'New comment on your video ' + video.name,
62 locals: {
63 accountName: this.payload.Account.getDisplayName(),
64 accountUrl: this.payload.Account.Actor.url,
65 comment: this.payload,
66 commentHtml,
67 video,
68 videoUrl,
69 action: {
70 text: 'View comment',
71 url: commentUrl
72 }
73 }
74 }
75 }
76}