"buildOptimizer": true,
"serviceWorker": true,
"ngswConfigPath": "src/ngsw-config.json",
+ "budgets": [
+ {
+ "type": "initial",
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ "maximumError": "5mb"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb",
+ "maximumError": "10kb"
+ }
+ ],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: dislikeObject })
return sequelizeTypescript.transaction(async t => {
- const rate = {
+ const url = getVideoDislikeActivityPubUrl(byActor, video)
+
+ const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, url)
+ if (existingRate && existingRate.type === 'dislike') return
+
+ await AccountVideoRateModel.create({
type: 'dislike' as 'dislike',
videoId: video.id,
- accountId: byAccount.id
- }
+ accountId: byAccount.id,
+ url
+ }, { transaction: t })
- const [ , created ] = await AccountVideoRateModel.findOrCreate({
- where: rate,
- defaults: Object.assign({}, rate, { url: getVideoDislikeActivityPubUrl(byActor, video) }),
- transaction: t
- })
- if (created === true) await video.increment('dislikes', { transaction: t })
+ await video.increment('dislikes', { transaction: t })
- if (video.isOwned() && created === true) {
+ if (video.isOwned()) {
// Don't resend the activity to the sender
const exceptions = [ byActor ]
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoUrl })
return sequelizeTypescript.transaction(async t => {
- const rate = {
+ const url = getVideoLikeActivityPubUrl(byActor, video)
+
+ const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, url)
+ if (existingRate && existingRate.type === 'like') return
+
+ await AccountVideoRateModel.create({
type: 'like' as 'like',
videoId: video.id,
- accountId: byAccount.id
- }
- const [ , created ] = await AccountVideoRateModel.findOrCreate({
- where: rate,
- defaults: Object.assign({}, rate, { url: getVideoLikeActivityPubUrl(byActor, video) }),
- transaction: t
- })
- if (created === true) await video.increment('likes', { transaction: t })
-
- if (video.isOwned() && created === true) {
+ accountId: byAccount.id,
+ url
+ }, { transaction: t })
+
+ await video.increment('likes', { transaction: t })
+
+ if (video.isOwned()) {
// Don't resend the activity to the sender
const exceptions = [ byActor ]
})
if (sanitizeAndCheckVideoCommentObject(body) === false) {
- logger.debug('Remote video comment JSON is not valid.', { body })
+ logger.debug('Remote video comment JSON %s is not valid.', commentUrl, { body })
return { created: false }
}
inReplyToCommentId,
videoId: obj.video.id,
accountId: obj.account.id,
- url: 'fake url'
- }, { transaction: t, validate: false } as any) // FIXME: sequelize typings
+ url: new Date().toISOString()
+ }, { transaction: t, validate: false })
- comment.set('url', getVideoCommentActivityPubUrl(obj.video, comment))
+ comment.url = getVideoCommentActivityPubUrl(obj.video, comment)
const savedComment = await comment.save({ transaction: t })
savedComment.InReplyToVideoComment = obj.inReplyToComment
return AccountVideoRateModel.findOne(options)
}
+ static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, transaction?: Transaction) {
+ const options: FindOptions = {
+ where: {
+ [ Op.or]: [
+ {
+ accountId,
+ videoId
+ },
+ {
+ url
+ }
+ ]
+ }
+ }
+ if (transaction) options.transaction = transaction
+
+ return AccountVideoRateModel.findOne(options)
+ }
+
static listByAccountForApi (options: {
start: number,
count: number,
videoId,
type
},
+ include: [
+ {
+ model: AccountModel.unscoped(),
+ required: true,
+ include: [
+ {
+ model: ActorModel.unscoped(),
+ required: true,
+ where: {
+ serverId: {
+ [Op.ne]: null
+ }
+ }
+ }
+ ]
+ }
+ ],
transaction: t
}
[Op.lt]: beforeUpdatedAt
},
videoId
- }
+ },
+ include: [
+ {
+ required: true,
+ model: AccountModel.unscoped(),
+ include: [
+ {
+ required: true,
+ model: ActorModel.unscoped(),
+ where: {
+ serverId: {
+ [Op.ne]: null
+ }
+ }
+ }
+ ]
+ }
+ ]
}
return VideoCommentModel.destroy(query)
-import * as Sequelize from 'sequelize'
import * as Bluebird from 'bluebird'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
import { throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoChannelModel } from './video-channel'
+import { Op, Transaction } from 'sequelize'
enum ScopeNames {
FULL = 'FULL',
})
Video: VideoModel
- static load (actorId: number, videoId: number, t?: Sequelize.Transaction) {
+ static load (actorId: number, videoId: number, t?: Transaction) {
return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({
where: {
actorId,
})
}
- static loadByUrl (url: string, t: Sequelize.Transaction) {
+ static loadByUrl (url: string, t: Transaction) {
return VideoShareModel.scope(ScopeNames.FULL).findOne({
where: {
url
})
}
- static loadActorsByShare (videoId: number, t: Sequelize.Transaction) {
+ static loadActorsByShare (videoId: number, t: Transaction) {
const query = {
where: {
videoId
.then(res => res.map(r => r.Actor))
}
- static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> {
+ static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<ActorModel[]> {
const query = {
attributes: [],
include: [
.then(res => res.map(r => r.Actor))
}
- static loadActorsByVideoChannel (videoChannelId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> {
+ static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<ActorModel[]> {
const query = {
attributes: [],
include: [
.then(res => res.map(r => r.Actor))
}
- static listAndCountByVideoId (videoId: number, start: number, count: number, t?: Sequelize.Transaction) {
+ static listAndCountByVideoId (videoId: number, start: number, count: number, t?: Transaction) {
const query = {
offset: start,
limit: count,
const query = {
where: {
updatedAt: {
- [Sequelize.Op.lt]: beforeUpdatedAt
+ [Op.lt]: beforeUpdatedAt
},
videoId
- }
+ },
+ include: [
+ {
+ model: ActorModel.unscoped(),
+ required: true,
+ where: {
+ serverId: {
+ [ Op.ne ]: null
+ }
+ }
+ }
+ ]
}
return VideoShareModel.destroy(query)
req.field('licence', attributes.licence.toString())
}
- for (let i = 0; i < attributes.tags.length; i++) {
+ const tags = attributes.tags || []
+ for (let i = 0; i < tags.length; i++) {
req.field('tags[' + i + ']', attributes.tags[i])
}