aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-07-09 16:23:01 +0200
committerChocobozzz <me@florianbigard.com>2021-07-20 15:27:18 +0200
commitdd0ebb715123dfa126a82d4e4fe3a04064ae77b8 (patch)
treee0741f35b31c66f09f7d9ad808b224ef86151bb1
parent9293139fde7091e9badcafa9b570b83cea9a10ad (diff)
downloadPeerTube-dd0ebb715123dfa126a82d4e4fe3a04064ae77b8.tar.gz
PeerTube-dd0ebb715123dfa126a82d4e4fe3a04064ae77b8.tar.zst
PeerTube-dd0ebb715123dfa126a82d4e4fe3a04064ae77b8.zip
Introduce notifications command
-rw-r--r--server/tests/api/check-params/contact-form.ts2
-rw-r--r--server/tests/api/check-params/video-comments.ts2
-rw-r--r--server/tests/api/moderation/blocklist-notification.ts47
-rw-r--r--server/tests/api/moderation/blocklist.ts28
-rw-r--r--server/tests/api/notifications/notifications-api.ts92
-rw-r--r--server/tests/api/notifications/user-notifications.ts5
-rw-r--r--server/tests/api/server/plugins.ts3
-rw-r--r--server/tests/api/videos/video-hls.ts1
-rw-r--r--server/tests/api/videos/video-nsfw.ts142
-rw-r--r--server/tools/test-live.ts2
-rw-r--r--shared/extra-utils/search/search-command.ts2
-rw-r--r--shared/extra-utils/server/servers.ts6
-rw-r--r--shared/extra-utils/shared/abstract-command.ts7
-rw-r--r--shared/extra-utils/users/index.ts3
-rw-r--r--shared/extra-utils/users/notifications-command.ts87
-rw-r--r--shared/extra-utils/users/notifications.ts (renamed from shared/extra-utils/users/user-notifications.ts)129
-rw-r--r--shared/extra-utils/videos/streaming-playlists-command.ts2
17 files changed, 279 insertions, 281 deletions
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts
index 5539266b8..4eed1661a 100644
--- a/server/tests/api/check-params/contact-form.ts
+++ b/server/tests/api/check-params/contact-form.ts
@@ -69,7 +69,7 @@ describe('Test contact form API validators', function () {
69 }) 69 })
70 70
71 it('Should accept a contact form with the correct parameters', async function () { 71 it('Should accept a contact form with the correct parameters', async function () {
72 await command.send({ ...defaultBody }) 72 await command.send(defaultBody)
73 }) 73 })
74 74
75 after(async function () { 75 after(async function () {
diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts
index ff94645cb..0f8c81392 100644
--- a/server/tests/api/check-params/video-comments.ts
+++ b/server/tests/api/check-params/video-comments.ts
@@ -278,7 +278,7 @@ describe('Test video comments API validator', function () {
278 let commentToDelete: number 278 let commentToDelete: number
279 279
280 { 280 {
281 const created = await server.commentsCommand.createThread({ videoId: video.uuid, text: 'hello' }) 281 const created = await server.commentsCommand.createThread({ videoId: video.uuid, token: userAccessToken, text: 'hello' })
282 commentToDelete = created.id 282 commentToDelete = created.id
283 } 283 }
284 284
diff --git a/server/tests/api/moderation/blocklist-notification.ts b/server/tests/api/moderation/blocklist-notification.ts
index a077d8739..b676a4db4 100644
--- a/server/tests/api/moderation/blocklist-notification.ts
+++ b/server/tests/api/moderation/blocklist-notification.ts
@@ -7,27 +7,22 @@ import {
7 createUser, 7 createUser,
8 doubleFollow, 8 doubleFollow,
9 flushAndRunMultipleServers, 9 flushAndRunMultipleServers,
10 getUserNotifications,
11 markAsReadAllNotifications,
12 ServerInfo, 10 ServerInfo,
13 setAccessTokensToServers, 11 setAccessTokensToServers,
14 uploadVideo, 12 uploadVideo,
15 userLogin, 13 userLogin,
16 waitJobs 14 waitJobs
17} from '@shared/extra-utils' 15} from '@shared/extra-utils'
18import { UserNotification, UserNotificationType } from '@shared/models' 16import { UserNotificationType } from '@shared/models'
19 17
20const expect = chai.expect 18const expect = chai.expect
21 19
22async function checkNotifications (url: string, token: string, expected: UserNotificationType[]) { 20async function checkNotifications (server: ServerInfo, token: string, expected: UserNotificationType[]) {
23 const res = await getUserNotifications(url, token, 0, 10, true) 21 const { data } = await server.notificationsCommand.list({ token, start: 0, count: 10, unread: true })
24 22 expect(data).to.have.lengthOf(expected.length)
25 const notifications: UserNotification[] = res.body.data
26
27 expect(notifications).to.have.lengthOf(expected.length)
28 23
29 for (const type of expected) { 24 for (const type of expected) {
30 expect(notifications.find(n => n.type === type)).to.exist 25 expect(data.find(n => n.type === type)).to.exist
31 } 26 }
32} 27}
33 28
@@ -47,8 +42,8 @@ describe('Test blocklist', function () {
47 42
48 await waitJobs(servers) 43 await waitJobs(servers)
49 44
50 await markAsReadAllNotifications(servers[0].url, userToken1) 45 await servers[0].notificationsCommand.markAsReadAll({ token: userToken1 })
51 await markAsReadAllNotifications(servers[0].url, userToken2) 46 await servers[0].notificationsCommand.markAsReadAll({ token: userToken2 })
52 47
53 { 48 {
54 const res = await uploadVideo(servers[0].url, userToken1, { name: 'video' }) 49 const res = await uploadVideo(servers[0].url, userToken1, { name: 'video' })
@@ -122,7 +117,7 @@ describe('Test blocklist', function () {
122 117
123 it('Should have appropriate notifications', async function () { 118 it('Should have appropriate notifications', async function () {
124 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ] 119 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
125 await checkNotifications(servers[0].url, userToken1, notifs) 120 await checkNotifications(servers[0], userToken1, notifs)
126 }) 121 })
127 122
128 it('Should block an account', async function () { 123 it('Should block an account', async function () {
@@ -133,13 +128,13 @@ describe('Test blocklist', function () {
133 }) 128 })
134 129
135 it('Should not have notifications from this account', async function () { 130 it('Should not have notifications from this account', async function () {
136 await checkNotifications(servers[0].url, userToken1, []) 131 await checkNotifications(servers[0], userToken1, [])
137 }) 132 })
138 133
139 it('Should have notifications of this account on user 2', async function () { 134 it('Should have notifications of this account on user 2', async function () {
140 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ] 135 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
141 136
142 await checkNotifications(servers[0].url, userToken2, notifs) 137 await checkNotifications(servers[0], userToken2, notifs)
143 138
144 await servers[0].blocklistCommand.removeFromMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host }) 139 await servers[0].blocklistCommand.removeFromMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host })
145 }) 140 })
@@ -155,7 +150,7 @@ describe('Test blocklist', function () {
155 150
156 it('Should have appropriate notifications', async function () { 151 it('Should have appropriate notifications', async function () {
157 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ] 152 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
158 await checkNotifications(servers[0].url, userToken1, notifs) 153 await checkNotifications(servers[0], userToken1, notifs)
159 }) 154 })
160 155
161 it('Should block an account', async function () { 156 it('Should block an account', async function () {
@@ -166,13 +161,13 @@ describe('Test blocklist', function () {
166 }) 161 })
167 162
168 it('Should not have notifications from this account', async function () { 163 it('Should not have notifications from this account', async function () {
169 await checkNotifications(servers[0].url, userToken1, []) 164 await checkNotifications(servers[0], userToken1, [])
170 }) 165 })
171 166
172 it('Should have notifications of this account on user 2', async function () { 167 it('Should have notifications of this account on user 2', async function () {
173 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ] 168 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
174 169
175 await checkNotifications(servers[0].url, userToken2, notifs) 170 await checkNotifications(servers[0], userToken2, notifs)
176 171
177 await servers[0].blocklistCommand.removeFromMyBlocklist({ token: userToken1, server: servers[1].host }) 172 await servers[0].blocklistCommand.removeFromMyBlocklist({ token: userToken1, server: servers[1].host })
178 }) 173 })
@@ -189,12 +184,12 @@ describe('Test blocklist', function () {
189 it('Should have appropriate notifications', async function () { 184 it('Should have appropriate notifications', async function () {
190 { 185 {
191 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ] 186 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
192 await checkNotifications(servers[0].url, userToken1, notifs) 187 await checkNotifications(servers[0], userToken1, notifs)
193 } 188 }
194 189
195 { 190 {
196 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ] 191 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
197 await checkNotifications(servers[0].url, userToken2, notifs) 192 await checkNotifications(servers[0], userToken2, notifs)
198 } 193 }
199 }) 194 })
200 195
@@ -206,8 +201,8 @@ describe('Test blocklist', function () {
206 }) 201 })
207 202
208 it('Should not have notifications from this account', async function () { 203 it('Should not have notifications from this account', async function () {
209 await checkNotifications(servers[0].url, userToken1, []) 204 await checkNotifications(servers[0], userToken1, [])
210 await checkNotifications(servers[0].url, userToken2, []) 205 await checkNotifications(servers[0], userToken2, [])
211 206
212 await servers[0].blocklistCommand.removeFromServerBlocklist({ account: 'user3@' + servers[1].host }) 207 await servers[0].blocklistCommand.removeFromServerBlocklist({ account: 'user3@' + servers[1].host })
213 }) 208 })
@@ -224,12 +219,12 @@ describe('Test blocklist', function () {
224 it('Should have appropriate notifications', async function () { 219 it('Should have appropriate notifications', async function () {
225 { 220 {
226 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ] 221 const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
227 await checkNotifications(servers[0].url, userToken1, notifs) 222 await checkNotifications(servers[0], userToken1, notifs)
228 } 223 }
229 224
230 { 225 {
231 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ] 226 const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
232 await checkNotifications(servers[0].url, userToken2, notifs) 227 await checkNotifications(servers[0], userToken2, notifs)
233 } 228 }
234 }) 229 })
235 230
@@ -241,8 +236,8 @@ describe('Test blocklist', function () {
241 }) 236 })
242 237
243 it('Should not have notifications from this account', async function () { 238 it('Should not have notifications from this account', async function () {
244 await checkNotifications(servers[0].url, userToken1, []) 239 await checkNotifications(servers[0], userToken1, [])
245 await checkNotifications(servers[0].url, userToken2, []) 240 await checkNotifications(servers[0], userToken2, [])
246 }) 241 })
247 }) 242 })
248 243
diff --git a/server/tests/api/moderation/blocklist.ts b/server/tests/api/moderation/blocklist.ts
index 00cb6c65c..44e3de4e4 100644
--- a/server/tests/api/moderation/blocklist.ts
+++ b/server/tests/api/moderation/blocklist.ts
@@ -9,7 +9,6 @@ import {
9 createUser, 9 createUser,
10 doubleFollow, 10 doubleFollow,
11 flushAndRunMultipleServers, 11 flushAndRunMultipleServers,
12 getUserNotifications,
13 getVideosList, 12 getVideosList,
14 getVideosListWithToken, 13 getVideosListWithToken,
15 ServerInfo, 14 ServerInfo,
@@ -18,7 +17,7 @@ import {
18 userLogin, 17 userLogin,
19 waitJobs 18 waitJobs
20} from '@shared/extra-utils' 19} from '@shared/extra-utils'
21import { UserNotification, UserNotificationType, Video } from '@shared/models' 20import { UserNotificationType, Video } from '@shared/models'
22 21
23const expect = chai.expect 22const expect = chai.expect
24 23
@@ -59,9 +58,8 @@ async function checkCommentNotification (
59 58
60 await waitJobs([ mainServer, comment.server ]) 59 await waitJobs([ mainServer, comment.server ])
61 60
62 const res = await getUserNotifications(mainServer.url, mainServer.accessToken, 0, 30) 61 const { data } = await mainServer.notificationsCommand.list({ start: 0, count: 30 })
63 const commentNotifications = (res.body.data as UserNotification[]) 62 const commentNotifications = data.filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
64 .filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
65 63
66 if (check === 'presence') expect(commentNotifications).to.have.lengthOf(1) 64 if (check === 'presence') expect(commentNotifications).to.have.lengthOf(1)
67 else expect(commentNotifications).to.have.lengthOf(0) 65 else expect(commentNotifications).to.have.lengthOf(0)
@@ -710,12 +708,10 @@ describe('Test blocklist', function () {
710 708
711 await waitJobs(servers) 709 await waitJobs(servers)
712 710
713 const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30) 711 const { data } = await servers[0].notificationsCommand.list({ start: 0, count: 30 })
714 const commentNotifications = (res.body.data as UserNotification[]) 712 const commentNotifications = data.filter(n => {
715 .filter(n => { 713 return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
716 return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && 714 })
717 n.createdAt >= now.toISOString()
718 })
719 715
720 expect(commentNotifications).to.have.lengthOf(0) 716 expect(commentNotifications).to.have.lengthOf(0)
721 } 717 }
@@ -773,12 +769,10 @@ describe('Test blocklist', function () {
773 769
774 await waitJobs(servers) 770 await waitJobs(servers)
775 771
776 const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30) 772 const { data } = await servers[0].notificationsCommand.list({ start: 0, count: 30 })
777 const commentNotifications = (res.body.data as UserNotification[]) 773 const commentNotifications = data.filter(n => {
778 .filter(n => { 774 return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
779 return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && 775 })
780 n.createdAt >= now.toISOString()
781 })
782 776
783 expect(commentNotifications).to.have.lengthOf(1) 777 expect(commentNotifications).to.have.lengthOf(1)
784 } 778 }
diff --git a/server/tests/api/notifications/notifications-api.ts b/server/tests/api/notifications/notifications-api.ts
index 1ed98ae7a..447492c5f 100644
--- a/server/tests/api/notifications/notifications-api.ts
+++ b/server/tests/api/notifications/notifications-api.ts
@@ -8,14 +8,10 @@ import {
8 cleanupTests, 8 cleanupTests,
9 getAllNotificationsSettings, 9 getAllNotificationsSettings,
10 getMyUserInformation, 10 getMyUserInformation,
11 getUserNotifications,
12 immutableAssign, 11 immutableAssign,
13 markAsReadAllNotifications,
14 markAsReadNotifications,
15 MockSmtpServer, 12 MockSmtpServer,
16 prepareNotificationsTest, 13 prepareNotificationsTest,
17 ServerInfo, 14 ServerInfo,
18 updateMyNotificationSettings,
19 uploadRandomVideo, 15 uploadRandomVideo,
20 waitJobs 16 waitJobs
21} from '@shared/extra-utils' 17} from '@shared/extra-utils'
@@ -26,7 +22,7 @@ const expect = chai.expect
26describe('Test notifications API', function () { 22describe('Test notifications API', function () {
27 let server: ServerInfo 23 let server: ServerInfo
28 let userNotifications: UserNotification[] = [] 24 let userNotifications: UserNotification[] = []
29 let userAccessToken: string 25 let userToken: string
30 let emails: object[] = [] 26 let emails: object[] = []
31 27
32 before(async function () { 28 before(async function () {
@@ -34,11 +30,11 @@ describe('Test notifications API', function () {
34 30
35 const res = await prepareNotificationsTest(1) 31 const res = await prepareNotificationsTest(1)
36 emails = res.emails 32 emails = res.emails
37 userAccessToken = res.userAccessToken 33 userToken = res.userAccessToken
38 userNotifications = res.userNotifications 34 userNotifications = res.userNotifications
39 server = res.servers[0] 35 server = res.servers[0]
40 36
41 await server.subscriptionsCommand.add({ token: userAccessToken, targetUri: 'root_channel@localhost:' + server.port }) 37 await server.subscriptionsCommand.add({ token: userToken, targetUri: 'root_channel@localhost:' + server.port })
42 38
43 for (let i = 0; i < 10; i++) { 39 for (let i = 0; i < 10; i++) {
44 await uploadRandomVideo(server, false) 40 await uploadRandomVideo(server, false)
@@ -50,49 +46,46 @@ describe('Test notifications API', function () {
50 describe('Mark as read', function () { 46 describe('Mark as read', function () {
51 47
52 it('Should mark as read some notifications', async function () { 48 it('Should mark as read some notifications', async function () {
53 const res = await getUserNotifications(server.url, userAccessToken, 2, 3) 49 const { data } = await server.notificationsCommand.list({ token: userToken, start: 2, count: 3 })
54 const ids = res.body.data.map(n => n.id) 50 const ids = data.map(n => n.id)
55 51
56 await markAsReadNotifications(server.url, userAccessToken, ids) 52 await server.notificationsCommand.markAsRead({ token: userToken, ids })
57 }) 53 })
58 54
59 it('Should have the notifications marked as read', async function () { 55 it('Should have the notifications marked as read', async function () {
60 const res = await getUserNotifications(server.url, userAccessToken, 0, 10) 56 const { data } = await server.notificationsCommand.list({ token: userToken, start: 0, count: 10 })
61 57
62 const notifications = res.body.data as UserNotification[] 58 expect(data[0].read).to.be.false
63 expect(notifications[0].read).to.be.false 59 expect(data[1].read).to.be.false
64 expect(notifications[1].read).to.be.false 60 expect(data[2].read).to.be.true
65 expect(notifications[2].read).to.be.true 61 expect(data[3].read).to.be.true
66 expect(notifications[3].read).to.be.true 62 expect(data[4].read).to.be.true
67 expect(notifications[4].read).to.be.true 63 expect(data[5].read).to.be.false
68 expect(notifications[5].read).to.be.false
69 }) 64 })
70 65
71 it('Should only list read notifications', async function () { 66 it('Should only list read notifications', async function () {
72 const res = await getUserNotifications(server.url, userAccessToken, 0, 10, false) 67 const { data } = await server.notificationsCommand.list({ token: userToken, start: 0, count: 10, unread: false })
73 68
74 const notifications = res.body.data as UserNotification[] 69 for (const notification of data) {
75 for (const notification of notifications) {
76 expect(notification.read).to.be.true 70 expect(notification.read).to.be.true
77 } 71 }
78 }) 72 })
79 73
80 it('Should only list unread notifications', async function () { 74 it('Should only list unread notifications', async function () {
81 const res = await getUserNotifications(server.url, userAccessToken, 0, 10, true) 75 const { data } = await server.notificationsCommand.list({ token: userToken, start: 0, count: 10, unread: true })
82 76
83 const notifications = res.body.data as UserNotification[] 77 for (const notification of data) {
84 for (const notification of notifications) {
85 expect(notification.read).to.be.false 78 expect(notification.read).to.be.false
86 } 79 }
87 }) 80 })
88 81
89 it('Should mark as read all notifications', async function () { 82 it('Should mark as read all notifications', async function () {
90 await markAsReadAllNotifications(server.url, userAccessToken) 83 await server.notificationsCommand.markAsReadAll({ token: userToken })
91 84
92 const res = await getUserNotifications(server.url, userAccessToken, 0, 10, true) 85 const body = await server.notificationsCommand.list({ token: userToken, start: 0, count: 10, unread: true })
93 86
94 expect(res.body.total).to.equal(0) 87 expect(body.total).to.equal(0)
95 expect(res.body.data).to.have.lengthOf(0) 88 expect(body.data).to.have.lengthOf(0)
96 }) 89 })
97 }) 90 })
98 91
@@ -104,19 +97,20 @@ describe('Test notifications API', function () {
104 server: server, 97 server: server,
105 emails, 98 emails,
106 socketNotifications: userNotifications, 99 socketNotifications: userNotifications,
107 token: userAccessToken 100 token: userToken
108 } 101 }
109 }) 102 })
110 103
111 it('Should not have notifications', async function () { 104 it('Should not have notifications', async function () {
112 this.timeout(20000) 105 this.timeout(20000)
113 106
114 await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), { 107 await server.notificationsCommand.updateMySettings({
115 newVideoFromSubscription: UserNotificationSettingValue.NONE 108 token: userToken,
116 })) 109 settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.NONE }
110 })
117 111
118 { 112 {
119 const res = await getMyUserInformation(server.url, userAccessToken) 113 const res = await getMyUserInformation(server.url, userToken)
120 const info = res.body as User 114 const info = res.body as User
121 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE) 115 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE)
122 } 116 }
@@ -130,12 +124,13 @@ describe('Test notifications API', function () {
130 it('Should only have web notifications', async function () { 124 it('Should only have web notifications', async function () {
131 this.timeout(20000) 125 this.timeout(20000)
132 126
133 await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), { 127 await server.notificationsCommand.updateMySettings({
134 newVideoFromSubscription: UserNotificationSettingValue.WEB 128 token: userToken,
135 })) 129 settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.WEB }
130 })
136 131
137 { 132 {
138 const res = await getMyUserInformation(server.url, userAccessToken) 133 const res = await getMyUserInformation(server.url, userToken)
139 const info = res.body as User 134 const info = res.body as User
140 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB) 135 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB)
141 } 136 }
@@ -156,12 +151,13 @@ describe('Test notifications API', function () {
156 it('Should only have mail notifications', async function () { 151 it('Should only have mail notifications', async function () {
157 this.timeout(20000) 152 this.timeout(20000)
158 153
159 await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), { 154 await server.notificationsCommand.updateMySettings({
160 newVideoFromSubscription: UserNotificationSettingValue.EMAIL 155 token: userToken,
161 })) 156 settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.EMAIL }
157 })
162 158
163 { 159 {
164 const res = await getMyUserInformation(server.url, userAccessToken) 160 const res = await getMyUserInformation(server.url, userToken)
165 const info = res.body as User 161 const info = res.body as User
166 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL) 162 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL)
167 } 163 }
@@ -182,12 +178,16 @@ describe('Test notifications API', function () {
182 it('Should have email and web notifications', async function () { 178 it('Should have email and web notifications', async function () {
183 this.timeout(20000) 179 this.timeout(20000)
184 180
185 await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), { 181 await server.notificationsCommand.updateMySettings({
186 newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL 182 token: userToken,
187 })) 183 settings: {
184 ...getAllNotificationsSettings(),
185 newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
186 }
187 })
188 188
189 { 189 {
190 const res = await getMyUserInformation(server.url, userAccessToken) 190 const res = await getMyUserInformation(server.url, userToken)
191 const info = res.body as User 191 const info = res.body as User
192 expect(info.notificationSettings.newVideoFromSubscription).to.equal( 192 expect(info.notificationSettings.newVideoFromSubscription).to.equal(
193 UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL 193 UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
diff --git a/server/tests/api/notifications/user-notifications.ts b/server/tests/api/notifications/user-notifications.ts
index 1d159c48f..4b31edf25 100644
--- a/server/tests/api/notifications/user-notifications.ts
+++ b/server/tests/api/notifications/user-notifications.ts
@@ -10,7 +10,6 @@ import {
10 checkNewVideoFromSubscription, 10 checkNewVideoFromSubscription,
11 checkVideoIsPublished, 11 checkVideoIsPublished,
12 cleanupTests, 12 cleanupTests,
13 getLastNotification,
14 ImportsCommand, 13 ImportsCommand,
15 MockSmtpServer, 14 MockSmtpServer,
16 prepareNotificationsTest, 15 prepareNotificationsTest,
@@ -64,7 +63,7 @@ describe('Test user notifications', function () {
64 63
65 await uploadRandomVideoOnServers(servers, 1) 64 await uploadRandomVideoOnServers(servers, 1)
66 65
67 const notification = await getLastNotification(servers[0].url, userAccessToken) 66 const notification = await servers[0].notificationsCommand.getLastest({ token: userAccessToken })
68 expect(notification).to.be.undefined 67 expect(notification).to.be.undefined
69 68
70 expect(emails).to.have.lengthOf(0) 69 expect(emails).to.have.lengthOf(0)
@@ -245,7 +244,7 @@ describe('Test user notifications', function () {
245 await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: false }) 244 await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: false })
246 await waitJobs(servers) 245 await waitJobs(servers)
247 246
248 const notification = await getLastNotification(servers[0].url, userAccessToken) 247 const notification = await servers[0].notificationsCommand.getLastest({ token: userAccessToken })
249 if (notification) { 248 if (notification) {
250 expect(notification.type).to.not.equal(UserNotificationType.MY_VIDEO_PUBLISHED) 249 expect(notification.type).to.not.equal(UserNotificationType.MY_VIDEO_PUBLISHED)
251 } 250 }
diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts
index 655cf00fa..d4a43276f 100644
--- a/server/tests/api/server/plugins.ts
+++ b/server/tests/api/server/plugins.ts
@@ -146,13 +146,12 @@ describe('Test plugins', function () {
146 } 146 }
147 147
148 { 148 {
149 const body = await command.list({ 149 const { data } = await command.list({
150 count: 2, 150 count: 2,
151 start: 0, 151 start: 0,
152 sort: 'name' 152 sort: 'name'
153 }) 153 })
154 154
155 const data = body
156 expect(data[0].name).to.equal('background-red') 155 expect(data[0].name).to.equal('background-red')
157 expect(data[1].name).to.equal('hello-world') 156 expect(data[1].name).to.equal('hello-world')
158 } 157 }
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts
index 3dd8c9066..428e1316d 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/videos/video-hls.ts
@@ -109,6 +109,7 @@ describe('Test HLS videos', function () {
109 let videoAudioUUID = '' 109 let videoAudioUUID = ''
110 110
111 function runTestSuite (hlsOnly: boolean) { 111 function runTestSuite (hlsOnly: boolean) {
112
112 it('Should upload a video and transcode it to HLS', async function () { 113 it('Should upload a video and transcode it to HLS', async function () {
113 this.timeout(120000) 114 this.timeout(120000)
114 115
diff --git a/server/tests/api/videos/video-nsfw.ts b/server/tests/api/videos/video-nsfw.ts
index 65813517d..5f30939cc 100644
--- a/server/tests/api/videos/video-nsfw.ts
+++ b/server/tests/api/videos/video-nsfw.ts
@@ -18,13 +18,13 @@ import {
18 uploadVideo, 18 uploadVideo,
19 userLogin 19 userLogin
20} from '@shared/extra-utils' 20} from '@shared/extra-utils'
21import { BooleanBothQuery, CustomConfig, User, VideosOverview } from '@shared/models' 21import { BooleanBothQuery, CustomConfig, ResultList, User, Video, VideosOverview } from '@shared/models'
22 22
23const expect = chai.expect 23const expect = chai.expect
24 24
25function createOverviewRes (overview: VideosOverview) { 25function createOverviewRes (overview: VideosOverview) {
26 const videos = overview.categories[0].videos 26 const videos = overview.categories[0].videos
27 return { body: { data: videos, total: videos.length } } 27 return { data: videos, total: videos.length }
28} 28}
29 29
30describe('Test video NSFW policy', function () { 30describe('Test video NSFW policy', function () {
@@ -32,49 +32,47 @@ describe('Test video NSFW policy', function () {
32 let userAccessToken: string 32 let userAccessToken: string
33 let customConfig: CustomConfig 33 let customConfig: CustomConfig
34 34
35 function getVideosFunctions (token?: string, query: { nsfw?: BooleanBothQuery } = {}) { 35 async function getVideosFunctions (token?: string, query: { nsfw?: BooleanBothQuery } = {}) {
36 return getMyUserInformation(server.url, server.accessToken) 36 const res = await getMyUserInformation(server.url, server.accessToken)
37 .then(res => { 37 const user: User = res.body
38 const user: User = res.body 38 const videoChannelName = user.videoChannels[0].name
39 const videoChannelName = user.videoChannels[0].name 39 const accountName = user.account.name + '@' + user.account.host
40 const accountName = user.account.name + '@' + user.account.host 40 const hasQuery = Object.keys(query).length !== 0
41 const hasQuery = Object.keys(query).length !== 0 41 let promises: Promise<ResultList<Video>>[]
42 let promises: Promise<any>[] 42
43 43 if (token) {
44 if (token) { 44 promises = [
45 promises = [ 45 getVideosListWithToken(server.url, token, query).then(res => res.body),
46 getVideosListWithToken(server.url, token, query), 46 server.searchCommand.advancedVideoSearch({ token, search: { search: 'n', ...query } }),
47 server.searchCommand.advancedVideoSearch({ token, search: { search: 'n', ...query } }), 47 getAccountVideos(server.url, token, accountName, 0, 5, undefined, query).then(res => res.body),
48 getAccountVideos(server.url, token, accountName, 0, 5, undefined, query), 48 getVideoChannelVideos(server.url, token, videoChannelName, 0, 5, undefined, query).then(res => res.body)
49 getVideoChannelVideos(server.url, token, videoChannelName, 0, 5, undefined, query) 49 ]
50 ] 50
51 51 // Overviews do not support video filters
52 // Overviews do not support video filters 52 if (!hasQuery) {
53 if (!hasQuery) { 53 const p = server.overviewsCommand.getVideos({ page: 1, token })
54 const p = server.overviewsCommand.getVideos({ page: 1, token }) 54 .then(res => createOverviewRes(res))
55 .then(res => createOverviewRes(res)) 55 promises.push(p)
56 promises.push(p) 56 }
57 } 57
58 58 return Promise.all(promises)
59 return Promise.all(promises) 59 }
60 } 60
61 61 promises = [
62 promises = [ 62 getVideosList(server.url).then(res => res.body),
63 getVideosList(server.url), 63 server.searchCommand.searchVideos({ search: 'n' }),
64 server.searchCommand.searchVideos({ search: 'n' }), 64 getAccountVideos(server.url, undefined, accountName, 0, 5).then(res => res.body),
65 getAccountVideos(server.url, undefined, accountName, 0, 5), 65 getVideoChannelVideos(server.url, undefined, videoChannelName, 0, 5).then(res => res.body)
66 getVideoChannelVideos(server.url, undefined, videoChannelName, 0, 5) 66 ]
67 ] 67
68 68 // Overviews do not support video filters
69 // Overviews do not support video filters 69 if (!hasQuery) {
70 if (!hasQuery) { 70 const p = server.overviewsCommand.getVideos({ page: 1 })
71 const p = server.overviewsCommand.getVideos({ page: 1 }) 71 .then(res => createOverviewRes(res))
72 .then(res => createOverviewRes(res)) 72 promises.push(p)
73 promises.push(p) 73 }
74 } 74
75 75 return Promise.all(promises)
76 return Promise.all(promises)
77 })
78 } 76 }
79 77
80 before(async function () { 78 before(async function () {
@@ -102,10 +100,10 @@ describe('Test video NSFW policy', function () {
102 const serverConfig = await server.configCommand.getConfig() 100 const serverConfig = await server.configCommand.getConfig()
103 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('display') 101 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('display')
104 102
105 for (const res of await getVideosFunctions()) { 103 for (const body of await getVideosFunctions()) {
106 expect(res.body.total).to.equal(2) 104 expect(body.total).to.equal(2)
107 105
108 const videos = res.body.data 106 const videos = body.data
109 expect(videos).to.have.lengthOf(2) 107 expect(videos).to.have.lengthOf(2)
110 expect(videos[0].name).to.equal('normal') 108 expect(videos[0].name).to.equal('normal')
111 expect(videos[1].name).to.equal('nsfw') 109 expect(videos[1].name).to.equal('nsfw')
@@ -119,10 +117,10 @@ describe('Test video NSFW policy', function () {
119 const serverConfig = await server.configCommand.getConfig() 117 const serverConfig = await server.configCommand.getConfig()
120 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('do_not_list') 118 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('do_not_list')
121 119
122 for (const res of await getVideosFunctions()) { 120 for (const body of await getVideosFunctions()) {
123 expect(res.body.total).to.equal(1) 121 expect(body.total).to.equal(1)
124 122
125 const videos = res.body.data 123 const videos = body.data
126 expect(videos).to.have.lengthOf(1) 124 expect(videos).to.have.lengthOf(1)
127 expect(videos[0].name).to.equal('normal') 125 expect(videos[0].name).to.equal('normal')
128 } 126 }
@@ -135,10 +133,10 @@ describe('Test video NSFW policy', function () {
135 const serverConfig = await server.configCommand.getConfig() 133 const serverConfig = await server.configCommand.getConfig()
136 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('blur') 134 expect(serverConfig.instance.defaultNSFWPolicy).to.equal('blur')
137 135
138 for (const res of await getVideosFunctions()) { 136 for (const body of await getVideosFunctions()) {
139 expect(res.body.total).to.equal(2) 137 expect(body.total).to.equal(2)
140 138
141 const videos = res.body.data 139 const videos = body.data
142 expect(videos).to.have.lengthOf(2) 140 expect(videos).to.have.lengthOf(2)
143 expect(videos[0].name).to.equal('normal') 141 expect(videos[0].name).to.equal('normal')
144 expect(videos[1].name).to.equal('nsfw') 142 expect(videos[1].name).to.equal('nsfw')
@@ -165,10 +163,10 @@ describe('Test video NSFW policy', function () {
165 customConfig.instance.defaultNSFWPolicy = 'do_not_list' 163 customConfig.instance.defaultNSFWPolicy = 'do_not_list'
166 await server.configCommand.updateCustomConfig({ newCustomConfig: customConfig }) 164 await server.configCommand.updateCustomConfig({ newCustomConfig: customConfig })
167 165
168 for (const res of await getVideosFunctions(userAccessToken)) { 166 for (const body of await getVideosFunctions(userAccessToken)) {
169 expect(res.body.total).to.equal(2) 167 expect(body.total).to.equal(2)
170 168
171 const videos = res.body.data 169 const videos = body.data
172 expect(videos).to.have.lengthOf(2) 170 expect(videos).to.have.lengthOf(2)
173 expect(videos[0].name).to.equal('normal') 171 expect(videos[0].name).to.equal('normal')
174 expect(videos[1].name).to.equal('nsfw') 172 expect(videos[1].name).to.equal('nsfw')
@@ -182,10 +180,10 @@ describe('Test video NSFW policy', function () {
182 nsfwPolicy: 'display' 180 nsfwPolicy: 'display'
183 }) 181 })
184 182
185 for (const res of await getVideosFunctions(server.accessToken)) { 183 for (const body of await getVideosFunctions(server.accessToken)) {
186 expect(res.body.total).to.equal(2) 184 expect(body.total).to.equal(2)
187 185
188 const videos = res.body.data 186 const videos = body.data
189 expect(videos).to.have.lengthOf(2) 187 expect(videos).to.have.lengthOf(2)
190 expect(videos[0].name).to.equal('normal') 188 expect(videos[0].name).to.equal('normal')
191 expect(videos[1].name).to.equal('nsfw') 189 expect(videos[1].name).to.equal('nsfw')
@@ -199,10 +197,10 @@ describe('Test video NSFW policy', function () {
199 nsfwPolicy: 'do_not_list' 197 nsfwPolicy: 'do_not_list'
200 }) 198 })
201 199
202 for (const res of await getVideosFunctions(server.accessToken)) { 200 for (const body of await getVideosFunctions(server.accessToken)) {
203 expect(res.body.total).to.equal(1) 201 expect(body.total).to.equal(1)
204 202
205 const videos = res.body.data 203 const videos = body.data
206 expect(videos).to.have.lengthOf(1) 204 expect(videos).to.have.lengthOf(1)
207 expect(videos[0].name).to.equal('normal') 205 expect(videos[0].name).to.equal('normal')
208 } 206 }
@@ -219,30 +217,30 @@ describe('Test video NSFW policy', function () {
219 }) 217 })
220 218
221 it('Should display NSFW videos when the nsfw param === true', async function () { 219 it('Should display NSFW videos when the nsfw param === true', async function () {
222 for (const res of await getVideosFunctions(server.accessToken, { nsfw: 'true' })) { 220 for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'true' })) {
223 expect(res.body.total).to.equal(1) 221 expect(body.total).to.equal(1)
224 222
225 const videos = res.body.data 223 const videos = body.data
226 expect(videos).to.have.lengthOf(1) 224 expect(videos).to.have.lengthOf(1)
227 expect(videos[0].name).to.equal('nsfw') 225 expect(videos[0].name).to.equal('nsfw')
228 } 226 }
229 }) 227 })
230 228
231 it('Should hide NSFW videos when the nsfw param === true', async function () { 229 it('Should hide NSFW videos when the nsfw param === true', async function () {
232 for (const res of await getVideosFunctions(server.accessToken, { nsfw: 'false' })) { 230 for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'false' })) {
233 expect(res.body.total).to.equal(1) 231 expect(body.total).to.equal(1)
234 232
235 const videos = res.body.data 233 const videos = body.data
236 expect(videos).to.have.lengthOf(1) 234 expect(videos).to.have.lengthOf(1)
237 expect(videos[0].name).to.equal('normal') 235 expect(videos[0].name).to.equal('normal')
238 } 236 }
239 }) 237 })
240 238
241 it('Should display both videos when the nsfw param === both', async function () { 239 it('Should display both videos when the nsfw param === both', async function () {
242 for (const res of await getVideosFunctions(server.accessToken, { nsfw: 'both' })) { 240 for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'both' })) {
243 expect(res.body.total).to.equal(2) 241 expect(body.total).to.equal(2)
244 242
245 const videos = res.body.data 243 const videos = body.data
246 expect(videos).to.have.lengthOf(2) 244 expect(videos).to.have.lengthOf(2)
247 expect(videos[0].name).to.equal('normal') 245 expect(videos[0].name).to.equal('normal')
248 expect(videos[1].name).to.equal('nsfw') 246 expect(videos[1].name).to.equal('nsfw')
diff --git a/server/tools/test-live.ts b/server/tools/test-live.ts
index 3c6a67cf7..3d1198d9c 100644
--- a/server/tools/test-live.ts
+++ b/server/tools/test-live.ts
@@ -38,7 +38,7 @@ async function run () {
38 38
39 const server = await flushAndRunServer(1, {}, [], { hideLogs: false, execArgv: [ '--inspect' ] }) 39 const server = await flushAndRunServer(1, {}, [], { hideLogs: false, execArgv: [ '--inspect' ] })
40 40
41 const cleanup = () => { 41 const cleanup = async () => {
42 console.log('Killing server') 42 console.log('Killing server')
43 await killallServers([ server ]) 43 await killallServers([ server ])
44 } 44 }
diff --git a/shared/extra-utils/search/search-command.ts b/shared/extra-utils/search/search-command.ts
index 7539a21ec..b6054f093 100644
--- a/shared/extra-utils/search/search-command.ts
+++ b/shared/extra-utils/search/search-command.ts
@@ -90,7 +90,7 @@ export class SearchCommand extends AbstractCommand {
90 ...options, 90 ...options,
91 91
92 path, 92 path,
93 query: search, 93 query: { sort: '-publishedAt', ...search },
94 implicitToken: false, 94 implicitToken: false,
95 defaultExpectedStatus: HttpStatusCode.OK_200 95 defaultExpectedStatus: HttpStatusCode.OK_200
96 }) 96 })
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index bd3be8373..e0e49d2c4 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -11,13 +11,14 @@ import { CLICommand } from '../cli'
11import { CustomPagesCommand } from '../custom-pages' 11import { CustomPagesCommand } from '../custom-pages'
12import { FeedCommand } from '../feeds' 12import { FeedCommand } from '../feeds'
13import { LogsCommand } from '../logs' 13import { LogsCommand } from '../logs'
14import { SQLCommand } from '../miscs'
14import { buildServerDirectory, getFileSize, isGithubCI, root, wait } from '../miscs/miscs' 15import { buildServerDirectory, getFileSize, isGithubCI, root, wait } from '../miscs/miscs'
15import { AbusesCommand } from '../moderation' 16import { AbusesCommand } from '../moderation'
16import { OverviewsCommand } from '../overviews' 17import { OverviewsCommand } from '../overviews'
17import { makeGetRequest } from '../requests/requests' 18import { makeGetRequest } from '../requests/requests'
18import { SearchCommand } from '../search' 19import { SearchCommand } from '../search'
19import { SocketIOCommand } from '../socket' 20import { SocketIOCommand } from '../socket'
20import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users' 21import { AccountsCommand, BlocklistCommand, NotificationsCommand, SubscriptionsCommand } from '../users'
21import { 22import {
22 BlacklistCommand, 23 BlacklistCommand,
23 CaptionsCommand, 24 CaptionsCommand,
@@ -30,7 +31,6 @@ import {
30 ServicesCommand, 31 ServicesCommand,
31 StreamingPlaylistsCommand 32 StreamingPlaylistsCommand
32} from '../videos' 33} from '../videos'
33import { SQLCommand } from '../miscs'
34import { CommentsCommand } from '../videos/comments-command' 34import { CommentsCommand } from '../videos/comments-command'
35import { ConfigCommand } from './config-command' 35import { ConfigCommand } from './config-command'
36import { ContactFormCommand } from './contact-form-command' 36import { ContactFormCommand } from './contact-form-command'
@@ -125,6 +125,7 @@ interface ServerInfo {
125 channelsCommand?: ChannelsCommand 125 channelsCommand?: ChannelsCommand
126 commentsCommand?: CommentsCommand 126 commentsCommand?: CommentsCommand
127 sqlCommand?: SQLCommand 127 sqlCommand?: SQLCommand
128 notificationsCommand?: NotificationsCommand
128} 129}
129 130
130function parallelTests () { 131function parallelTests () {
@@ -370,6 +371,7 @@ function assignCommands (server: ServerInfo) {
370 server.channelsCommand = new ChannelsCommand(server) 371 server.channelsCommand = new ChannelsCommand(server)
371 server.commentsCommand = new CommentsCommand(server) 372 server.commentsCommand = new CommentsCommand(server)
372 server.sqlCommand = new SQLCommand(server) 373 server.sqlCommand = new SQLCommand(server)
374 server.notificationsCommand = new NotificationsCommand(server)
373} 375}
374 376
375async function reRunServer (server: ServerInfo, configOverride?: any) { 377async function reRunServer (server: ServerInfo, configOverride?: any) {
diff --git a/shared/extra-utils/shared/abstract-command.ts b/shared/extra-utils/shared/abstract-command.ts
index 200db90d4..fd2deb57e 100644
--- a/shared/extra-utils/shared/abstract-command.ts
+++ b/shared/extra-utils/shared/abstract-command.ts
@@ -78,7 +78,7 @@ abstract class AbstractCommand {
78 } 78 }
79 79
80 protected getRequest (options: InternalGetCommandOptions) { 80 protected getRequest (options: InternalGetCommandOptions) {
81 const { redirects, query, contentType, accept } = options 81 const { redirects, query, contentType, accept, range } = options
82 82
83 return makeGetRequest({ 83 return makeGetRequest({
84 ...this.buildCommonRequestOptions(options), 84 ...this.buildCommonRequestOptions(options),
@@ -86,6 +86,7 @@ abstract class AbstractCommand {
86 redirects, 86 redirects,
87 query, 87 query,
88 contentType, 88 contentType,
89 range,
89 accept 90 accept
90 }) 91 })
91 } 92 }
@@ -168,10 +169,10 @@ abstract class AbstractCommand {
168 } 169 }
169 170
170 private buildCommonRequestOptions (options: InternalCommonCommandOptions) { 171 private buildCommonRequestOptions (options: InternalCommonCommandOptions) {
171 const { path } = options 172 const { url, path } = options
172 173
173 return { 174 return {
174 url: this.server.url, 175 url: url ?? this.server.url,
175 path, 176 path,
176 177
177 token: this.buildCommonRequestToken(options), 178 token: this.buildCommonRequestToken(options),
diff --git a/shared/extra-utils/users/index.ts b/shared/extra-utils/users/index.ts
index 9f760d7fd..ed166c756 100644
--- a/shared/extra-utils/users/index.ts
+++ b/shared/extra-utils/users/index.ts
@@ -2,6 +2,7 @@ export * from './accounts-command'
2export * from './accounts' 2export * from './accounts'
3export * from './blocklist-command' 3export * from './blocklist-command'
4export * from './login' 4export * from './login'
5export * from './user-notifications' 5export * from './notifications'
6export * from './notifications-command'
6export * from './subscriptions-command' 7export * from './subscriptions-command'
7export * from './users' 8export * from './users'
diff --git a/shared/extra-utils/users/notifications-command.ts b/shared/extra-utils/users/notifications-command.ts
new file mode 100644
index 000000000..dfe574ca1
--- /dev/null
+++ b/shared/extra-utils/users/notifications-command.ts
@@ -0,0 +1,87 @@
1import { ResultList } from '@shared/models'
2import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
3import { UserNotification, UserNotificationSetting } from '../../models/users'
4import { AbstractCommand, OverrideCommandOptions } from '../shared'
5
6export class NotificationsCommand extends AbstractCommand {
7
8 updateMySettings (options: OverrideCommandOptions & {
9 settings: UserNotificationSetting
10 }) {
11 const path = '/api/v1/users/me/notification-settings'
12
13 return this.putBodyRequest({
14 ...options,
15
16 path,
17 fields: options.settings,
18 implicitToken: true,
19 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
20 })
21 }
22
23 list (options: OverrideCommandOptions & {
24 start?: number
25 count?: number
26 unread?: boolean
27 sort?: string
28 }) {
29 const { start, count, unread, sort = '-createdAt' } = options
30 const path = '/api/v1/users/me/notifications'
31
32 return this.getRequestBody<ResultList<UserNotification>>({
33 ...options,
34
35 path,
36 query: {
37 start,
38 count,
39 sort,
40 unread
41 },
42 implicitToken: true,
43 defaultExpectedStatus: HttpStatusCode.OK_200
44 })
45 }
46
47 markAsRead (options: OverrideCommandOptions & {
48 ids: number[]
49 }) {
50 const { ids } = options
51 const path = '/api/v1/users/me/notifications/read'
52
53 return this.postBodyRequest({
54 ...options,
55
56 path,
57 fields: { ids },
58 implicitToken: true,
59 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
60 })
61 }
62
63 markAsReadAll (options: OverrideCommandOptions) {
64 const path = '/api/v1/users/me/notifications/read-all'
65
66 return this.postBodyRequest({
67 ...options,
68
69 path,
70 implicitToken: true,
71 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
72 })
73 }
74
75 async getLastest (options: OverrideCommandOptions = {}) {
76 const { total, data } = await this.list({
77 ...options,
78 start: 0,
79 count: 1,
80 sort: '-createdAt'
81 })
82
83 if (total === 0) return undefined
84
85 return data[0]
86 }
87}
diff --git a/shared/extra-utils/users/user-notifications.ts b/shared/extra-utils/users/notifications.ts
index 961cfcc0f..81f0729fa 100644
--- a/shared/extra-utils/users/user-notifications.ts
+++ b/shared/extra-utils/users/notifications.ts
@@ -3,86 +3,32 @@
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { inspect } from 'util' 4import { inspect } from 'util'
5import { AbuseState, PluginType } from '@shared/models' 5import { AbuseState, PluginType } from '@shared/models'
6import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
7import { UserNotification, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '../../models/users' 6import { UserNotification, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '../../models/users'
8import { MockSmtpServer } from '../mock-servers/mock-email' 7import { MockSmtpServer } from '../mock-servers/mock-email'
9import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
10import { doubleFollow } from '../server/follows' 8import { doubleFollow } from '../server/follows'
11import { flushAndRunMultipleServers, ServerInfo } from '../server/servers' 9import { flushAndRunMultipleServers, ServerInfo } from '../server/servers'
12import { setAccessTokensToServers, userLogin } from './login' 10import { setAccessTokensToServers, userLogin } from './login'
13import { createUser, getMyUserInformation } from './users' 11import { createUser, getMyUserInformation } from './users'
14 12
15function updateMyNotificationSettings ( 13function getAllNotificationsSettings (): UserNotificationSetting {
16 url: string, 14 return {
17 token: string, 15 newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
18 settings: UserNotificationSetting, 16 newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
19 statusCodeExpected = HttpStatusCode.NO_CONTENT_204 17 abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
20) { 18 videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
21 const path = '/api/v1/users/me/notification-settings' 19 blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
22 20 myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
23 return makePutBodyRequest({ 21 myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
24 url, 22 commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
25 path, 23 newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
26 token, 24 newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
27 fields: settings, 25 newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
28 statusCodeExpected 26 abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
29 }) 27 abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
30} 28 autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
31 29 newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
32async function getUserNotifications ( 30 newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
33 url: string, 31 }
34 token: string,
35 start: number,
36 count: number,
37 unread?: boolean,
38 sort = '-createdAt',
39 statusCodeExpected = HttpStatusCode.OK_200
40) {
41 const path = '/api/v1/users/me/notifications'
42
43 return makeGetRequest({
44 url,
45 path,
46 token,
47 query: {
48 start,
49 count,
50 sort,
51 unread
52 },
53 statusCodeExpected
54 })
55}
56
57function markAsReadNotifications (url: string, token: string, ids: number[], statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
58 const path = '/api/v1/users/me/notifications/read'
59
60 return makePostBodyRequest({
61 url,
62 path,
63 token,
64 fields: { ids },
65 statusCodeExpected
66 })
67}
68
69function markAsReadAllNotifications (url: string, token: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
70 const path = '/api/v1/users/me/notifications/read-all'
71
72 return makePostBodyRequest({
73 url,
74 path,
75 token,
76 statusCodeExpected
77 })
78}
79
80async function getLastNotification (serverUrl: string, accessToken: string) {
81 const res = await getUserNotifications(serverUrl, accessToken, 0, 1, undefined, '-createdAt')
82
83 if (res.body.total === 0) return undefined
84
85 return res.body.data[0] as UserNotification
86} 32}
87 33
88type CheckerBaseParams = { 34type CheckerBaseParams = {
@@ -104,7 +50,7 @@ async function checkNotification (
104 const check = base.check || { web: true, mail: true } 50 const check = base.check || { web: true, mail: true }
105 51
106 if (check.web) { 52 if (check.web) {
107 const notification = await getLastNotification(base.server.url, base.token) 53 const notification = await base.server.notificationsCommand.getLastest({ token: base.token })
108 54
109 if (notification || checkType !== 'absence') { 55 if (notification || checkType !== 'absence') {
110 notificationChecker(notification, checkType) 56 notificationChecker(notification, checkType)
@@ -680,27 +626,6 @@ async function checkNewPluginVersion (base: CheckerBaseParams, pluginType: Plugi
680 await checkNotification(base, notificationChecker, emailNotificationFinder, type) 626 await checkNotification(base, notificationChecker, emailNotificationFinder, type)
681} 627}
682 628
683function getAllNotificationsSettings (): UserNotificationSetting {
684 return {
685 newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
686 newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
687 abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
688 videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
689 blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
690 myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
691 myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
692 commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
693 newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
694 newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
695 newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
696 abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
697 abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
698 autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
699 newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
700 newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
701 }
702}
703
704async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) { 629async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) {
705 const userNotifications: UserNotification[] = [] 630 const userNotifications: UserNotification[] = []
706 const adminNotifications: UserNotification[] = [] 631 const adminNotifications: UserNotification[] = []
@@ -739,11 +664,11 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
739 }) 664 })
740 const userAccessToken = await userLogin(servers[0], user) 665 const userAccessToken = await userLogin(servers[0], user)
741 666
742 await updateMyNotificationSettings(servers[0].url, userAccessToken, getAllNotificationsSettings()) 667 await servers[0].notificationsCommand.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
743 await updateMyNotificationSettings(servers[0].url, servers[0].accessToken, getAllNotificationsSettings()) 668 await servers[0].notificationsCommand.updateMySettings({ settings: getAllNotificationsSettings() })
744 669
745 if (serversCount > 1) { 670 if (serversCount > 1) {
746 await updateMyNotificationSettings(servers[1].url, servers[1].accessToken, getAllNotificationsSettings()) 671 await servers[1].notificationsCommand.updateMySettings({ settings: getAllNotificationsSettings() })
747 } 672 }
748 673
749 { 674 {
@@ -777,11 +702,11 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
777// --------------------------------------------------------------------------- 702// ---------------------------------------------------------------------------
778 703
779export { 704export {
705 getAllNotificationsSettings,
706
780 CheckerBaseParams, 707 CheckerBaseParams,
781 CheckerType, 708 CheckerType,
782 getAllNotificationsSettings,
783 checkNotification, 709 checkNotification,
784 markAsReadAllNotifications,
785 checkMyVideoImportIsFinished, 710 checkMyVideoImportIsFinished,
786 checkUserRegistered, 711 checkUserRegistered,
787 checkAutoInstanceFollowing, 712 checkAutoInstanceFollowing,
@@ -791,14 +716,10 @@ export {
791 checkNewCommentOnMyVideo, 716 checkNewCommentOnMyVideo,
792 checkNewBlacklistOnMyVideo, 717 checkNewBlacklistOnMyVideo,
793 checkCommentMention, 718 checkCommentMention,
794 updateMyNotificationSettings,
795 checkNewVideoAbuseForModerators, 719 checkNewVideoAbuseForModerators,
796 checkVideoAutoBlacklistForModerators, 720 checkVideoAutoBlacklistForModerators,
797 checkNewAbuseMessage, 721 checkNewAbuseMessage,
798 checkAbuseStateChange, 722 checkAbuseStateChange,
799 getUserNotifications,
800 markAsReadNotifications,
801 getLastNotification,
802 checkNewInstanceFollower, 723 checkNewInstanceFollower,
803 prepareNotificationsTest, 724 prepareNotificationsTest,
804 checkNewCommentAbuseForModerators, 725 checkNewCommentAbuseForModerators,
diff --git a/shared/extra-utils/videos/streaming-playlists-command.ts b/shared/extra-utils/videos/streaming-playlists-command.ts
index b109597c9..fab3eb556 100644
--- a/shared/extra-utils/videos/streaming-playlists-command.ts
+++ b/shared/extra-utils/videos/streaming-playlists-command.ts
@@ -21,7 +21,7 @@ export class StreamingPlaylistsCommand extends AbstractCommand {
21 url: string 21 url: string
22 range?: string 22 range?: string
23 }) { 23 }) {
24 return unwrapText(this.getRawRequest({ 24 return unwrapBody<Buffer>(this.getRawRequest({
25 ...options, 25 ...options,
26 26
27 url: options.url, 27 url: options.url,