mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 09:49:20 +02:00
Add typeOneOf filter to list notifications
This commit is contained in:
parent
8f35e76928
commit
0bf17d869c
11 changed files with 200 additions and 98 deletions
|
@ -4,6 +4,7 @@ export * from './user-create-result.model.js'
|
||||||
export * from './user-create.model.js'
|
export * from './user-create.model.js'
|
||||||
export * from './user-flag.model.js'
|
export * from './user-flag.model.js'
|
||||||
export * from './user-login.model.js'
|
export * from './user-login.model.js'
|
||||||
|
export * from './user-notification-list-query.model.js'
|
||||||
export * from './user-notification-setting.model.js'
|
export * from './user-notification-setting.model.js'
|
||||||
export * from './user-notification.model.js'
|
export * from './user-notification.model.js'
|
||||||
export * from './user-refresh-token.model.js'
|
export * from './user-refresh-token.model.js'
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { UserNotificationType_Type } from './user-notification.model.js'
|
||||||
|
|
||||||
|
export type UserNotificationListQuery = {
|
||||||
|
start?: number
|
||||||
|
count?: number
|
||||||
|
sort?: string
|
||||||
|
|
||||||
|
unread?: boolean
|
||||||
|
|
||||||
|
typeOneOf?: UserNotificationType_Type[]
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { HttpStatusCode, ResultList, UserNotification, UserNotificationSetting } from '@peertube/peertube-models'
|
import { HttpStatusCode, ResultList, UserNotification, UserNotificationSetting, UserNotificationType_Type } from '@peertube/peertube-models'
|
||||||
import { AbstractCommand, OverrideCommandOptions } from '../shared/index.js'
|
import { AbstractCommand, OverrideCommandOptions } from '../shared/index.js'
|
||||||
|
|
||||||
export class NotificationsCommand extends AbstractCommand {
|
export class NotificationsCommand extends AbstractCommand {
|
||||||
|
@ -23,8 +23,9 @@ export class NotificationsCommand extends AbstractCommand {
|
||||||
count?: number
|
count?: number
|
||||||
unread?: boolean
|
unread?: boolean
|
||||||
sort?: string
|
sort?: string
|
||||||
|
typeOneOf?: UserNotificationType_Type[]
|
||||||
}) {
|
}) {
|
||||||
const { start, count, unread, sort = '-createdAt' } = options
|
const { start, count, unread, typeOneOf, sort = '-createdAt' } = options
|
||||||
const path = '/api/v1/users/me/notifications'
|
const path = '/api/v1/users/me/notifications'
|
||||||
|
|
||||||
return this.getRequestBody<ResultList<UserNotification>>({
|
return this.getRequestBody<ResultList<UserNotification>>({
|
||||||
|
@ -35,6 +36,7 @@ export class NotificationsCommand extends AbstractCommand {
|
||||||
start,
|
start,
|
||||||
count,
|
count,
|
||||||
sort,
|
sort,
|
||||||
|
typeOneOf,
|
||||||
unread
|
unread
|
||||||
},
|
},
|
||||||
implicitToken: true,
|
implicitToken: true,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import { io } from 'socket.io-client'
|
import { io } from 'socket.io-client'
|
||||||
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@tests/shared/checks.js'
|
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@tests/shared/checks.js'
|
||||||
import { wait } from '@peertube/peertube-core-utils'
|
import { wait } from '@peertube/peertube-core-utils'
|
||||||
import { HttpStatusCode, UserNotificationSetting, UserNotificationSettingValue } from '@peertube/peertube-models'
|
import { HttpStatusCode, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '@peertube/peertube-models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createSingleServer,
|
createSingleServer,
|
||||||
|
@ -42,15 +42,15 @@ describe('Test user notifications API validators', function () {
|
||||||
await checkBadSortPagination(server.url, path, server.accessToken)
|
await checkBadSortPagination(server.url, path, server.accessToken)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an incorrect unread parameter', async function () {
|
it('Should fail with an incorrect typeOneOf parameter', async function () {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path,
|
path,
|
||||||
query: {
|
query: {
|
||||||
unread: 'toto'
|
typeOneOf: 'toto'
|
||||||
},
|
},
|
||||||
token: server.accessToken,
|
token: server.accessToken,
|
||||||
expectedStatus: HttpStatusCode.OK_200
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -66,6 +66,9 @@ describe('Test user notifications API validators', function () {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path,
|
path,
|
||||||
|
query: {
|
||||||
|
typeOneOf: [ UserNotificationType.ABUSE_NEW_MESSAGE ]
|
||||||
|
},
|
||||||
token: server.accessToken,
|
token: server.accessToken,
|
||||||
expectedStatus: HttpStatusCode.OK_200
|
expectedStatus: HttpStatusCode.OK_200
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { UserNotification, UserNotificationSettingValue } from '@peertube/peertube-models'
|
import { UserNotification, UserNotificationSettingValue, UserNotificationType } from '@peertube/peertube-models'
|
||||||
import { cleanupTests, PeerTubeServer, waitJobs } from '@peertube/peertube-server-commands'
|
import { cleanupTests, PeerTubeServer, waitJobs } from '@peertube/peertube-server-commands'
|
||||||
import { MockSmtpServer } from '@tests/shared/mock-servers/mock-email.js'
|
import { MockSmtpServer } from '@tests/shared/mock-servers/mock-email.js'
|
||||||
import {
|
import {
|
||||||
|
@ -43,6 +43,34 @@ describe('Test notifications API', function () {
|
||||||
expect(data).to.have.lengthOf(2)
|
expect(data).to.have.lengthOf(2)
|
||||||
expect(total).to.equal(10)
|
expect(total).to.equal(10)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should correctly filter notifications on its type', async function () {
|
||||||
|
{
|
||||||
|
const { data, total } = await server.notifications.list({
|
||||||
|
token: userToken,
|
||||||
|
start: 0,
|
||||||
|
count: 2,
|
||||||
|
typeOneOf: [ UserNotificationType.ABUSE_NEW_MESSAGE ]
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(data).to.have.lengthOf(0)
|
||||||
|
expect(total).to.equal(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { data, total } = await server.notifications.list({
|
||||||
|
token: userToken,
|
||||||
|
start: 0,
|
||||||
|
count: 2,
|
||||||
|
typeOneOf: [ UserNotificationType.ABUSE_NEW_MESSAGE, UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION ]
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
expect(data).to.have.lengthOf(2)
|
||||||
|
expect(total).to.equal(10)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Mark as read', function () {
|
describe('Mark as read', function () {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'multer'
|
import { HttpStatusCode, UserNotificationListQuery, UserNotificationSetting } from '@peertube/peertube-models'
|
||||||
import express from 'express'
|
|
||||||
import { HttpStatusCode, UserNotificationSetting } from '@peertube/peertube-models'
|
|
||||||
import { getFormattedObjects } from '@server/helpers/utils.js'
|
import { getFormattedObjects } from '@server/helpers/utils.js'
|
||||||
import { UserNotificationModel } from '@server/models/user/user-notification.js'
|
import { UserNotificationModel } from '@server/models/user/user-notification.js'
|
||||||
|
import express from 'express'
|
||||||
|
import 'multer'
|
||||||
import {
|
import {
|
||||||
asyncMiddleware,
|
asyncMiddleware,
|
||||||
asyncRetryTransactionMiddleware,
|
asyncRetryTransactionMiddleware,
|
||||||
|
@ -22,13 +22,15 @@ import { meRouter } from './me.js'
|
||||||
|
|
||||||
const myNotificationsRouter = express.Router()
|
const myNotificationsRouter = express.Router()
|
||||||
|
|
||||||
meRouter.put('/me/notification-settings',
|
meRouter.put(
|
||||||
|
'/me/notification-settings',
|
||||||
authenticate,
|
authenticate,
|
||||||
updateNotificationSettingsValidator,
|
updateNotificationSettingsValidator,
|
||||||
asyncRetryTransactionMiddleware(updateNotificationSettings)
|
asyncRetryTransactionMiddleware(updateNotificationSettings)
|
||||||
)
|
)
|
||||||
|
|
||||||
myNotificationsRouter.get('/me/notifications',
|
myNotificationsRouter.get(
|
||||||
|
'/me/notifications',
|
||||||
authenticate,
|
authenticate,
|
||||||
paginationValidator,
|
paginationValidator,
|
||||||
userNotificationsSortValidator,
|
userNotificationsSortValidator,
|
||||||
|
@ -38,16 +40,14 @@ myNotificationsRouter.get('/me/notifications',
|
||||||
asyncMiddleware(listUserNotifications)
|
asyncMiddleware(listUserNotifications)
|
||||||
)
|
)
|
||||||
|
|
||||||
myNotificationsRouter.post('/me/notifications/read',
|
myNotificationsRouter.post(
|
||||||
|
'/me/notifications/read',
|
||||||
authenticate,
|
authenticate,
|
||||||
markAsReadUserNotificationsValidator,
|
markAsReadUserNotificationsValidator,
|
||||||
asyncMiddleware(markAsReadUserNotifications)
|
asyncMiddleware(markAsReadUserNotifications)
|
||||||
)
|
)
|
||||||
|
|
||||||
myNotificationsRouter.post('/me/notifications/read-all',
|
myNotificationsRouter.post('/me/notifications/read-all', authenticate, asyncMiddleware(markAsReadAllUserNotifications))
|
||||||
authenticate,
|
|
||||||
asyncMiddleware(markAsReadAllUserNotifications)
|
|
||||||
)
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
myNotificationsRouter
|
myNotificationsRouter
|
||||||
|
@ -88,7 +88,16 @@ async function updateNotificationSettings (req: express.Request, res: express.Re
|
||||||
async function listUserNotifications (req: express.Request, res: express.Response) {
|
async function listUserNotifications (req: express.Request, res: express.Response) {
|
||||||
const user = res.locals.oauth.token.User
|
const user = res.locals.oauth.token.User
|
||||||
|
|
||||||
const resultList = await UserNotificationModel.listForApi(user.id, req.query.start, req.query.count, req.query.sort, req.query.unread)
|
const query = req.query as UserNotificationListQuery
|
||||||
|
|
||||||
|
const resultList = await UserNotificationModel.listForApi({
|
||||||
|
userId: user.id,
|
||||||
|
start: query.start,
|
||||||
|
count: query.count,
|
||||||
|
sort: query.sort,
|
||||||
|
unread: query.unread,
|
||||||
|
typeOneOf: query.typeOneOf
|
||||||
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ const getLogsValidator = [
|
||||||
query('tagsOneOf')
|
query('tagsOneOf')
|
||||||
.optional()
|
.optional()
|
||||||
.customSanitizer(arrayify)
|
.customSanitizer(arrayify)
|
||||||
.custom(isStringArray).withMessage('Should have a valid one of tags array'),
|
.custom(isStringArray).withMessage('Should have a valid tags one of array'),
|
||||||
query('endDate')
|
query('endDate')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isDateValid).withMessage('Should have an end date that conforms to ISO 8601'),
|
.custom(isDateValid).withMessage('Should have an end date that conforms to ISO 8601'),
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
|
import { arrayify } from '@peertube/peertube-core-utils'
|
||||||
|
import { isNumberArray } from '@server/helpers/custom-validators/search.js'
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { body, query } from 'express-validator'
|
import { body, query } from 'express-validator'
|
||||||
import { isNotEmptyIntArray, toBooleanOrNull } from '../../../helpers/custom-validators/misc.js'
|
import { isNotEmptyIntArray, toBooleanOrNull } from '../../../helpers/custom-validators/misc.js'
|
||||||
import { isUserNotificationSettingValid } from '../../../helpers/custom-validators/user-notifications.js'
|
import { isUserNotificationSettingValid } from '../../../helpers/custom-validators/user-notifications.js'
|
||||||
import { areValidationErrors } from '../shared/index.js'
|
import { areValidationErrors } from '../shared/index.js'
|
||||||
|
|
||||||
const listUserNotificationsValidator = [
|
export const listUserNotificationsValidator = [
|
||||||
query('unread')
|
query('unread')
|
||||||
.optional()
|
.optional()
|
||||||
.customSanitizer(toBooleanOrNull)
|
.customSanitizer(toBooleanOrNull)
|
||||||
.isBoolean().withMessage('Should have a valid unread boolean'),
|
.isBoolean().withMessage('Should have a valid unread boolean'),
|
||||||
|
|
||||||
|
query('typeOneOf')
|
||||||
|
.optional()
|
||||||
|
.customSanitizer(arrayify)
|
||||||
|
.custom(isNumberArray).withMessage('Should have a valid typeOneOf array'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
@ -17,7 +24,7 @@ const listUserNotificationsValidator = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const updateNotificationSettingsValidator = [
|
export const updateNotificationSettingsValidator = [
|
||||||
body('newVideoFromSubscription')
|
body('newVideoFromSubscription')
|
||||||
.custom(isUserNotificationSettingValid),
|
.custom(isUserNotificationSettingValid),
|
||||||
body('newCommentOnMyVideo')
|
body('newCommentOnMyVideo')
|
||||||
|
@ -50,7 +57,7 @@ const updateNotificationSettingsValidator = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const markAsReadUserNotificationsValidator = [
|
export const markAsReadUserNotificationsValidator = [
|
||||||
body('ids')
|
body('ids')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isNotEmptyIntArray).withMessage('Should have a valid array of notification ids'),
|
.custom(isNotEmptyIntArray).withMessage('Should have a valid array of notification ids'),
|
||||||
|
@ -61,11 +68,3 @@ const markAsReadUserNotificationsValidator = [
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export {
|
|
||||||
listUserNotificationsValidator,
|
|
||||||
updateNotificationSettingsValidator,
|
|
||||||
markAsReadUserNotificationsValidator
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { Sequelize } from 'sequelize'
|
import { ActorImageType, UserNotificationType_Type } from '@peertube/peertube-models'
|
||||||
import { AbstractRunQuery, ModelBuilder } from '@server/models/shared/index.js'
|
import { AbstractRunQuery, ModelBuilder } from '@server/models/shared/index.js'
|
||||||
import { UserNotificationModelForApi } from '@server/types/models/index.js'
|
import { UserNotificationModelForApi } from '@server/types/models/index.js'
|
||||||
import { ActorImageType } from '@peertube/peertube-models'
|
import { Sequelize } from 'sequelize'
|
||||||
import { getSort } from '../../shared/index.js'
|
import { getSort } from '../../shared/index.js'
|
||||||
|
|
||||||
export interface ListNotificationsOptions {
|
export interface ListNotificationsOptions {
|
||||||
userId: number
|
userId: number
|
||||||
unread?: boolean
|
unread?: boolean
|
||||||
|
typeOneOf?: UserNotificationType_Type[]
|
||||||
|
|
||||||
sort: string
|
sort: string
|
||||||
offset: number
|
offset: number
|
||||||
limit: number
|
limit: number
|
||||||
|
@ -61,6 +63,11 @@ export class UserNotificationListQueryBuilder extends AbstractRunQuery {
|
||||||
base += 'AND "UserNotificationModel"."read" IS TRUE '
|
base += 'AND "UserNotificationModel"."read" IS TRUE '
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.typeOneOf) {
|
||||||
|
base += 'AND "UserNotificationModel"."type" IN (:typeOneOf) '
|
||||||
|
this.replacements.typeOneOf = this.options.typeOneOf
|
||||||
|
}
|
||||||
|
|
||||||
return `WHERE ${base}`
|
return `WHERE ${base}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,6 @@ import { ActorImageModel } from '../actor/actor-image.js'
|
||||||
] as (ModelIndexesOptions & { where?: WhereOptions })[]
|
] as (ModelIndexesOptions & { where?: WhereOptions })[]
|
||||||
})
|
})
|
||||||
export class UserNotificationModel extends SequelizeModel<UserNotificationModel> {
|
export class UserNotificationModel extends SequelizeModel<UserNotificationModel> {
|
||||||
|
|
||||||
@AllowNull(false)
|
@AllowNull(false)
|
||||||
@Default(null)
|
@Default(null)
|
||||||
@Is('UserNotificationType', value => throwIfNotValid(value, isUserNotificationTypeValid, 'type'))
|
@Is('UserNotificationType', value => throwIfNotValid(value, isUserNotificationTypeValid, 'type'))
|
||||||
|
@ -275,22 +274,33 @@ export class UserNotificationModel extends SequelizeModel<UserNotificationModel>
|
||||||
})
|
})
|
||||||
VideoCaption: Awaited<VideoCaptionModel>
|
VideoCaption: Awaited<VideoCaptionModel>
|
||||||
|
|
||||||
static listForApi (userId: number, start: number, count: number, sort: string, unread?: boolean) {
|
static listForApi (options: {
|
||||||
const where = { userId }
|
userId: number
|
||||||
|
start: number
|
||||||
|
count: number
|
||||||
|
sort: string
|
||||||
|
unread?: boolean
|
||||||
|
typeOneOf?: UserNotificationType_Type[]
|
||||||
|
}) {
|
||||||
|
const { userId, start, count, sort, unread, typeOneOf } = options
|
||||||
|
|
||||||
|
const countWhere = { userId }
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
userId,
|
|
||||||
unread,
|
|
||||||
offset: start,
|
offset: start,
|
||||||
limit: count,
|
limit: count,
|
||||||
sort,
|
sort,
|
||||||
where
|
|
||||||
|
userId,
|
||||||
|
unread,
|
||||||
|
typeOneOf
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unread !== undefined) query.where['read'] = !unread
|
if (unread !== undefined) countWhere['read'] = !unread
|
||||||
|
if (typeOneOf !== undefined) countWhere['type'] = { [Op.in]: typeOneOf }
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
UserNotificationModel.count({ where })
|
UserNotificationModel.count({ where: countWhere })
|
||||||
.then(count => count || 0),
|
.then(count => count || 0),
|
||||||
|
|
||||||
count === 0
|
count === 0
|
||||||
|
@ -339,31 +349,31 @@ export class UserNotificationModel extends SequelizeModel<UserNotificationModel>
|
||||||
const queries = [
|
const queries = [
|
||||||
buildAccountWhereQuery(
|
buildAccountWhereQuery(
|
||||||
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
||||||
`INNER JOIN "account" ON "userNotification"."accountId" = "account"."id" ` +
|
`INNER JOIN "account" ON "userNotification"."accountId" = "account"."id" ` +
|
||||||
`INNER JOIN actor ON "actor"."id" = "account"."actorId" `
|
`INNER JOIN actor ON "actor"."id" = "account"."actorId" `
|
||||||
),
|
),
|
||||||
|
|
||||||
// Remove notifications from muted accounts that followed ours
|
// Remove notifications from muted accounts that followed ours
|
||||||
buildAccountWhereQuery(
|
buildAccountWhereQuery(
|
||||||
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
||||||
`INNER JOIN "actorFollow" ON "actorFollow".id = "userNotification"."actorFollowId" ` +
|
`INNER JOIN "actorFollow" ON "actorFollow".id = "userNotification"."actorFollowId" ` +
|
||||||
`INNER JOIN actor ON actor.id = "actorFollow"."actorId" ` +
|
`INNER JOIN actor ON actor.id = "actorFollow"."actorId" ` +
|
||||||
`INNER JOIN account ON account."actorId" = actor.id `
|
`INNER JOIN account ON account."actorId" = actor.id `
|
||||||
),
|
),
|
||||||
|
|
||||||
// Remove notifications from muted accounts that commented something
|
// Remove notifications from muted accounts that commented something
|
||||||
buildAccountWhereQuery(
|
buildAccountWhereQuery(
|
||||||
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
||||||
`INNER JOIN "actorFollow" ON "actorFollow".id = "userNotification"."actorFollowId" ` +
|
`INNER JOIN "actorFollow" ON "actorFollow".id = "userNotification"."actorFollowId" ` +
|
||||||
`INNER JOIN actor ON actor.id = "actorFollow"."actorId" ` +
|
`INNER JOIN actor ON actor.id = "actorFollow"."actorId" ` +
|
||||||
`INNER JOIN account ON account."actorId" = actor.id `
|
`INNER JOIN account ON account."actorId" = actor.id `
|
||||||
),
|
),
|
||||||
|
|
||||||
buildAccountWhereQuery(
|
buildAccountWhereQuery(
|
||||||
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
`SELECT "userNotification"."id" FROM "userNotification" ` +
|
||||||
`INNER JOIN "videoComment" ON "videoComment".id = "userNotification"."commentId" ` +
|
`INNER JOIN "videoComment" ON "videoComment".id = "userNotification"."commentId" ` +
|
||||||
`INNER JOIN account ON account.id = "videoComment"."accountId" ` +
|
`INNER JOIN account ON account.id = "videoComment"."accountId" ` +
|
||||||
`INNER JOIN actor ON "actor"."id" = "account"."actorId" `
|
`INNER JOIN actor ON "actor"."id" = "account"."actorId" `
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -2317,6 +2317,13 @@ paths:
|
||||||
tags:
|
tags:
|
||||||
- My Notifications
|
- My Notifications
|
||||||
parameters:
|
parameters:
|
||||||
|
- name: typeOneOf
|
||||||
|
in: query
|
||||||
|
description: only list notifications of these types
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/NotificationType'
|
||||||
- name: unread
|
- name: unread
|
||||||
in: query
|
in: query
|
||||||
description: only list unread notifications
|
description: only list unread notifications
|
||||||
|
@ -10718,58 +10725,83 @@ components:
|
||||||
- `1` WEB
|
- `1` WEB
|
||||||
|
|
||||||
- `2` EMAIL
|
- `2` EMAIL
|
||||||
|
NotificationType:
|
||||||
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
- 6
|
||||||
|
- 7
|
||||||
|
- 8
|
||||||
|
- 9
|
||||||
|
- 10
|
||||||
|
- 11
|
||||||
|
- 12
|
||||||
|
- 13
|
||||||
|
- 14
|
||||||
|
- 15
|
||||||
|
- 16
|
||||||
|
- 17
|
||||||
|
- 18
|
||||||
|
- 19
|
||||||
|
- 20
|
||||||
|
- 21
|
||||||
|
- 22
|
||||||
|
description: >
|
||||||
|
Notification type. One of the following values:
|
||||||
|
|
||||||
|
- `1` NEW_VIDEO_FROM_SUBSCRIPTION
|
||||||
|
|
||||||
|
- `2` NEW_COMMENT_ON_MY_VIDEO
|
||||||
|
|
||||||
|
- `3` NEW_ABUSE_FOR_MODERATORS
|
||||||
|
|
||||||
|
- `4` BLACKLIST_ON_MY_VIDEO
|
||||||
|
|
||||||
|
- `5` UNBLACKLIST_ON_MY_VIDEO
|
||||||
|
|
||||||
|
- `6` MY_VIDEO_PUBLISHED
|
||||||
|
|
||||||
|
- `7` MY_VIDEO_IMPORT_SUCCESS
|
||||||
|
|
||||||
|
- `8` MY_VIDEO_IMPORT_ERROR
|
||||||
|
|
||||||
|
- `9` NEW_USER_REGISTRATION
|
||||||
|
|
||||||
|
- `10` NEW_FOLLOW
|
||||||
|
|
||||||
|
- `11` COMMENT_MENTION
|
||||||
|
|
||||||
|
- `12` VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
|
||||||
|
|
||||||
|
- `13` NEW_INSTANCE_FOLLOWER
|
||||||
|
|
||||||
|
- `14` AUTO_INSTANCE_FOLLOWING
|
||||||
|
|
||||||
|
- `15` ABUSE_STATE_CHANGE
|
||||||
|
|
||||||
|
- `16` ABUSE_NEW_MESSAGE
|
||||||
|
|
||||||
|
- `17` NEW_PLUGIN_VERSION
|
||||||
|
|
||||||
|
- `18` NEW_PEERTUBE_VERSION
|
||||||
|
|
||||||
|
- `19` MY_VIDEO_STUDIO_EDITION_FINISHED
|
||||||
|
|
||||||
|
- `20` NEW_USER_REGISTRATION_REQUEST
|
||||||
|
|
||||||
|
- `21` NEW_LIVE_FROM_SUBSCRIPTION
|
||||||
|
|
||||||
|
- `22` MY_VIDEO_TRANSCRIPTION_GENERATED
|
||||||
Notification:
|
Notification:
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
$ref: '#/components/schemas/id'
|
$ref: '#/components/schemas/id'
|
||||||
type:
|
type:
|
||||||
type: integer
|
$ref: '#/components/schemas/NotificationType'
|
||||||
description: >
|
|
||||||
Notification type, following the `UserNotificationType` enum:
|
|
||||||
|
|
||||||
- `1` NEW_VIDEO_FROM_SUBSCRIPTION
|
|
||||||
|
|
||||||
- `2` NEW_COMMENT_ON_MY_VIDEO
|
|
||||||
|
|
||||||
- `3` NEW_ABUSE_FOR_MODERATORS
|
|
||||||
|
|
||||||
- `4` BLACKLIST_ON_MY_VIDEO
|
|
||||||
|
|
||||||
- `5` UNBLACKLIST_ON_MY_VIDEO
|
|
||||||
|
|
||||||
- `6` MY_VIDEO_PUBLISHED
|
|
||||||
|
|
||||||
- `7` MY_VIDEO_IMPORT_SUCCESS
|
|
||||||
|
|
||||||
- `8` MY_VIDEO_IMPORT_ERROR
|
|
||||||
|
|
||||||
- `9` NEW_USER_REGISTRATION
|
|
||||||
|
|
||||||
- `10` NEW_FOLLOW
|
|
||||||
|
|
||||||
- `11` COMMENT_MENTION
|
|
||||||
|
|
||||||
- `12` VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
|
|
||||||
|
|
||||||
- `13` NEW_INSTANCE_FOLLOWER
|
|
||||||
|
|
||||||
- `14` AUTO_INSTANCE_FOLLOWING
|
|
||||||
|
|
||||||
- `15` ABUSE_STATE_CHANGE
|
|
||||||
|
|
||||||
- `16` ABUSE_NEW_MESSAGE
|
|
||||||
|
|
||||||
- `17` NEW_PLUGIN_VERSION
|
|
||||||
|
|
||||||
- `18` NEW_PEERTUBE_VERSION
|
|
||||||
|
|
||||||
- `19` MY_VIDEO_STUDIO_EDITION_FINISHED
|
|
||||||
|
|
||||||
- `20` NEW_USER_REGISTRATION_REQUEST
|
|
||||||
|
|
||||||
- `21` NEW_LIVE_FROM_SUBSCRIPTION
|
|
||||||
|
|
||||||
- `22` MY_VIDEO_TRANSCRIPTION_GENERATED
|
|
||||||
read:
|
read:
|
||||||
type: boolean
|
type: boolean
|
||||||
video:
|
video:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue