Add video abuse to activity pub
This commit is contained in:
parent
59c857da59
commit
8e13fa7d09
|
@ -11,6 +11,7 @@
|
||||||
<p-column field="reason" header="Reason"></p-column>
|
<p-column field="reason" header="Reason"></p-column>
|
||||||
<p-column field="reporterServerHost" header="Reporter server host"></p-column>
|
<p-column field="reporterServerHost" header="Reporter server host"></p-column>
|
||||||
<p-column field="reporterUsername" header="Reporter username"></p-column>
|
<p-column field="reporterUsername" header="Reporter username"></p-column>
|
||||||
|
<p-column field="videoName" header="Video name"></p-column>
|
||||||
<p-column header="Video" styleClass="action-cell">
|
<p-column header="Video" styleClass="action-cell">
|
||||||
<ng-template pTemplate="body" let-videoAbuse="rowData">
|
<ng-template pTemplate="body" let-videoAbuse="rowData">
|
||||||
<a [routerLink]="getRouterVideoLink(videoAbuse.videoId)" title="Go to the video">{{ videoAbuse.videoId }}</a>
|
<a [routerLink]="getRouterVideoLink(videoAbuse.videoId)" title="Go to the video">{{ videoAbuse.videoId }}</a>
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
} from '../../../middlewares'
|
} from '../../../middlewares'
|
||||||
import { VideoInstance } from '../../../models'
|
import { VideoInstance } from '../../../models'
|
||||||
import { VideoAbuseCreate, UserRight } from '../../../../shared'
|
import { VideoAbuseCreate, UserRight } from '../../../../shared'
|
||||||
|
import { sendVideoAbuse } from '../../../lib/index'
|
||||||
|
|
||||||
const abuseVideoRouter = express.Router()
|
const abuseVideoRouter = express.Router()
|
||||||
|
|
||||||
|
@ -63,28 +64,21 @@ async function reportVideoAbuseRetryWrapper (req: express.Request, res: express.
|
||||||
|
|
||||||
async function reportVideoAbuse (req: express.Request, res: express.Response) {
|
async function reportVideoAbuse (req: express.Request, res: express.Response) {
|
||||||
const videoInstance = res.locals.video as VideoInstance
|
const videoInstance = res.locals.video as VideoInstance
|
||||||
const reporterUsername = res.locals.oauth.token.User.username
|
const reporterAccount = res.locals.oauth.token.User.Account
|
||||||
const body: VideoAbuseCreate = req.body
|
const body: VideoAbuseCreate = req.body
|
||||||
|
|
||||||
const abuseToCreate = {
|
const abuseToCreate = {
|
||||||
reporterUsername,
|
reporterAccountId: reporterAccount.id,
|
||||||
reason: body.reason,
|
reason: body.reason,
|
||||||
videoId: videoInstance.id,
|
videoId: videoInstance.id
|
||||||
reporterServerId: null // This is our server that reported this abuse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.sequelize.transaction(async t => {
|
await db.sequelize.transaction(async t => {
|
||||||
const abuse = await db.VideoAbuse.create(abuseToCreate, { transaction: t })
|
const videoAbuseInstance = await db.VideoAbuse.create(abuseToCreate, { transaction: t })
|
||||||
// We send the information to the destination server
|
|
||||||
if (videoInstance.isOwned() === false) {
|
|
||||||
const reportData = {
|
|
||||||
reporterUsername,
|
|
||||||
reportReason: abuse.reason,
|
|
||||||
videoUUID: videoInstance.uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// await friends.reportAbuseVideoToFriend(reportData, videoInstance, t)
|
// We send the video abuse to the origin server
|
||||||
// TODO: send abuse to origin server
|
if (videoInstance.isOwned() === false) {
|
||||||
|
await sendVideoAbuse(reporterAccount, videoAbuseInstance, videoInstance, t)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,11 @@ function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObjec
|
||||||
return doRequestAndSaveToFile(options, thumbnailPath)
|
return doRequestAndSaveToFile(options, thumbnailPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActivityPubUrl (type: 'video' | 'videoChannel' | 'account', id: string) {
|
function getActivityPubUrl (type: 'video' | 'videoChannel' | 'account' | 'videoAbuse', id: string) {
|
||||||
if (type === 'video') return CONFIG.WEBSERVER.URL + '/videos/watch/' + id
|
if (type === 'video') return CONFIG.WEBSERVER.URL + '/videos/watch/' + id
|
||||||
else if (type === 'videoChannel') return CONFIG.WEBSERVER.URL + '/video-channels/' + id
|
else if (type === 'videoChannel') return CONFIG.WEBSERVER.URL + '/video-channels/' + id
|
||||||
else if (type === 'account') return CONFIG.WEBSERVER.URL + '/account/' + id
|
else if (type === 'account') return CONFIG.WEBSERVER.URL + '/account/' + id
|
||||||
|
else if (type === 'videoAbuse') return CONFIG.WEBSERVER.URL + '/admin/video-abuses/' + id
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -134,7 +135,8 @@ function activityPubContextify <T> (data: T) {
|
||||||
'nsfw': 'as:sensitive',
|
'nsfw': 'as:sensitive',
|
||||||
'language': 'http://schema.org/inLanguage',
|
'language': 'http://schema.org/inLanguage',
|
||||||
'views': 'http://schema.org/Number',
|
'views': 'http://schema.org/Number',
|
||||||
'size': 'http://schema.org/Number'
|
'size': 'http://schema.org/Number',
|
||||||
|
'VideoChannel': 'https://peertu.be/ns/VideoChannel'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
@ -112,10 +112,6 @@ function isVideoAbuseReasonValid (value: string) {
|
||||||
return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
|
return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isVideoAbuseReporterUsernameValid (value: string) {
|
|
||||||
return isUserUsernameValid(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function isVideoViewsValid (value: string) {
|
function isVideoViewsValid (value: string) {
|
||||||
return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
|
return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +205,6 @@ export {
|
||||||
isVideoThumbnailDataValid,
|
isVideoThumbnailDataValid,
|
||||||
isVideoFileExtnameValid,
|
isVideoFileExtnameValid,
|
||||||
isVideoAbuseReasonValid,
|
isVideoAbuseReasonValid,
|
||||||
isVideoAbuseReporterUsernameValid,
|
|
||||||
isVideoFile,
|
isVideoFile,
|
||||||
isVideoViewsValid,
|
isVideoViewsValid,
|
||||||
isVideoLikesValid,
|
isVideoLikesValid,
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { ActivityCreate, VideoChannelObject, VideoTorrentObject } from '../../../shared'
|
import { ActivityCreate, VideoChannelObject } from '../../../shared'
|
||||||
import { ActivityAdd } from '../../../shared/models/activitypub/activity'
|
import { VideoAbuseObject } from '../../../shared/models/activitypub/objects/video-abuse-object'
|
||||||
import { generateThumbnailFromUrl, logger, retryTransactionWrapper } from '../../helpers'
|
import { logger, retryTransactionWrapper } from '../../helpers'
|
||||||
import { database as db } from '../../initializers'
|
|
||||||
import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
|
|
||||||
import Bluebird = require('bluebird')
|
|
||||||
import { AccountInstance } from '../../models/account/account-interface'
|
|
||||||
import { getActivityPubUrl, getOrCreateAccount } from '../../helpers/activitypub'
|
import { getActivityPubUrl, getOrCreateAccount } from '../../helpers/activitypub'
|
||||||
|
import { database as db } from '../../initializers'
|
||||||
|
import { AccountInstance } from '../../models/account/account-interface'
|
||||||
|
|
||||||
async function processCreateActivity (activity: ActivityCreate) {
|
async function processCreateActivity (activity: ActivityCreate) {
|
||||||
const activityObject = activity.object
|
const activityObject = activity.object
|
||||||
|
@ -14,6 +12,8 @@ async function processCreateActivity (activity: ActivityCreate) {
|
||||||
|
|
||||||
if (activityType === 'VideoChannel') {
|
if (activityType === 'VideoChannel') {
|
||||||
return processCreateVideoChannel(account, activityObject as VideoChannelObject)
|
return processCreateVideoChannel(account, activityObject as VideoChannelObject)
|
||||||
|
} else if (activityType === 'Flag') {
|
||||||
|
return processCreateVideoAbuse(account, activityObject as VideoAbuseObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id })
|
logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id })
|
||||||
|
@ -62,3 +62,34 @@ async function addRemoteVideoChannel (account: AccountInstance, videoChannelToCr
|
||||||
|
|
||||||
logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid)
|
logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processCreateVideoAbuse (account: AccountInstance, videoAbuseToCreateData: VideoAbuseObject) {
|
||||||
|
const options = {
|
||||||
|
arguments: [ account, videoAbuseToCreateData ],
|
||||||
|
errorMessage: 'Cannot insert the remote video abuse with many retries.'
|
||||||
|
}
|
||||||
|
|
||||||
|
return retryTransactionWrapper(addRemoteVideoAbuse, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addRemoteVideoAbuse (account: AccountInstance, videoAbuseToCreateData: VideoAbuseObject) {
|
||||||
|
logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object)
|
||||||
|
|
||||||
|
return db.sequelize.transaction(async t => {
|
||||||
|
const video = await db.Video.loadByUrl(videoAbuseToCreateData.object, t)
|
||||||
|
if (!video) {
|
||||||
|
logger.warn('Unknown video %s for remote video abuse.', videoAbuseToCreateData.object)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const videoAbuseData = {
|
||||||
|
reporterAccountId: account.id,
|
||||||
|
reason: videoAbuseToCreateData.content,
|
||||||
|
videoId: video.id
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.VideoAbuse.create(videoAbuseData)
|
||||||
|
|
||||||
|
logger.info('Remote abuse for video uuid %s created', videoAbuseToCreateData.object)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
import { httpRequestJobScheduler } from '../jobs'
|
import { httpRequestJobScheduler } from '../jobs'
|
||||||
import { signObject, activityPubContextify } from '../../helpers'
|
import { signObject, activityPubContextify } from '../../helpers'
|
||||||
import { Activity } from '../../../shared'
|
import { Activity } from '../../../shared'
|
||||||
|
import { VideoAbuseInstance } from '../../models/video/video-abuse-interface'
|
||||||
|
import { getActivityPubUrl } from '../../helpers/activitypub'
|
||||||
|
|
||||||
async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) {
|
async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) {
|
||||||
const videoChannelObject = videoChannel.toActivityPubObject()
|
const videoChannelObject = videoChannel.toActivityPubObject()
|
||||||
|
@ -56,16 +58,28 @@ async function sendDeleteAccount (account: AccountInstance, t: Sequelize.Transac
|
||||||
return broadcastToFollowers(data, account, t)
|
return broadcastToFollowers(data, account, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendVideoAbuse (
|
||||||
|
fromAccount: AccountInstance,
|
||||||
|
videoAbuse: VideoAbuseInstance,
|
||||||
|
video: VideoInstance,
|
||||||
|
t: Sequelize.Transaction
|
||||||
|
) {
|
||||||
|
const url = getActivityPubUrl('videoAbuse', videoAbuse.id.toString())
|
||||||
|
const data = await createActivityData(url, fromAccount, video.url)
|
||||||
|
|
||||||
|
return unicastTo(data, video.VideoChannel.Account.sharedInboxUrl, t)
|
||||||
|
}
|
||||||
|
|
||||||
async function sendAccept (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) {
|
async function sendAccept (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) {
|
||||||
const data = await acceptActivityData(fromAccount)
|
const data = await acceptActivityData(fromAccount)
|
||||||
|
|
||||||
return unicastTo(data, toAccount, t)
|
return unicastTo(data, toAccount.inboxUrl, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendFollow (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) {
|
async function sendFollow (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) {
|
||||||
const data = await followActivityData(toAccount.url, fromAccount)
|
const data = await followActivityData(toAccount.url, fromAccount)
|
||||||
|
|
||||||
return unicastTo(data, toAccount, t)
|
return unicastTo(data, toAccount.inboxUrl, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -79,7 +93,8 @@ export {
|
||||||
sendDeleteVideo,
|
sendDeleteVideo,
|
||||||
sendDeleteAccount,
|
sendDeleteAccount,
|
||||||
sendAccept,
|
sendAccept,
|
||||||
sendFollow
|
sendFollow,
|
||||||
|
sendVideoAbuse
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -95,9 +110,9 @@ async function broadcastToFollowers (data: any, fromAccount: AccountInstance, t:
|
||||||
return httpRequestJobScheduler.createJob(t, 'httpRequestBroadcastHandler', jobPayload)
|
return httpRequestJobScheduler.createJob(t, 'httpRequestBroadcastHandler', jobPayload)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unicastTo (data: any, toAccount: AccountInstance, t: Sequelize.Transaction) {
|
async function unicastTo (data: any, toAccountUrl: string, t: Sequelize.Transaction) {
|
||||||
const jobPayload = {
|
const jobPayload = {
|
||||||
uris: [ toAccount.inboxUrl ],
|
uris: [ toAccountUrl ],
|
||||||
body: data
|
body: data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import * as Sequelize from 'sequelize'
|
|
||||||
import * as Promise from 'bluebird'
|
import * as Promise from 'bluebird'
|
||||||
|
import * as Sequelize from 'sequelize'
|
||||||
import { ServerInstance } from '../server/server-interface'
|
|
||||||
import { ResultList } from '../../../shared'
|
import { ResultList } from '../../../shared'
|
||||||
|
|
||||||
// Don't use barrel, import just what we need
|
|
||||||
import { VideoAbuse as FormattedVideoAbuse } from '../../../shared/models/videos/video-abuse.model'
|
import { VideoAbuse as FormattedVideoAbuse } from '../../../shared/models/videos/video-abuse.model'
|
||||||
|
import { AccountInstance } from '../account/account-interface'
|
||||||
|
import { ServerInstance } from '../server/server-interface'
|
||||||
|
import { VideoInstance } from './video-interface'
|
||||||
|
|
||||||
export namespace VideoAbuseMethods {
|
export namespace VideoAbuseMethods {
|
||||||
export type ToFormattedJSON = (this: VideoAbuseInstance) => FormattedVideoAbuse
|
export type ToFormattedJSON = (this: VideoAbuseInstance) => FormattedVideoAbuse
|
||||||
|
@ -18,9 +17,12 @@ export interface VideoAbuseClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoAbuseAttributes {
|
export interface VideoAbuseAttributes {
|
||||||
reporterUsername: string
|
|
||||||
reason: string
|
reason: string
|
||||||
videoId: number
|
videoId: number
|
||||||
|
reporterAccountId: number
|
||||||
|
|
||||||
|
Account?: AccountInstance
|
||||||
|
Video?: VideoInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttributes, Sequelize.Instance<VideoAbuseAttributes> {
|
export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttributes, Sequelize.Instance<VideoAbuseAttributes> {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as Sequelize from 'sequelize'
|
import * as Sequelize from 'sequelize'
|
||||||
|
|
||||||
import { CONFIG } from '../../initializers'
|
import { CONFIG } from '../../initializers'
|
||||||
import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../../helpers'
|
import { isVideoAbuseReasonValid } from '../../helpers'
|
||||||
|
|
||||||
import { addMethodsToModel, getSort } from '../utils'
|
import { addMethodsToModel, getSort } from '../utils'
|
||||||
import {
|
import {
|
||||||
|
@ -18,16 +18,6 @@ let listForApi: VideoAbuseMethods.ListForApi
|
||||||
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||||
VideoAbuse = sequelize.define<VideoAbuseInstance, VideoAbuseAttributes>('VideoAbuse',
|
VideoAbuse = sequelize.define<VideoAbuseInstance, VideoAbuseAttributes>('VideoAbuse',
|
||||||
{
|
{
|
||||||
reporterUsername: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
reporterUsernameValid: value => {
|
|
||||||
const res = isVideoAbuseReporterUsernameValid(value)
|
|
||||||
if (res === false) throw new Error('Video abuse reporter username is not valid.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reason: {
|
reason: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
@ -45,7 +35,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
||||||
fields: [ 'videoId' ]
|
fields: [ 'videoId' ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: [ 'reporterServerId' ]
|
fields: [ 'reporterAccountId' ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -69,8 +59,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
||||||
toFormattedJSON = function (this: VideoAbuseInstance) {
|
toFormattedJSON = function (this: VideoAbuseInstance) {
|
||||||
let reporterServerHost
|
let reporterServerHost
|
||||||
|
|
||||||
if (this.Server) {
|
if (this.Account.Server) {
|
||||||
reporterServerHost = this.Server.host
|
reporterServerHost = this.Account.Server.host
|
||||||
} else {
|
} else {
|
||||||
// It means it's our video
|
// It means it's our video
|
||||||
reporterServerHost = CONFIG.WEBSERVER.HOST
|
reporterServerHost = CONFIG.WEBSERVER.HOST
|
||||||
|
@ -78,10 +68,12 @@ toFormattedJSON = function (this: VideoAbuseInstance) {
|
||||||
|
|
||||||
const json = {
|
const json = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
reporterServerHost,
|
|
||||||
reason: this.reason,
|
reason: this.reason,
|
||||||
reporterUsername: this.reporterUsername,
|
reporterUsername: this.Account.name,
|
||||||
videoId: this.videoId,
|
reporterServerHost,
|
||||||
|
videoId: this.Video.id,
|
||||||
|
videoUUID: this.Video.uuid,
|
||||||
|
videoName: this.Video.name,
|
||||||
createdAt: this.createdAt
|
createdAt: this.createdAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,9 +83,9 @@ toFormattedJSON = function (this: VideoAbuseInstance) {
|
||||||
// ------------------------------ STATICS ------------------------------
|
// ------------------------------ STATICS ------------------------------
|
||||||
|
|
||||||
function associate (models) {
|
function associate (models) {
|
||||||
VideoAbuse.belongsTo(models.Server, {
|
VideoAbuse.belongsTo(models.Account, {
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
name: 'reporterServerId',
|
name: 'reporterAccountId',
|
||||||
allowNull: true
|
allowNull: true
|
||||||
},
|
},
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE'
|
||||||
|
@ -115,8 +107,18 @@ listForApi = function (start: number, count: number, sort: string) {
|
||||||
order: [ getSort(sort) ],
|
order: [ getSort(sort) ],
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoAbuse['sequelize'].models.Server,
|
model: VideoAbuse['sequelize'].models.Account,
|
||||||
required: false
|
required: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: VideoAbuse['sequelize'].models.Server,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: VideoAbuse['sequelize'].models.Video,
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import {
|
import { VideoChannelObject, VideoTorrentObject } from './objects'
|
||||||
VideoChannelObject,
|
|
||||||
VideoTorrentObject
|
|
||||||
} from './objects'
|
|
||||||
import { ActivityPubSignature } from './activitypub-signature'
|
import { ActivityPubSignature } from './activitypub-signature'
|
||||||
|
import { VideoAbuseObject } from './objects/video-abuse-object'
|
||||||
|
|
||||||
export type Activity = ActivityCreate | ActivityAdd | ActivityUpdate | ActivityFlag |
|
export type Activity = ActivityCreate | ActivityAdd | ActivityUpdate | ActivityFlag |
|
||||||
ActivityDelete | ActivityFollow | ActivityAccept
|
ActivityDelete | ActivityFollow | ActivityAccept
|
||||||
|
@ -21,7 +19,7 @@ export interface BaseActivity {
|
||||||
|
|
||||||
export interface ActivityCreate extends BaseActivity {
|
export interface ActivityCreate extends BaseActivity {
|
||||||
type: 'Create'
|
type: 'Create'
|
||||||
object: VideoChannelObject
|
object: VideoChannelObject | VideoAbuseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActivityAdd extends BaseActivity {
|
export interface ActivityAdd extends BaseActivity {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './common-objects'
|
export * from './common-objects'
|
||||||
|
export * from './video-abuse-object'
|
||||||
export * from './video-channel-object'
|
export * from './video-channel-object'
|
||||||
export * from './video-torrent-object'
|
export * from './video-torrent-object'
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface VideoAbuseObject {
|
||||||
|
type: 'Flag',
|
||||||
|
content: string
|
||||||
|
object: string
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
import { ActivityIdentifierObject } from './common-objects'
|
|
||||||
|
|
||||||
export interface VideoChannelObject {
|
export interface VideoChannelObject {
|
||||||
type: 'VideoChannel'
|
type: 'VideoChannel'
|
||||||
id: string
|
id: string
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
export interface VideoAbuse {
|
export interface VideoAbuse {
|
||||||
id: number
|
id: number
|
||||||
reporterServerHost: string
|
|
||||||
reason: string
|
reason: string
|
||||||
reporterUsername: string
|
reporterUsername: string
|
||||||
|
reporterServerHost: string
|
||||||
videoId: number
|
videoId: number
|
||||||
|
videoUUID: string
|
||||||
|
videoName: string
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue