diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/abuse.ts | 4 | ||||
-rw-r--r-- | server/controllers/api/users/my-abuses.ts | 2 | ||||
-rw-r--r-- | server/helpers/middlewares/abuses.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/abuse.ts | 16 | ||||
-rw-r--r-- | server/models/abuse/abuse.ts | 26 | ||||
-rw-r--r-- | server/tests/api/check-params/abuses.ts | 52 | ||||
-rw-r--r-- | server/tests/api/moderation/abuses.ts | 19 | ||||
-rw-r--r-- | server/types/models/moderation/abuse.ts | 6 | ||||
-rw-r--r-- | server/typings/express/index.d.ts | 5 |
9 files changed, 109 insertions, 23 deletions
diff --git a/server/controllers/api/abuse.ts b/server/controllers/api/abuse.ts index 50d068157..72e62fc0b 100644 --- a/server/controllers/api/abuse.ts +++ b/server/controllers/api/abuse.ts | |||
@@ -16,6 +16,7 @@ import { | |||
16 | asyncMiddleware, | 16 | asyncMiddleware, |
17 | asyncRetryTransactionMiddleware, | 17 | asyncRetryTransactionMiddleware, |
18 | authenticate, | 18 | authenticate, |
19 | checkAbuseValidForMessagesValidator, | ||
19 | deleteAbuseMessageValidator, | 20 | deleteAbuseMessageValidator, |
20 | ensureUserHasRight, | 21 | ensureUserHasRight, |
21 | getAbuseValidator, | 22 | getAbuseValidator, |
@@ -58,12 +59,14 @@ abuseRouter.delete('/:id', | |||
58 | abuseRouter.get('/:id/messages', | 59 | abuseRouter.get('/:id/messages', |
59 | authenticate, | 60 | authenticate, |
60 | asyncMiddleware(getAbuseValidator), | 61 | asyncMiddleware(getAbuseValidator), |
62 | checkAbuseValidForMessagesValidator, | ||
61 | asyncRetryTransactionMiddleware(listAbuseMessages) | 63 | asyncRetryTransactionMiddleware(listAbuseMessages) |
62 | ) | 64 | ) |
63 | 65 | ||
64 | abuseRouter.post('/:id/messages', | 66 | abuseRouter.post('/:id/messages', |
65 | authenticate, | 67 | authenticate, |
66 | asyncMiddleware(getAbuseValidator), | 68 | asyncMiddleware(getAbuseValidator), |
69 | checkAbuseValidForMessagesValidator, | ||
67 | addAbuseMessageValidator, | 70 | addAbuseMessageValidator, |
68 | asyncRetryTransactionMiddleware(addAbuseMessage) | 71 | asyncRetryTransactionMiddleware(addAbuseMessage) |
69 | ) | 72 | ) |
@@ -71,6 +74,7 @@ abuseRouter.post('/:id/messages', | |||
71 | abuseRouter.delete('/:id/messages/:messageId', | 74 | abuseRouter.delete('/:id/messages/:messageId', |
72 | authenticate, | 75 | authenticate, |
73 | asyncMiddleware(getAbuseValidator), | 76 | asyncMiddleware(getAbuseValidator), |
77 | checkAbuseValidForMessagesValidator, | ||
74 | asyncMiddleware(deleteAbuseMessageValidator), | 78 | asyncMiddleware(deleteAbuseMessageValidator), |
75 | asyncRetryTransactionMiddleware(deleteAbuseMessage) | 79 | asyncRetryTransactionMiddleware(deleteAbuseMessage) |
76 | ) | 80 | ) |
diff --git a/server/controllers/api/users/my-abuses.ts b/server/controllers/api/users/my-abuses.ts index e43fc483e..fcd0ce3fc 100644 --- a/server/controllers/api/users/my-abuses.ts +++ b/server/controllers/api/users/my-abuses.ts | |||
@@ -43,6 +43,6 @@ async function listMyAbuses (req: express.Request, res: express.Response) { | |||
43 | 43 | ||
44 | return res.json({ | 44 | return res.json({ |
45 | total: resultList.total, | 45 | total: resultList.total, |
46 | data: resultList.data.map(d => d.toFormattedAdminJSON()) | 46 | data: resultList.data.map(d => d.toFormattedUserJSON()) |
47 | }) | 47 | }) |
48 | } | 48 | } |
diff --git a/server/helpers/middlewares/abuses.ts b/server/helpers/middlewares/abuses.ts index be8c8b449..659ad8939 100644 --- a/server/helpers/middlewares/abuses.ts +++ b/server/helpers/middlewares/abuses.ts | |||
@@ -26,7 +26,7 @@ async function doesVideoAbuseExist (abuseIdArg: number | string, videoUUID: stri | |||
26 | } | 26 | } |
27 | 27 | ||
28 | async function doesAbuseExist (abuseId: number | string, res: Response) { | 28 | async function doesAbuseExist (abuseId: number | string, res: Response) { |
29 | const abuse = await AbuseModel.loadById(parseInt(abuseId + '', 10)) | 29 | const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) |
30 | 30 | ||
31 | if (!abuse) { | 31 | if (!abuse) { |
32 | res.status(404) | 32 | res.status(404) |
diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts index cb0bc658a..2a096e0af 100644 --- a/server/middlewares/validators/abuse.ts +++ b/server/middlewares/validators/abuse.ts | |||
@@ -201,6 +201,21 @@ const getAbuseValidator = [ | |||
201 | } | 201 | } |
202 | ] | 202 | ] |
203 | 203 | ||
204 | const checkAbuseValidForMessagesValidator = [ | ||
205 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
206 | logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body }) | ||
207 | |||
208 | const abuse = res.locals.abuse | ||
209 | if (abuse.ReporterAccount.isOwned() === false) { | ||
210 | return res.status(400).json({ | ||
211 | error: 'This abuse was created by a user of your instance.', | ||
212 | }) | ||
213 | } | ||
214 | |||
215 | return next() | ||
216 | } | ||
217 | ] | ||
218 | |||
204 | const addAbuseMessageValidator = [ | 219 | const addAbuseMessageValidator = [ |
205 | body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'), | 220 | body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'), |
206 | 221 | ||
@@ -357,6 +372,7 @@ export { | |||
357 | abuseReportValidator, | 372 | abuseReportValidator, |
358 | abuseGetValidator, | 373 | abuseGetValidator, |
359 | addAbuseMessageValidator, | 374 | addAbuseMessageValidator, |
375 | checkAbuseValidForMessagesValidator, | ||
360 | abuseUpdateValidator, | 376 | abuseUpdateValidator, |
361 | deleteAbuseMessageValidator, | 377 | deleteAbuseMessageValidator, |
362 | abuseListForUserValidator, | 378 | abuseListForUserValidator, |
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 7002502d5..3353e9e41 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -25,14 +25,14 @@ import { | |||
25 | AbusePredefinedReasonsString, | 25 | AbusePredefinedReasonsString, |
26 | AbuseState, | 26 | AbuseState, |
27 | AbuseVideoIs, | 27 | AbuseVideoIs, |
28 | AdminVideoAbuse, | ||
29 | AdminAbuse, | 28 | AdminAbuse, |
29 | AdminVideoAbuse, | ||
30 | AdminVideoCommentAbuse, | 30 | AdminVideoCommentAbuse, |
31 | UserAbuse, | 31 | UserAbuse, |
32 | UserVideoAbuse | 32 | UserVideoAbuse |
33 | } from '@shared/models' | 33 | } from '@shared/models' |
34 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' | 34 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' |
35 | import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MUserAccountId, MAbuseUserFormattable } from '../../types/models' | 35 | import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MAbuseReporter, MAbuseUserFormattable, MUserAccountId } from '../../types/models' |
36 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' | 36 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' |
37 | import { getSort, throwIfNotValid } from '../utils' | 37 | import { getSort, throwIfNotValid } from '../utils' |
38 | import { ThumbnailModel } from '../video/thumbnail' | 38 | import { ThumbnailModel } from '../video/thumbnail' |
@@ -266,7 +266,7 @@ export class AbuseModel extends Model<AbuseModel> { | |||
266 | VideoAbuse: VideoAbuseModel | 266 | VideoAbuse: VideoAbuseModel |
267 | 267 | ||
268 | // FIXME: deprecated in 2.3. Remove these validators | 268 | // FIXME: deprecated in 2.3. Remove these validators |
269 | static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MAbuse> { | 269 | static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MAbuseReporter> { |
270 | const videoWhere: WhereOptions = {} | 270 | const videoWhere: WhereOptions = {} |
271 | 271 | ||
272 | if (videoId) videoWhere.videoId = videoId | 272 | if (videoId) videoWhere.videoId = videoId |
@@ -278,6 +278,10 @@ export class AbuseModel extends Model<AbuseModel> { | |||
278 | model: VideoAbuseModel, | 278 | model: VideoAbuseModel, |
279 | required: true, | 279 | required: true, |
280 | where: videoWhere | 280 | where: videoWhere |
281 | }, | ||
282 | { | ||
283 | model: AccountModel, | ||
284 | as: 'ReporterAccount' | ||
281 | } | 285 | } |
282 | ], | 286 | ], |
283 | where: { | 287 | where: { |
@@ -287,11 +291,17 @@ export class AbuseModel extends Model<AbuseModel> { | |||
287 | return AbuseModel.findOne(query) | 291 | return AbuseModel.findOne(query) |
288 | } | 292 | } |
289 | 293 | ||
290 | static loadById (id: number): Bluebird<MAbuse> { | 294 | static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> { |
291 | const query = { | 295 | const query = { |
292 | where: { | 296 | where: { |
293 | id | 297 | id |
294 | } | 298 | }, |
299 | include: [ | ||
300 | { | ||
301 | model: AccountModel, | ||
302 | as: 'ReporterAccount' | ||
303 | } | ||
304 | ] | ||
295 | } | 305 | } |
296 | 306 | ||
297 | return AbuseModel.findOne(query) | 307 | return AbuseModel.findOne(query) |
@@ -466,8 +476,6 @@ export class AbuseModel extends Model<AbuseModel> { | |||
466 | label: AbuseModel.getStateLabel(this.state) | 476 | label: AbuseModel.getStateLabel(this.state) |
467 | }, | 477 | }, |
468 | 478 | ||
469 | moderationComment: this.moderationComment, | ||
470 | |||
471 | countMessages, | 479 | countMessages, |
472 | 480 | ||
473 | createdAt: this.createdAt, | 481 | createdAt: this.createdAt, |
@@ -500,6 +508,8 @@ export class AbuseModel extends Model<AbuseModel> { | |||
500 | video, | 508 | video, |
501 | comment, | 509 | comment, |
502 | 510 | ||
511 | moderationComment: this.moderationComment, | ||
512 | |||
503 | reporterAccount: this.ReporterAccount | 513 | reporterAccount: this.ReporterAccount |
504 | ? this.ReporterAccount.toFormattedJSON() | 514 | ? this.ReporterAccount.toFormattedJSON() |
505 | : null, | 515 | : null, |
@@ -519,7 +529,7 @@ export class AbuseModel extends Model<AbuseModel> { | |||
519 | const countMessages = this.get('countMessages') as number | 529 | const countMessages = this.get('countMessages') as number |
520 | 530 | ||
521 | const video = this.buildBaseVideoAbuse() | 531 | const video = this.buildBaseVideoAbuse() |
522 | const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse() | 532 | const comment = this.buildBaseVideoCommentAbuse() |
523 | const abuse = this.buildBaseAbuse(countMessages || 0) | 533 | const abuse = this.buildBaseAbuse(countMessages || 0) |
524 | 534 | ||
525 | return Object.assign(abuse, { | 535 | return Object.assign(abuse, { |
diff --git a/server/tests/api/check-params/abuses.ts b/server/tests/api/check-params/abuses.ts index 5e1d66c25..0ef8f6cac 100644 --- a/server/tests/api/check-params/abuses.ts +++ b/server/tests/api/check-params/abuses.ts | |||
@@ -3,21 +3,26 @@ | |||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import { AbuseCreate, AbuseState } from '@shared/models' | 4 | import { AbuseCreate, AbuseState } from '@shared/models' |
5 | import { | 5 | import { |
6 | addAbuseMessage, | ||
6 | cleanupTests, | 7 | cleanupTests, |
7 | createUser, | 8 | createUser, |
8 | deleteAbuse, | 9 | deleteAbuse, |
10 | deleteAbuseMessage, | ||
11 | doubleFollow, | ||
9 | flushAndRunServer, | 12 | flushAndRunServer, |
13 | generateUserAccessToken, | ||
14 | getAdminAbusesList, | ||
15 | getVideoIdFromUUID, | ||
16 | listAbuseMessages, | ||
10 | makeGetRequest, | 17 | makeGetRequest, |
11 | makePostBodyRequest, | 18 | makePostBodyRequest, |
19 | reportAbuse, | ||
12 | ServerInfo, | 20 | ServerInfo, |
13 | setAccessTokensToServers, | 21 | setAccessTokensToServers, |
14 | updateAbuse, | 22 | updateAbuse, |
15 | uploadVideo, | 23 | uploadVideo, |
16 | userLogin, | 24 | userLogin, |
17 | generateUserAccessToken, | 25 | waitJobs |
18 | addAbuseMessage, | ||
19 | listAbuseMessages, | ||
20 | deleteAbuseMessage | ||
21 | } from '../../../../shared/extra-utils' | 26 | } from '../../../../shared/extra-utils' |
22 | import { | 27 | import { |
23 | checkBadCountPagination, | 28 | checkBadCountPagination, |
@@ -29,6 +34,7 @@ describe('Test abuses API validators', function () { | |||
29 | const basePath = '/api/v1/abuses/' | 34 | const basePath = '/api/v1/abuses/' |
30 | 35 | ||
31 | let server: ServerInfo | 36 | let server: ServerInfo |
37 | |||
32 | let userAccessToken = '' | 38 | let userAccessToken = '' |
33 | let userAccessToken2 = '' | 39 | let userAccessToken2 = '' |
34 | let abuseId: number | 40 | let abuseId: number |
@@ -321,7 +327,7 @@ describe('Test abuses API validators', function () { | |||
321 | }) | 327 | }) |
322 | }) | 328 | }) |
323 | 329 | ||
324 | describe('When listing abuse message', function () { | 330 | describe('When listing abuse messages', function () { |
325 | 331 | ||
326 | it('Should fail with an invalid abuse id', async function () { | 332 | it('Should fail with an invalid abuse id', async function () { |
327 | await listAbuseMessages(server.url, userAccessToken, 888, 404) | 333 | await listAbuseMessages(server.url, userAccessToken, 888, 404) |
@@ -382,7 +388,43 @@ describe('Test abuses API validators', function () { | |||
382 | }) | 388 | }) |
383 | }) | 389 | }) |
384 | 390 | ||
391 | describe('When trying to manage messages of a remote abuse', function () { | ||
392 | let remoteAbuseId: number | ||
393 | let anotherServer: ServerInfo | ||
394 | |||
395 | before(async function () { | ||
396 | this.timeout(20000) | ||
397 | |||
398 | anotherServer = await flushAndRunServer(2) | ||
399 | await setAccessTokensToServers([ anotherServer ]) | ||
400 | |||
401 | await doubleFollow(anotherServer, server) | ||
402 | |||
403 | const server2VideoId = await getVideoIdFromUUID(anotherServer.url, server.video.uuid) | ||
404 | await reportAbuse({ | ||
405 | url: anotherServer.url, | ||
406 | token: anotherServer.accessToken, | ||
407 | reason: 'remote server', | ||
408 | videoId: server2VideoId | ||
409 | }) | ||
410 | |||
411 | await waitJobs([ server, anotherServer ]) | ||
412 | |||
413 | const res = await getAdminAbusesList({ url: server.url, token: server.accessToken, sort: '-createdAt' }) | ||
414 | remoteAbuseId = res.body.data[0].id | ||
415 | }) | ||
416 | |||
417 | it('Should fail when listing abuse messages of a remote abuse', async function () { | ||
418 | await listAbuseMessages(server.url, server.accessToken, remoteAbuseId, 400) | ||
419 | }) | ||
420 | |||
421 | it('Should fail when creating abuse message of a remote abuse', async function () { | ||
422 | await addAbuseMessage(server.url, server.accessToken, remoteAbuseId, 'message', 400) | ||
423 | }) | ||
424 | }) | ||
425 | |||
385 | after(async function () { | 426 | after(async function () { |
386 | await cleanupTests([ server ]) | 427 | await cleanupTests([ server ]) |
387 | }) | 428 | }) |
388 | }) | 429 | }) |
430 | |||
diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts index 601125fdf..fb765e7e3 100644 --- a/server/tests/api/moderation/abuses.ts +++ b/server/tests/api/moderation/abuses.ts | |||
@@ -2,12 +2,23 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { AbuseFilter, AbusePredefinedReasonsString, AbuseState, Account, AdminAbuse, UserAbuse, VideoComment, AbuseMessage } from '@shared/models' | ||
6 | import { | 5 | import { |
6 | AbuseFilter, | ||
7 | AbuseMessage, | ||
8 | AbusePredefinedReasonsString, | ||
9 | AbuseState, | ||
10 | Account, | ||
11 | AdminAbuse, | ||
12 | UserAbuse, | ||
13 | VideoComment | ||
14 | } from '@shared/models' | ||
15 | import { | ||
16 | addAbuseMessage, | ||
7 | addVideoCommentThread, | 17 | addVideoCommentThread, |
8 | cleanupTests, | 18 | cleanupTests, |
9 | createUser, | 19 | createUser, |
10 | deleteAbuse, | 20 | deleteAbuse, |
21 | deleteAbuseMessage, | ||
11 | deleteVideoComment, | 22 | deleteVideoComment, |
12 | flushAndRunMultipleServers, | 23 | flushAndRunMultipleServers, |
13 | generateUserAccessToken, | 24 | generateUserAccessToken, |
@@ -18,6 +29,7 @@ import { | |||
18 | getVideoIdFromUUID, | 29 | getVideoIdFromUUID, |
19 | getVideosList, | 30 | getVideosList, |
20 | immutableAssign, | 31 | immutableAssign, |
32 | listAbuseMessages, | ||
21 | removeUser, | 33 | removeUser, |
22 | removeVideo, | 34 | removeVideo, |
23 | reportAbuse, | 35 | reportAbuse, |
@@ -26,10 +38,7 @@ import { | |||
26 | updateAbuse, | 38 | updateAbuse, |
27 | uploadVideo, | 39 | uploadVideo, |
28 | uploadVideoAndGetId, | 40 | uploadVideoAndGetId, |
29 | userLogin, | 41 | userLogin |
30 | addAbuseMessage, | ||
31 | listAbuseMessages, | ||
32 | deleteAbuseMessage | ||
33 | } from '../../../../shared/extra-utils/index' | 42 | } from '../../../../shared/extra-utils/index' |
34 | import { doubleFollow } from '../../../../shared/extra-utils/server/follows' | 43 | import { doubleFollow } from '../../../../shared/extra-utils/server/follows' |
35 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' | 44 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' |
diff --git a/server/types/models/moderation/abuse.ts b/server/types/models/moderation/abuse.ts index 39ef50771..d793a720f 100644 --- a/server/types/models/moderation/abuse.ts +++ b/server/types/models/moderation/abuse.ts | |||
@@ -2,7 +2,7 @@ import { VideoAbuseModel } from '@server/models/abuse/video-abuse' | |||
2 | import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse' | 2 | import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse' |
3 | import { PickWith } from '@shared/core-utils' | 3 | import { PickWith } from '@shared/core-utils' |
4 | import { AbuseModel } from '../../../models/abuse/abuse' | 4 | import { AbuseModel } from '../../../models/abuse/abuse' |
5 | import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl } from '../account' | 5 | import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl, MAccount } from '../account' |
6 | import { MCommentOwner, MCommentUrl, MVideoUrl, MCommentOwnerVideo, MComment, MCommentVideo } from '../video' | 6 | import { MCommentOwner, MCommentUrl, MVideoUrl, MCommentOwnerVideo, MComment, MCommentVideo } from '../video' |
7 | import { MVideo, MVideoAccountLightBlacklistAllFiles } from '../video/video' | 7 | import { MVideo, MVideoAccountLightBlacklistAllFiles } from '../video/video' |
8 | 8 | ||
@@ -18,6 +18,10 @@ export type MVideoAbuse = Omit<VideoAbuseModel, 'Abuse' | 'Video'> | |||
18 | 18 | ||
19 | export type MCommentAbuse = Omit<VideoCommentAbuseModel, 'Abuse' | 'VideoComment'> | 19 | export type MCommentAbuse = Omit<VideoCommentAbuseModel, 'Abuse' | 'VideoComment'> |
20 | 20 | ||
21 | export type MAbuseReporter = | ||
22 | MAbuse & | ||
23 | Use<'ReporterAccount', MAccountDefault> | ||
24 | |||
21 | // ############################################################################ | 25 | // ############################################################################ |
22 | 26 | ||
23 | export type MVideoAbuseVideo = | 27 | export type MVideoAbuseVideo = |
diff --git a/server/typings/express/index.d.ts b/server/typings/express/index.d.ts index 452c6e1a0..d95b8925d 100644 --- a/server/typings/express/index.d.ts +++ b/server/typings/express/index.d.ts | |||
@@ -9,7 +9,8 @@ import { | |||
9 | MVideoFile, | 9 | MVideoFile, |
10 | MVideoImmutable, | 10 | MVideoImmutable, |
11 | MVideoPlaylistFull, | 11 | MVideoPlaylistFull, |
12 | MVideoPlaylistFullSummary | 12 | MVideoPlaylistFullSummary, |
13 | MAbuseReporter | ||
13 | } from '@server/types/models' | 14 | } from '@server/types/models' |
14 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' | 15 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' |
15 | import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server' | 16 | import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server' |
@@ -78,7 +79,7 @@ declare module 'express' { | |||
78 | 79 | ||
79 | videoCaption?: MVideoCaptionVideo | 80 | videoCaption?: MVideoCaptionVideo |
80 | 81 | ||
81 | abuse?: MAbuse | 82 | abuse?: MAbuseReporter |
82 | abuseMessage?: MAbuseMessage | 83 | abuseMessage?: MAbuseMessage |
83 | 84 | ||
84 | videoStreamingPlaylist?: MStreamingPlaylist | 85 | videoStreamingPlaylist?: MStreamingPlaylist |