mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-06 03:50:26 +02:00
Type models
This commit is contained in:
parent
65fcc3119c
commit
e02643f32e
76 changed files with 1710 additions and 816 deletions
23
server/models/application-interface.ts
Normal file
23
server/models/application-interface.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace ApplicationMethods {
|
||||
export type LoadMigrationVersion = (callback: (err: Error, version: number) => void) => void
|
||||
export type UpdateMigrationVersion = (newVersion: number, transaction: any, callback: any) => void
|
||||
}
|
||||
|
||||
export interface ApplicationClass {
|
||||
loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
|
||||
updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
|
||||
}
|
||||
|
||||
export interface ApplicationAttributes {
|
||||
migrationVersion: number
|
||||
}
|
||||
|
||||
export interface ApplicationInstance extends ApplicationClass, ApplicationAttributes, Sequelize.Instance<ApplicationAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface ApplicationModel extends ApplicationClass, Sequelize.Model<ApplicationInstance, ApplicationAttributes> {}
|
|
@ -1,5 +1,20 @@
|
|||
module.exports = function (sequelize, DataTypes) {
|
||||
const Application = sequelize.define('Application',
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
ApplicationClass,
|
||||
ApplicationAttributes,
|
||||
ApplicationInstance,
|
||||
|
||||
ApplicationMethods
|
||||
} from './application-interface'
|
||||
|
||||
let Application: Sequelize.Model<ApplicationInstance, ApplicationAttributes>
|
||||
let loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
|
||||
let updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
|
||||
|
||||
export default function defineApplication (sequelize: Sequelize.Sequelize, DataTypes) {
|
||||
Application = sequelize.define<ApplicationInstance, ApplicationAttributes>('Application',
|
||||
{
|
||||
migrationVersion: {
|
||||
type: DataTypes.INTEGER,
|
||||
|
@ -9,34 +24,31 @@ module.exports = function (sequelize, DataTypes) {
|
|||
isInt: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
classMethods: {
|
||||
loadMigrationVersion,
|
||||
updateMigrationVersion
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [ loadMigrationVersion, updateMigrationVersion ]
|
||||
addMethodsToModel(Application, classMethods)
|
||||
|
||||
return Application
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function loadMigrationVersion (callback) {
|
||||
loadMigrationVersion = function (callback: (err: Error, version: number) => void) {
|
||||
const query = {
|
||||
attributes: [ 'migrationVersion' ]
|
||||
}
|
||||
|
||||
return this.findOne(query).asCallback(function (err, data) {
|
||||
return Application.findOne(query).asCallback(function (err, data) {
|
||||
const version = data ? data.migrationVersion : null
|
||||
|
||||
return callback(err, version)
|
||||
})
|
||||
}
|
||||
|
||||
function updateMigrationVersion (newVersion, transaction, callback) {
|
||||
const options: { where?: any, transaction?: any } = {
|
||||
updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) {
|
||||
const options: Sequelize.UpdateOptions = {
|
||||
where: {}
|
||||
}
|
||||
|
||||
|
@ -46,5 +58,5 @@ function updateMigrationVersion (newVersion, transaction, callback) {
|
|||
options.transaction = transaction
|
||||
}
|
||||
|
||||
return this.update({ migrationVersion: newVersion }, options).asCallback(callback)
|
||||
return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
|
||||
}
|
||||
|
|
21
server/models/author-interface.ts
Normal file
21
server/models/author-interface.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace AuthorMethods {
|
||||
export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void
|
||||
}
|
||||
|
||||
export interface AuthorClass {
|
||||
findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
|
||||
}
|
||||
|
||||
export interface AuthorAttributes {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize.Instance<AuthorAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}
|
|
@ -1,7 +1,21 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { isUserUsernameValid } from '../helpers'
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Author = sequelize.define('Author',
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
AuthorClass,
|
||||
AuthorInstance,
|
||||
AuthorAttributes,
|
||||
|
||||
AuthorMethods
|
||||
} from './author-interface'
|
||||
|
||||
let Author: Sequelize.Model<AuthorInstance, AuthorAttributes>
|
||||
let findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
|
||||
|
||||
export default function defineAuthor (sequelize: Sequelize.Sequelize, DataTypes) {
|
||||
Author = sequelize.define<AuthorInstance, AuthorAttributes>('Author',
|
||||
{
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -30,22 +44,20 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'name', 'podId' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
findOrCreateAuthor
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [ associate, findOrCreateAuthor ]
|
||||
addMethodsToModel(Author, classMethods)
|
||||
|
||||
return Author
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Pod, {
|
||||
Author.belongsTo(models.Pod, {
|
||||
foreignKey: {
|
||||
name: 'podId',
|
||||
allowNull: true
|
||||
|
@ -53,7 +65,7 @@ function associate (models) {
|
|||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.belongsTo(models.User, {
|
||||
Author.belongsTo(models.User, {
|
||||
foreignKey: {
|
||||
name: 'userId',
|
||||
allowNull: true
|
||||
|
@ -62,7 +74,7 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function findOrCreateAuthor (name, podId, userId, transaction, callback) {
|
||||
findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
|
||||
if (!callback) {
|
||||
callback = transaction
|
||||
transaction = null
|
||||
|
@ -81,7 +93,7 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) {
|
|||
|
||||
if (transaction) query.transaction = transaction
|
||||
|
||||
this.findOrCreate(query).asCallback(function (err, result) {
|
||||
Author.findOrCreate(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
// [ instance, wasCreated ]
|
||||
|
|
17
server/models/index.ts
Normal file
17
server/models/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
export * from './application-interface'
|
||||
export * from './author-interface'
|
||||
export * from './job-interface'
|
||||
export * from './oauth-client-interface'
|
||||
export * from './oauth-token-interface'
|
||||
export * from './pod-interface'
|
||||
export * from './request-interface'
|
||||
export * from './request-to-pod-interface'
|
||||
export * from './request-video-event-interface'
|
||||
export * from './request-video-qadu-interface'
|
||||
export * from './tag-interface'
|
||||
export * from './user-video-rate-interface'
|
||||
export * from './user-interface'
|
||||
export * from './video-abuse-interface'
|
||||
export * from './video-blacklist-interface'
|
||||
export * from './video-tag-interface'
|
||||
export * from './video-interface'
|
23
server/models/job-interface.ts
Normal file
23
server/models/job-interface.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace JobMethods {
|
||||
export type ListWithLimit = (limit, state, callback) => void
|
||||
}
|
||||
|
||||
export interface JobClass {
|
||||
listWithLimit: JobMethods.ListWithLimit
|
||||
}
|
||||
|
||||
export interface JobAttributes {
|
||||
state: string
|
||||
handlerName: string
|
||||
handlerInputData: object
|
||||
}
|
||||
|
||||
export interface JobInstance extends JobClass, JobAttributes, Sequelize.Instance<JobAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface JobModel extends JobClass, Sequelize.Model<JobInstance, JobAttributes> {}
|
|
@ -1,11 +1,22 @@
|
|||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { JOB_STATES } from '../initializers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
JobClass,
|
||||
JobInstance,
|
||||
JobAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Job = sequelize.define('Job',
|
||||
JobMethods
|
||||
} from './job-interface'
|
||||
|
||||
let Job: Sequelize.Model<JobInstance, JobAttributes>
|
||||
let listWithLimit: JobMethods.ListWithLimit
|
||||
|
||||
export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
|
||||
Job = sequelize.define<JobInstance, JobAttributes>('Job',
|
||||
{
|
||||
state: {
|
||||
type: DataTypes.ENUM(values(JOB_STATES)),
|
||||
|
@ -25,19 +36,19 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'state' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
listWithLimit
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [ listWithLimit ]
|
||||
addMethodsToModel(Job, classMethods)
|
||||
|
||||
return Job
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function listWithLimit (limit, state, callback) {
|
||||
listWithLimit = function (limit, state, callback) {
|
||||
const query = {
|
||||
order: [
|
||||
[ 'id', 'ASC' ]
|
||||
|
@ -48,5 +59,5 @@ function listWithLimit (limit, state, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
return this.findAll(query).asCallback(callback)
|
||||
return Job.findAll(query).asCallback(callback)
|
||||
}
|
||||
|
|
28
server/models/oauth-client-interface.ts
Normal file
28
server/models/oauth-client-interface.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace OAuthClientMethods {
|
||||
export type CountTotal = (callback) => void
|
||||
export type LoadFirstClient = (callback) => void
|
||||
export type GetByIdAndSecret = (clientId, clientSecret) => void
|
||||
}
|
||||
|
||||
export interface OAuthClientClass {
|
||||
countTotal: OAuthClientMethods.CountTotal
|
||||
loadFirstClient: OAuthClientMethods.LoadFirstClient
|
||||
getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
|
||||
}
|
||||
|
||||
export interface OAuthClientAttributes {
|
||||
clientId: string
|
||||
clientSecret: string
|
||||
grants: string[]
|
||||
redirectUris: string[]
|
||||
}
|
||||
|
||||
export interface OAuthClientInstance extends OAuthClientClass, OAuthClientAttributes, Sequelize.Instance<OAuthClientAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface OAuthClientModel extends OAuthClientClass, Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> {}
|
|
@ -1,5 +1,21 @@
|
|||
module.exports = function (sequelize, DataTypes) {
|
||||
const OAuthClient = sequelize.define('OAuthClient',
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
OAuthClientClass,
|
||||
OAuthClientInstance,
|
||||
OAuthClientAttributes,
|
||||
|
||||
OAuthClientMethods
|
||||
} from './oauth-client-interface'
|
||||
|
||||
let OAuthClient: Sequelize.Model<OAuthClientInstance, OAuthClientAttributes>
|
||||
let countTotal: OAuthClientMethods.CountTotal
|
||||
let loadFirstClient: OAuthClientMethods.LoadFirstClient
|
||||
let getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
OAuthClient = sequelize.define('OAuthClient',
|
||||
{
|
||||
clientId: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -26,29 +42,40 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'clientId', 'clientSecret' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
countTotal,
|
||||
getByIdAndSecret,
|
||||
loadFirstClient
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
countTotal,
|
||||
getByIdAndSecret,
|
||||
loadFirstClient
|
||||
]
|
||||
addMethodsToModel(OAuthClient, classMethods)
|
||||
|
||||
return OAuthClient
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function countTotal (callback) {
|
||||
return this.count().asCallback(callback)
|
||||
function associate (models) {
|
||||
OAuthClient.hasMany(models.OAuthToken, {
|
||||
foreignKey: 'oAuthClientId',
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function loadFirstClient (callback) {
|
||||
return this.findOne().asCallback(callback)
|
||||
countTotal = function (callback) {
|
||||
return OAuthClient.count().asCallback(callback)
|
||||
}
|
||||
|
||||
function getByIdAndSecret (clientId, clientSecret) {
|
||||
loadFirstClient = function (callback) {
|
||||
return OAuthClient.findOne().asCallback(callback)
|
||||
}
|
||||
|
||||
getByIdAndSecret = function (clientId, clientSecret) {
|
||||
const query = {
|
||||
where: {
|
||||
clientId: clientId,
|
||||
|
@ -56,5 +83,5 @@ function getByIdAndSecret (clientId, clientSecret) {
|
|||
}
|
||||
}
|
||||
|
||||
return this.findOne(query)
|
||||
return OAuthClient.findOne(query)
|
||||
}
|
||||
|
|
34
server/models/oauth-token-interface.ts
Normal file
34
server/models/oauth-token-interface.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { UserModel } from './user-interface'
|
||||
|
||||
export namespace OAuthTokenMethods {
|
||||
export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void
|
||||
export type GetByTokenAndPopulateUser = (bearerToken) => void
|
||||
export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any
|
||||
export type RemoveByUserId = (userId, callback) => void
|
||||
}
|
||||
|
||||
export interface OAuthTokenClass {
|
||||
getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
|
||||
getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
|
||||
getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
|
||||
removeByUserId: OAuthTokenMethods.RemoveByUserId
|
||||
}
|
||||
|
||||
export interface OAuthTokenAttributes {
|
||||
accessToken: string
|
||||
accessTokenExpiresAt: Date
|
||||
refreshToken: string
|
||||
refreshTokenExpiresAt: Date
|
||||
|
||||
User?: UserModel
|
||||
}
|
||||
|
||||
export interface OAuthTokenInstance extends OAuthTokenClass, OAuthTokenAttributes, Sequelize.Instance<OAuthTokenAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface OAuthTokenModel extends OAuthTokenClass, Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> {}
|
|
@ -1,9 +1,24 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { logger } from '../helpers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
OAuthTokenClass,
|
||||
OAuthTokenInstance,
|
||||
OAuthTokenAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const OAuthToken = sequelize.define('OAuthToken',
|
||||
OAuthTokenMethods
|
||||
} from './oauth-token-interface'
|
||||
|
||||
let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
|
||||
let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
|
||||
let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
|
||||
let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
|
||||
let removeByUserId: OAuthTokenMethods.RemoveByUserId
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
OAuthToken = sequelize.define('OAuthToken',
|
||||
{
|
||||
accessToken: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -38,25 +53,27 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'oAuthClientId' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
getByRefreshTokenAndPopulateClient,
|
||||
getByTokenAndPopulateUser,
|
||||
getByRefreshTokenAndPopulateUser,
|
||||
removeByUserId
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
getByRefreshTokenAndPopulateClient,
|
||||
getByTokenAndPopulateUser,
|
||||
getByRefreshTokenAndPopulateUser,
|
||||
removeByUserId
|
||||
]
|
||||
addMethodsToModel(OAuthToken, classMethods)
|
||||
|
||||
return OAuthToken
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.User, {
|
||||
OAuthToken.belongsTo(models.User, {
|
||||
foreignKey: {
|
||||
name: 'userId',
|
||||
allowNull: false
|
||||
|
@ -64,7 +81,7 @@ function associate (models) {
|
|||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.belongsTo(models.OAuthClient, {
|
||||
OAuthToken.belongsTo(models.OAuthClient, {
|
||||
foreignKey: {
|
||||
name: 'oAuthClientId',
|
||||
allowNull: false
|
||||
|
@ -73,25 +90,25 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function getByRefreshTokenAndPopulateClient (refreshToken) {
|
||||
getByRefreshTokenAndPopulateClient = function (refreshToken) {
|
||||
const query = {
|
||||
where: {
|
||||
refreshToken: refreshToken
|
||||
},
|
||||
include: [ this.associations.OAuthClient ]
|
||||
include: [ OAuthToken['sequelize'].models.OAuthClient ]
|
||||
}
|
||||
|
||||
return this.findOne(query).then(function (token) {
|
||||
return OAuthToken.findOne(query).then(function (token) {
|
||||
if (!token) return token
|
||||
|
||||
const tokenInfos = {
|
||||
refreshToken: token.refreshToken,
|
||||
refreshTokenExpiresAt: token.refreshTokenExpiresAt,
|
||||
client: {
|
||||
id: token.client.id
|
||||
id: token['client'].id
|
||||
},
|
||||
user: {
|
||||
id: token.user
|
||||
id: token['user']
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,42 +118,42 @@ function getByRefreshTokenAndPopulateClient (refreshToken) {
|
|||
})
|
||||
}
|
||||
|
||||
function getByTokenAndPopulateUser (bearerToken) {
|
||||
getByTokenAndPopulateUser = function (bearerToken) {
|
||||
const query = {
|
||||
where: {
|
||||
accessToken: bearerToken
|
||||
},
|
||||
include: [ this.sequelize.models.User ]
|
||||
include: [ OAuthToken['sequelize'].models.User ]
|
||||
}
|
||||
|
||||
return this.findOne(query).then(function (token) {
|
||||
if (token) token.user = token.User
|
||||
return OAuthToken.findOne(query).then(function (token) {
|
||||
if (token) token['user'] = token.User
|
||||
|
||||
return token
|
||||
})
|
||||
}
|
||||
|
||||
function getByRefreshTokenAndPopulateUser (refreshToken) {
|
||||
getByRefreshTokenAndPopulateUser = function (refreshToken) {
|
||||
const query = {
|
||||
where: {
|
||||
refreshToken: refreshToken
|
||||
},
|
||||
include: [ this.sequelize.models.User ]
|
||||
include: [ OAuthToken['sequelize'].models.User ]
|
||||
}
|
||||
|
||||
return this.findOne(query).then(function (token) {
|
||||
token.user = token.User
|
||||
return OAuthToken.findOne(query).then(function (token) {
|
||||
token['user'] = token.User
|
||||
|
||||
return token
|
||||
})
|
||||
}
|
||||
|
||||
function removeByUserId (userId, callback) {
|
||||
removeByUserId = function (userId, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
userId: userId
|
||||
}
|
||||
}
|
||||
|
||||
return this.destroy(query).asCallback(callback)
|
||||
return OAuthToken.destroy(query).asCallback(callback)
|
||||
}
|
||||
|
|
46
server/models/pod-interface.ts
Normal file
46
server/models/pod-interface.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace PodMethods {
|
||||
export type ToFormatedJSON = () => void
|
||||
|
||||
export type CountAll = (callback) => void
|
||||
export type IncrementScores = (ids, value, callback) => void
|
||||
export type List = (callback) => void
|
||||
export type ListAllIds = (transaction, callback) => void
|
||||
export type ListRandomPodIdsWithRequest = (limit, tableWithPods, tableWithPodsJoins, callback) => void
|
||||
export type ListBadPods = (callback) => void
|
||||
export type Load = (id, callback) => void
|
||||
export type LoadByHost = (host, callback) => void
|
||||
export type RemoveAll = (callback) => void
|
||||
export type UpdatePodsScore = (goodPods, badPods) => void
|
||||
}
|
||||
|
||||
export interface PodClass {
|
||||
countAll: PodMethods.CountAll
|
||||
incrementScores: PodMethods.IncrementScores
|
||||
list: PodMethods.List
|
||||
listAllIds: PodMethods.ListAllIds
|
||||
listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
|
||||
listBadPods: PodMethods.ListBadPods
|
||||
load: PodMethods.Load
|
||||
loadByHost: PodMethods.LoadByHost
|
||||
removeAll: PodMethods.RemoveAll
|
||||
updatePodsScore: PodMethods.UpdatePodsScore
|
||||
}
|
||||
|
||||
export interface PodAttributes {
|
||||
host?: string
|
||||
publicKey?: string
|
||||
score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
|
||||
email?: string
|
||||
}
|
||||
|
||||
export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
|
||||
toFormatedJSON: PodMethods.ToFormatedJSON,
|
||||
}
|
||||
|
||||
export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}
|
|
@ -1,13 +1,34 @@
|
|||
import { each, waterfall } from 'async'
|
||||
import { map } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { FRIEND_SCORE, PODS_SCORE } from '../initializers'
|
||||
import { logger, isHostValid } from '../helpers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
PodClass,
|
||||
PodInstance,
|
||||
PodAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Pod = sequelize.define('Pod',
|
||||
PodMethods
|
||||
} from './pod-interface'
|
||||
|
||||
let Pod: Sequelize.Model<PodInstance, PodAttributes>
|
||||
let toFormatedJSON: PodMethods.ToFormatedJSON
|
||||
let countAll: PodMethods.CountAll
|
||||
let incrementScores: PodMethods.IncrementScores
|
||||
let list: PodMethods.List
|
||||
let listAllIds: PodMethods.ListAllIds
|
||||
let listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
|
||||
let listBadPods: PodMethods.ListBadPods
|
||||
let load: PodMethods.Load
|
||||
let loadByHost: PodMethods.LoadByHost
|
||||
let removeAll: PodMethods.RemoveAll
|
||||
let updatePodsScore: PodMethods.UpdatePodsScore
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
Pod = sequelize.define('Pod',
|
||||
{
|
||||
host: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -49,33 +70,33 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'score' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
countAll,
|
||||
incrementScores,
|
||||
list,
|
||||
listAllIds,
|
||||
listRandomPodIdsWithRequest,
|
||||
listBadPods,
|
||||
load,
|
||||
loadByHost,
|
||||
updatePodsScore,
|
||||
removeAll
|
||||
},
|
||||
instanceMethods: {
|
||||
toFormatedJSON
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
countAll,
|
||||
incrementScores,
|
||||
list,
|
||||
listAllIds,
|
||||
listRandomPodIdsWithRequest,
|
||||
listBadPods,
|
||||
load,
|
||||
loadByHost,
|
||||
updatePodsScore,
|
||||
removeAll
|
||||
]
|
||||
const instanceMethods = [ toFormatedJSON ]
|
||||
addMethodsToModel(Pod, classMethods, instanceMethods)
|
||||
|
||||
return Pod
|
||||
}
|
||||
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function toFormatedJSON () {
|
||||
toFormatedJSON = function () {
|
||||
const json = {
|
||||
id: this.id,
|
||||
host: this.host,
|
||||
|
@ -90,22 +111,22 @@ function toFormatedJSON () {
|
|||
// ------------------------------ Statics ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsToMany(models.Request, {
|
||||
Pod.belongsToMany(models.Request, {
|
||||
foreignKey: 'podId',
|
||||
through: models.RequestToPod,
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function countAll (callback) {
|
||||
return this.count().asCallback(callback)
|
||||
countAll = function (callback) {
|
||||
return Pod.count().asCallback(callback)
|
||||
}
|
||||
|
||||
function incrementScores (ids, value, callback) {
|
||||
incrementScores = function (ids, value, callback) {
|
||||
if (!callback) callback = function () { /* empty */ }
|
||||
|
||||
const update = {
|
||||
score: this.sequelize.literal('score +' + value)
|
||||
score: Sequelize.literal('score +' + value)
|
||||
}
|
||||
|
||||
const options = {
|
||||
|
@ -118,14 +139,14 @@ function incrementScores (ids, value, callback) {
|
|||
validate: false
|
||||
}
|
||||
|
||||
return this.update(update, options).asCallback(callback)
|
||||
return Pod.update(update, options).asCallback(callback)
|
||||
}
|
||||
|
||||
function list (callback) {
|
||||
return this.findAll().asCallback(callback)
|
||||
list = function (callback) {
|
||||
return Pod.findAll().asCallback(callback)
|
||||
}
|
||||
|
||||
function listAllIds (transaction, callback) {
|
||||
listAllIds = function (transaction, callback) {
|
||||
if (!callback) {
|
||||
callback = transaction
|
||||
transaction = null
|
||||
|
@ -137,22 +158,20 @@ function listAllIds (transaction, callback) {
|
|||
|
||||
if (transaction) query.transaction = transaction
|
||||
|
||||
return this.findAll(query).asCallback(function (err, pods) {
|
||||
return Pod.findAll(query).asCallback(function (err, pods) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, map(pods, 'id'))
|
||||
})
|
||||
}
|
||||
|
||||
function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins, callback) {
|
||||
listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) {
|
||||
if (!callback) {
|
||||
callback = tableWithPodsJoins
|
||||
tableWithPodsJoins = ''
|
||||
}
|
||||
|
||||
const self = this
|
||||
|
||||
self.count().asCallback(function (err, count) {
|
||||
Pod.count().asCallback(function (err, count) {
|
||||
if (err) return callback(err)
|
||||
|
||||
// Optimization...
|
||||
|
@ -171,13 +190,13 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
|
|||
where: {
|
||||
id: {
|
||||
$in: [
|
||||
this.sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
|
||||
Sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.findAll(query).asCallback(function (err, pods) {
|
||||
return Pod.findAll(query).asCallback(function (err, pods) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, map(pods, 'id'))
|
||||
|
@ -185,49 +204,47 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
|
|||
})
|
||||
}
|
||||
|
||||
function listBadPods (callback) {
|
||||
listBadPods = function (callback) {
|
||||
const query = {
|
||||
where: {
|
||||
score: { $lte: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
return this.findAll(query).asCallback(callback)
|
||||
return Pod.findAll(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function load (id, callback) {
|
||||
return this.findById(id).asCallback(callback)
|
||||
load = function (id, callback) {
|
||||
return Pod.findById(id).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadByHost (host, callback) {
|
||||
loadByHost = function (host, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
host: host
|
||||
}
|
||||
}
|
||||
|
||||
return this.findOne(query).asCallback(callback)
|
||||
return Pod.findOne(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function removeAll (callback) {
|
||||
return this.destroy().asCallback(callback)
|
||||
removeAll = function (callback) {
|
||||
return Pod.destroy().asCallback(callback)
|
||||
}
|
||||
|
||||
function updatePodsScore (goodPods, badPods) {
|
||||
const self = this
|
||||
|
||||
updatePodsScore = function (goodPods, badPods) {
|
||||
logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
|
||||
|
||||
if (goodPods.length !== 0) {
|
||||
this.incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
|
||||
incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
|
||||
if (err) logger.error('Cannot increment scores of good pods.', { error: err })
|
||||
})
|
||||
}
|
||||
|
||||
if (badPods.length !== 0) {
|
||||
this.incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
|
||||
incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
|
||||
if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
|
||||
removeBadPods.call(self)
|
||||
removeBadPods()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -236,11 +253,9 @@ function updatePodsScore (goodPods, badPods) {
|
|||
|
||||
// Remove pods with a score of 0 (too many requests where they were unreachable)
|
||||
function removeBadPods () {
|
||||
const self = this
|
||||
|
||||
waterfall([
|
||||
function findBadPods (callback) {
|
||||
self.sequelize.models.Pod.listBadPods(function (err, pods) {
|
||||
listBadPods(function (err, pods) {
|
||||
if (err) {
|
||||
logger.error('Cannot find bad pods.', { error: err })
|
||||
return callback(err)
|
||||
|
|
32
server/models/request-interface.ts
Normal file
32
server/models/request-interface.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { PodAttributes } from './pod-interface'
|
||||
|
||||
export namespace RequestMethods {
|
||||
export type CountTotalRequests = (callback) => void
|
||||
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
|
||||
export type RemoveWithEmptyTo = (callback) => void
|
||||
export type RemoveAll = (callback) => void
|
||||
}
|
||||
|
||||
export interface RequestClass {
|
||||
countTotalRequests: RequestMethods.CountTotalRequests
|
||||
listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
|
||||
removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
|
||||
removeAll: RequestMethods.RemoveAll
|
||||
}
|
||||
|
||||
export interface RequestAttributes {
|
||||
request: object
|
||||
endpoint: string
|
||||
}
|
||||
|
||||
export interface RequestInstance extends Sequelize.Instance<RequestAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
|
||||
setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
|
||||
}
|
||||
|
||||
export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}
|
20
server/models/request-to-pod-interface.ts
Normal file
20
server/models/request-to-pod-interface.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace RequestToPodMethods {
|
||||
export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void
|
||||
}
|
||||
|
||||
export interface RequestToPodClass {
|
||||
removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
|
||||
}
|
||||
|
||||
export interface RequestToPodAttributes {
|
||||
}
|
||||
|
||||
export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface RequestToPodModel extends RequestToPodClass, Sequelize.Model<RequestToPodInstance, RequestToPodAttributes> {}
|
|
@ -1,5 +1,19 @@
|
|||
module.exports = function (sequelize, DataTypes) {
|
||||
const RequestToPod = sequelize.define('RequestToPod', {}, {
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
RequestToPodClass,
|
||||
RequestToPodInstance,
|
||||
RequestToPodAttributes,
|
||||
|
||||
RequestToPodMethods
|
||||
} from './request-to-pod-interface'
|
||||
|
||||
let RequestToPod: Sequelize.Model<RequestToPodInstance, RequestToPodAttributes>
|
||||
let removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
RequestToPod = sequelize.define('RequestToPod', {}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: [ 'requestId' ]
|
||||
|
@ -11,18 +25,20 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'requestId', 'podId' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
removeByRequestIdsAndPod
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const classMethods = [
|
||||
removeByRequestIdsAndPod
|
||||
]
|
||||
addMethodsToModel(RequestToPod, classMethods)
|
||||
|
||||
return RequestToPod
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function removeByRequestIdsAndPod (requestsIds, podId, callback) {
|
||||
removeByRequestIdsAndPod = function (requestsIds, podId, callback) {
|
||||
if (!callback) callback = function () { /* empty */ }
|
||||
|
||||
const query = {
|
||||
|
@ -34,5 +50,5 @@ function removeByRequestIdsAndPod (requestsIds, podId, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
this.destroy(query).asCallback(callback)
|
||||
RequestToPod.destroy(query).asCallback(callback)
|
||||
}
|
||||
|
|
26
server/models/request-video-event-interface.ts
Normal file
26
server/models/request-video-event-interface.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace RequestVideoEventMethods {
|
||||
export type CountTotalRequests = (callback) => void
|
||||
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
|
||||
export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
|
||||
export type RemoveAll = (callback) => void
|
||||
}
|
||||
|
||||
export interface RequestVideoEventClass {
|
||||
countTotalRequests: RequestVideoEventMethods.CountTotalRequests
|
||||
listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
|
||||
removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
|
||||
removeAll: RequestVideoEventMethods.RemoveAll
|
||||
}
|
||||
|
||||
export interface RequestVideoEventAttributes {
|
||||
type: string
|
||||
count: number
|
||||
}
|
||||
|
||||
export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}
|
|
@ -3,14 +3,28 @@
|
|||
*/
|
||||
|
||||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
|
||||
import { isVideoEventCountValid } from '../helpers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
RequestVideoEventClass,
|
||||
RequestVideoEventInstance,
|
||||
RequestVideoEventAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const RequestVideoEvent = sequelize.define('RequestVideoEvent',
|
||||
RequestVideoEventMethods
|
||||
} from './request-video-event-interface'
|
||||
|
||||
let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
|
||||
let countTotalRequests: RequestVideoEventMethods.CountTotalRequests
|
||||
let listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
|
||||
let removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
|
||||
let removeAll: RequestVideoEventMethods.RemoveAll
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
RequestVideoEvent = sequelize.define('RequestVideoEvent',
|
||||
{
|
||||
type: {
|
||||
type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)),
|
||||
|
@ -33,26 +47,27 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'videoId' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeByRequestIdsAndPod
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeByRequestIdsAndPod
|
||||
]
|
||||
addMethodsToModel(RequestVideoEvent, classMethods)
|
||||
|
||||
return RequestVideoEvent
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Video, {
|
||||
RequestVideoEvent.belongsTo(models.Video, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
|
@ -61,14 +76,13 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function countTotalRequests (callback) {
|
||||
countTotalRequests = function (callback) {
|
||||
const query = {}
|
||||
return this.count(query).asCallback(callback)
|
||||
return RequestVideoEvent.count(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
||||
const self = this
|
||||
const Pod = this.sequelize.models.Pod
|
||||
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
|
||||
const Pod = RequestVideoEvent['sequelize'].models.Pod
|
||||
|
||||
// We make a join between videos and authors to find the podId of our video event requests
|
||||
const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
|
||||
|
@ -86,13 +100,13 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
],
|
||||
include: [
|
||||
{
|
||||
model: self.sequelize.models.Video,
|
||||
model: RequestVideoEvent['sequelize'].models.Video,
|
||||
include: [
|
||||
{
|
||||
model: self.sequelize.models.Author,
|
||||
model: RequestVideoEvent['sequelize'].models.Author,
|
||||
include: [
|
||||
{
|
||||
model: self.sequelize.models.Pod,
|
||||
model: RequestVideoEvent['sequelize'].models.Pod,
|
||||
where: {
|
||||
id: {
|
||||
$in: podIds
|
||||
|
@ -106,7 +120,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
]
|
||||
}
|
||||
|
||||
self.findAll(query).asCallback(function (err, requests) {
|
||||
RequestVideoEvent.findAll(query).asCallback(function (err, requests) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
|
||||
|
@ -115,7 +129,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function removeByRequestIdsAndPod (ids, podId, callback) {
|
||||
removeByRequestIdsAndPod = function (ids, podId, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
id: {
|
||||
|
@ -124,10 +138,10 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
|
|||
},
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Video,
|
||||
model: RequestVideoEvent['sequelize'].models.Video,
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Author,
|
||||
model: RequestVideoEvent['sequelize'].models.Author,
|
||||
where: {
|
||||
podId
|
||||
}
|
||||
|
@ -137,12 +151,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
|
|||
]
|
||||
}
|
||||
|
||||
this.destroy(query).asCallback(callback)
|
||||
RequestVideoEvent.destroy(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function removeAll (callback) {
|
||||
removeAll = function (callback) {
|
||||
// Delete all requests
|
||||
this.truncate({ cascade: true }).asCallback(callback)
|
||||
RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
25
server/models/request-video-qadu-interface.ts
Normal file
25
server/models/request-video-qadu-interface.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace RequestVideoQaduMethods {
|
||||
export type CountTotalRequests = (callback) => void
|
||||
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
|
||||
export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
|
||||
export type RemoveAll = (callback) => void
|
||||
}
|
||||
|
||||
export interface RequestVideoQaduClass {
|
||||
countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
|
||||
listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
|
||||
removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
|
||||
removeAll: RequestVideoQaduMethods.RemoveAll
|
||||
}
|
||||
|
||||
export interface RequestVideoQaduAttributes {
|
||||
type: string
|
||||
}
|
||||
|
||||
export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}
|
|
@ -10,13 +10,27 @@
|
|||
*/
|
||||
|
||||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
RequestVideoQaduClass,
|
||||
RequestVideoQaduInstance,
|
||||
RequestVideoQaduAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const RequestVideoQadu = sequelize.define('RequestVideoQadu',
|
||||
RequestVideoQaduMethods
|
||||
} from './request-video-qadu-interface'
|
||||
|
||||
let RequestVideoQadu: Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes>
|
||||
let countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
|
||||
let listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
|
||||
let removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
|
||||
let removeAll: RequestVideoQaduMethods.RemoveAll
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
RequestVideoQadu = sequelize.define('RequestVideoQadu',
|
||||
{
|
||||
type: {
|
||||
type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)),
|
||||
|
@ -32,26 +46,27 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'videoId' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeByRequestIdsAndPod
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeByRequestIdsAndPod
|
||||
]
|
||||
addMethodsToModel(RequestVideoQadu, classMethods)
|
||||
|
||||
return RequestVideoQadu
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Pod, {
|
||||
RequestVideoQadu.belongsTo(models.Pod, {
|
||||
foreignKey: {
|
||||
name: 'podId',
|
||||
allowNull: false
|
||||
|
@ -59,7 +74,7 @@ function associate (models) {
|
|||
onDelete: 'CASCADE'
|
||||
})
|
||||
|
||||
this.belongsTo(models.Video, {
|
||||
RequestVideoQadu.belongsTo(models.Video, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
|
@ -68,14 +83,13 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function countTotalRequests (callback) {
|
||||
countTotalRequests = function (callback) {
|
||||
const query = {}
|
||||
return this.count(query).asCallback(callback)
|
||||
return RequestVideoQadu.count(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
||||
const self = this
|
||||
const Pod = this.sequelize.models.Pod
|
||||
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
|
||||
const Pod = RequestVideoQadu['sequelize'].models.Pod
|
||||
|
||||
Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) {
|
||||
if (err) return callback(err)
|
||||
|
@ -86,7 +100,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
const query = {
|
||||
include: [
|
||||
{
|
||||
model: self.sequelize.models.Pod,
|
||||
model: RequestVideoQadu['sequelize'].models.Pod,
|
||||
where: {
|
||||
id: {
|
||||
$in: podIds
|
||||
|
@ -94,12 +108,12 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
}
|
||||
},
|
||||
{
|
||||
model: self.sequelize.models.Video
|
||||
model: RequestVideoQadu['sequelize'].models.Video
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
self.findAll(query).asCallback(function (err, requests) {
|
||||
RequestVideoQadu.findAll(query).asCallback(function (err, requests) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
|
||||
|
@ -108,7 +122,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function removeByRequestIdsAndPod (ids, podId, callback) {
|
||||
removeByRequestIdsAndPod = function (ids, podId, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
id: {
|
||||
|
@ -118,12 +132,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
this.destroy(query).asCallback(callback)
|
||||
RequestVideoQadu.destroy(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function removeAll (callback) {
|
||||
removeAll = function (callback) {
|
||||
// Delete all requests
|
||||
this.truncate({ cascade: true }).asCallback(callback)
|
||||
RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { REQUEST_ENDPOINTS } from '../initializers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
RequestClass,
|
||||
RequestInstance,
|
||||
RequestAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Request = sequelize.define('Request',
|
||||
RequestMethods
|
||||
} from './request-interface'
|
||||
|
||||
let Request: Sequelize.Model<RequestInstance, RequestAttributes>
|
||||
let countTotalRequests: RequestMethods.CountTotalRequests
|
||||
let listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
|
||||
let removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
|
||||
let removeAll: RequestMethods.RemoveAll
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
Request = sequelize.define('Request',
|
||||
{
|
||||
request: {
|
||||
type: DataTypes.JSON,
|
||||
|
@ -15,27 +29,27 @@ module.exports = function (sequelize, DataTypes) {
|
|||
type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)),
|
||||
allowNull: false
|
||||
}
|
||||
},
|
||||
{
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeWithEmptyTo
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
listWithLimitAndRandom,
|
||||
|
||||
countTotalRequests,
|
||||
removeAll,
|
||||
removeWithEmptyTo
|
||||
]
|
||||
addMethodsToModel(Request, classMethods)
|
||||
|
||||
return Request
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsToMany(models.Pod, {
|
||||
Request.belongsToMany(models.Pod, {
|
||||
foreignKey: {
|
||||
name: 'requestId',
|
||||
allowNull: false
|
||||
|
@ -45,19 +59,18 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function countTotalRequests (callback) {
|
||||
countTotalRequests = function (callback) {
|
||||
// We need to include Pod because there are no cascade delete when a pod is removed
|
||||
// So we could count requests that do not have existing pod anymore
|
||||
const query = {
|
||||
include: [ this.sequelize.models.Pod ]
|
||||
include: [ Request['sequelize'].models.Pod ]
|
||||
}
|
||||
|
||||
return this.count(query).asCallback(callback)
|
||||
return Request.count(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
||||
const self = this
|
||||
const Pod = this.sequelize.models.Pod
|
||||
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
|
||||
const Pod = Request['sequelize'].models.Pod
|
||||
|
||||
Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) {
|
||||
if (err) return callback(err)
|
||||
|
@ -73,7 +86,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
],
|
||||
include: [
|
||||
{
|
||||
model: self.sequelize.models.Pod,
|
||||
model: Request['sequelize'].models.Pod,
|
||||
where: {
|
||||
id: {
|
||||
$in: podIds
|
||||
|
@ -83,7 +96,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
]
|
||||
}
|
||||
|
||||
self.findAll(query).asCallback(function (err, requests) {
|
||||
Request.findAll(query).asCallback(function (err, requests) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
|
||||
|
@ -92,25 +105,25 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function removeAll (callback) {
|
||||
removeAll = function (callback) {
|
||||
// Delete all requests
|
||||
this.truncate({ cascade: true }).asCallback(callback)
|
||||
Request.truncate({ cascade: true }).asCallback(callback)
|
||||
}
|
||||
|
||||
function removeWithEmptyTo (callback) {
|
||||
removeWithEmptyTo = function (callback) {
|
||||
if (!callback) callback = function () { /* empty */ }
|
||||
|
||||
const query = {
|
||||
where: {
|
||||
id: {
|
||||
$notIn: [
|
||||
this.sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
|
||||
Sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.destroy(query).asCallback(callback)
|
||||
Request.destroy(query).asCallback(callback)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
19
server/models/tag-interface.ts
Normal file
19
server/models/tag-interface.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace TagMethods {
|
||||
export type FindOrCreateTags = (tags, transaction, callback) => void
|
||||
}
|
||||
|
||||
export interface TagClass {
|
||||
findOrCreateTags: TagMethods.FindOrCreateTags
|
||||
}
|
||||
|
||||
export interface TagAttributes {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface TagInstance extends TagClass, TagAttributes, Sequelize.Instance<TagAttributes> {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface TagModel extends TagClass, Sequelize.Model<TagInstance, TagAttributes> {}
|
|
@ -1,9 +1,20 @@
|
|||
import { each } from 'async'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
TagClass,
|
||||
TagInstance,
|
||||
TagAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Tag = sequelize.define('Tag',
|
||||
TagMethods
|
||||
} from './tag-interface'
|
||||
|
||||
let Tag: Sequelize.Model<TagInstance, TagAttributes>
|
||||
let findOrCreateTags: TagMethods.FindOrCreateTags
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
Tag = sequelize.define('Tag',
|
||||
{
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -17,35 +28,36 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'name' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
findOrCreateTags
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
findOrCreateTags
|
||||
]
|
||||
addMethodsToModel(Tag, classMethods)
|
||||
|
||||
return Tag
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsToMany(models.Video, {
|
||||
Tag.belongsToMany(models.Video, {
|
||||
foreignKey: 'tagId',
|
||||
through: models.VideoTag,
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function findOrCreateTags (tags, transaction, callback) {
|
||||
findOrCreateTags = function (tags, transaction, callback) {
|
||||
if (!callback) {
|
||||
callback = transaction
|
||||
transaction = null
|
||||
}
|
||||
|
||||
const self = this
|
||||
const tagInstances = []
|
||||
|
||||
each(tags, function (tag, callbackEach) {
|
||||
|
@ -60,7 +72,7 @@ function findOrCreateTags (tags, transaction, callback) {
|
|||
|
||||
if (transaction) query.transaction = transaction
|
||||
|
||||
self.findOrCreate(query).asCallback(function (err, res) {
|
||||
Tag.findOrCreate(query).asCallback(function (err, res) {
|
||||
if (err) return callbackEach(err)
|
||||
|
||||
// res = [ tag, isCreated ]
|
||||
|
|
45
server/models/user-interface.ts
Normal file
45
server/models/user-interface.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace UserMethods {
|
||||
export type IsPasswordMatch = (password, callback) => void
|
||||
export type ToFormatedJSON = () => void
|
||||
export type IsAdmin = () => boolean
|
||||
|
||||
export type CountTotal = (callback) => void
|
||||
export type GetByUsername = (username) => any
|
||||
export type List = (callback) => void
|
||||
export type ListForApi = (start, count, sort, callback) => void
|
||||
export type LoadById = (id, callback) => void
|
||||
export type LoadByUsername = (username, callback) => void
|
||||
export type LoadByUsernameOrEmail = (username, email, callback) => void
|
||||
}
|
||||
|
||||
export interface UserClass {
|
||||
isPasswordMatch: UserMethods.IsPasswordMatch,
|
||||
toFormatedJSON: UserMethods.ToFormatedJSON,
|
||||
isAdmin: UserMethods.IsAdmin,
|
||||
|
||||
countTotal: UserMethods.CountTotal,
|
||||
getByUsername: UserMethods.GetByUsername,
|
||||
list: UserMethods.List,
|
||||
listForApi: UserMethods.ListForApi,
|
||||
loadById: UserMethods.LoadById,
|
||||
loadByUsername: UserMethods.LoadByUsername,
|
||||
loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
|
||||
}
|
||||
|
||||
export interface UserAttributes {
|
||||
password: string
|
||||
username: string
|
||||
email: string
|
||||
displayNSFW?: boolean
|
||||
role: string
|
||||
}
|
||||
|
||||
export interface UserInstance extends UserClass, UserAttributes, Sequelize.Instance<UserAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface UserModel extends UserClass, Sequelize.Model<UserInstance, UserAttributes> {}
|
21
server/models/user-video-rate-interface.ts
Normal file
21
server/models/user-video-rate-interface.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace UserVideoRateMethods {
|
||||
export type Load = (userId, videoId, transaction, callback) => void
|
||||
}
|
||||
|
||||
export interface UserVideoRateClass {
|
||||
load: UserVideoRateMethods.Load
|
||||
}
|
||||
|
||||
export interface UserVideoRateAttributes {
|
||||
type: string
|
||||
}
|
||||
|
||||
export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface UserVideoRateModel extends UserVideoRateClass, Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes> {}
|
|
@ -3,13 +3,24 @@
|
|||
|
||||
*/
|
||||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { VIDEO_RATE_TYPES } from '../initializers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
UserVideoRateClass,
|
||||
UserVideoRateInstance,
|
||||
UserVideoRateAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const UserVideoRate = sequelize.define('UserVideoRate',
|
||||
UserVideoRateMethods
|
||||
} from './user-video-rate-interface'
|
||||
|
||||
let UserVideoRate: Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes>
|
||||
let load: UserVideoRateMethods.Load
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
UserVideoRate = sequelize.define('UserVideoRate',
|
||||
{
|
||||
type: {
|
||||
type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)),
|
||||
|
@ -22,22 +33,24 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'videoId', 'userId', 'type' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
load
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
load
|
||||
]
|
||||
addMethodsToModel(UserVideoRate, classMethods)
|
||||
|
||||
return UserVideoRate
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Video, {
|
||||
UserVideoRate.belongsTo(models.Video, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
|
@ -45,7 +58,7 @@ function associate (models) {
|
|||
onDelete: 'CASCADE'
|
||||
})
|
||||
|
||||
this.belongsTo(models.User, {
|
||||
UserVideoRate.belongsTo(models.User, {
|
||||
foreignKey: {
|
||||
name: 'userId',
|
||||
allowNull: false
|
||||
|
@ -54,21 +67,14 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function load (userId, videoId, transaction, callback) {
|
||||
if (!callback) {
|
||||
callback = transaction
|
||||
transaction = null
|
||||
}
|
||||
|
||||
const query = {
|
||||
load = function (userId, videoId, transaction, callback) {
|
||||
const options: Sequelize.FindOptions = {
|
||||
where: {
|
||||
userId,
|
||||
videoId
|
||||
}
|
||||
}
|
||||
|
||||
const options: any = {}
|
||||
if (transaction) options.transaction = transaction
|
||||
|
||||
return this.findOne(query, options).asCallback(callback)
|
||||
return UserVideoRate.findOne(options).asCallback(callback)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { getSort } from './utils'
|
||||
import { USER_ROLES } from '../initializers'
|
||||
|
@ -10,10 +11,29 @@ import {
|
|||
isUserDisplayNSFWValid
|
||||
} from '../helpers'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
UserClass,
|
||||
UserInstance,
|
||||
UserAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const User = sequelize.define('User',
|
||||
UserMethods
|
||||
} from './user-interface'
|
||||
|
||||
let User: Sequelize.Model<UserInstance, UserAttributes>
|
||||
let isPasswordMatch: UserMethods.IsPasswordMatch
|
||||
let toFormatedJSON: UserMethods.ToFormatedJSON
|
||||
let isAdmin: UserMethods.IsAdmin
|
||||
let countTotal: UserMethods.CountTotal
|
||||
let getByUsername: UserMethods.GetByUsername
|
||||
let list: UserMethods.List
|
||||
let listForApi: UserMethods.ListForApi
|
||||
let loadById: UserMethods.LoadById
|
||||
let loadByUsername: UserMethods.LoadByUsername
|
||||
let loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
User = sequelize.define('User',
|
||||
{
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -69,22 +89,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
countTotal,
|
||||
getByUsername,
|
||||
list,
|
||||
listForApi,
|
||||
loadById,
|
||||
loadByUsername,
|
||||
loadByUsernameOrEmail
|
||||
},
|
||||
instanceMethods: {
|
||||
isPasswordMatch,
|
||||
toFormatedJSON,
|
||||
isAdmin
|
||||
},
|
||||
hooks: {
|
||||
beforeCreate: beforeCreateOrUpdate,
|
||||
beforeUpdate: beforeCreateOrUpdate
|
||||
|
@ -92,26 +96,46 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
countTotal,
|
||||
getByUsername,
|
||||
list,
|
||||
listForApi,
|
||||
loadById,
|
||||
loadByUsername,
|
||||
loadByUsernameOrEmail
|
||||
]
|
||||
const instanceMethods = [
|
||||
isPasswordMatch,
|
||||
toFormatedJSON,
|
||||
isAdmin
|
||||
]
|
||||
addMethodsToModel(User, classMethods, instanceMethods)
|
||||
|
||||
return User
|
||||
}
|
||||
|
||||
function beforeCreateOrUpdate (user, options, next) {
|
||||
cryptPassword(user.password, function (err, hash) {
|
||||
if (err) return next(err)
|
||||
function beforeCreateOrUpdate (user, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
cryptPassword(user.password, function (err, hash) {
|
||||
if (err) return reject(err)
|
||||
|
||||
user.password = hash
|
||||
user.password = hash
|
||||
|
||||
return next()
|
||||
return resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function isPasswordMatch (password, callback) {
|
||||
isPasswordMatch = function (password, callback) {
|
||||
return comparePassword(password, this.password, callback)
|
||||
}
|
||||
|
||||
function toFormatedJSON () {
|
||||
toFormatedJSON = function () {
|
||||
return {
|
||||
id: this.id,
|
||||
username: this.username,
|
||||
|
@ -122,76 +146,76 @@ function toFormatedJSON () {
|
|||
}
|
||||
}
|
||||
|
||||
function isAdmin () {
|
||||
isAdmin = function () {
|
||||
return this.role === USER_ROLES.ADMIN
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.hasOne(models.Author, {
|
||||
User.hasOne(models.Author, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.hasMany(models.OAuthToken, {
|
||||
User.hasMany(models.OAuthToken, {
|
||||
foreignKey: 'userId',
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function countTotal (callback) {
|
||||
countTotal = function (callback) {
|
||||
return this.count().asCallback(callback)
|
||||
}
|
||||
|
||||
function getByUsername (username) {
|
||||
getByUsername = function (username) {
|
||||
const query = {
|
||||
where: {
|
||||
username: username
|
||||
}
|
||||
}
|
||||
|
||||
return this.findOne(query)
|
||||
return User.findOne(query)
|
||||
}
|
||||
|
||||
function list (callback) {
|
||||
return this.find().asCallback(callback)
|
||||
list = function (callback) {
|
||||
return User.find().asCallback(callback)
|
||||
}
|
||||
|
||||
function listForApi (start, count, sort, callback) {
|
||||
listForApi = function (start, count, sort, callback) {
|
||||
const query = {
|
||||
offset: start,
|
||||
limit: count,
|
||||
order: [ getSort(sort) ]
|
||||
}
|
||||
|
||||
return this.findAndCountAll(query).asCallback(function (err, result) {
|
||||
return User.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
})
|
||||
}
|
||||
|
||||
function loadById (id, callback) {
|
||||
return this.findById(id).asCallback(callback)
|
||||
loadById = function (id, callback) {
|
||||
return User.findById(id).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadByUsername (username, callback) {
|
||||
loadByUsername = function (username, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
username: username
|
||||
}
|
||||
}
|
||||
|
||||
return this.findOne(query).asCallback(callback)
|
||||
return User.findOne(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadByUsernameOrEmail (username, email, callback) {
|
||||
loadByUsernameOrEmail = function (username, email, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
$or: [ { username }, { email } ]
|
||||
}
|
||||
}
|
||||
|
||||
return this.findOne(query).asCallback(callback)
|
||||
return User.findOne(query).asCallback(callback)
|
||||
}
|
||||
|
|
|
@ -14,8 +14,14 @@ function getSort (value) {
|
|||
return [ field, direction ]
|
||||
}
|
||||
|
||||
function addMethodsToModel (model: any, classMethods: Function[], instanceMethods: Function[] = []) {
|
||||
classMethods.forEach(m => model[m.name] = m)
|
||||
instanceMethods.forEach(m => model.prototype[m.name] = m)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
addMethodsToModel,
|
||||
getSort
|
||||
}
|
||||
|
|
24
server/models/video-abuse-interface.ts
Normal file
24
server/models/video-abuse-interface.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace VideoAbuseMethods {
|
||||
export type toFormatedJSON = () => void
|
||||
|
||||
export type ListForApi = (start, count, sort, callback) => void
|
||||
}
|
||||
|
||||
export interface VideoAbuseClass {
|
||||
listForApi: VideoAbuseMethods.ListForApi
|
||||
}
|
||||
|
||||
export interface VideoAbuseAttributes {
|
||||
reporterUsername: string
|
||||
reason: string
|
||||
}
|
||||
|
||||
export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface VideoAbuseModel extends VideoAbuseClass, Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes> {}
|
|
@ -1,9 +1,22 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { CONFIG } from '../initializers'
|
||||
import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers'
|
||||
import { getSort } from './utils'
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const VideoAbuse = sequelize.define('VideoAbuse',
|
||||
import { addMethodsToModel, getSort } from './utils'
|
||||
import {
|
||||
VideoAbuseClass,
|
||||
VideoAbuseInstance,
|
||||
VideoAbuseAttributes,
|
||||
|
||||
VideoAbuseMethods
|
||||
} from './video-abuse-interface'
|
||||
|
||||
let VideoAbuse: Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes>
|
||||
let listForApi: VideoAbuseMethods.ListForApi
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
VideoAbuse = sequelize.define('VideoAbuse',
|
||||
{
|
||||
reporterUsername: {
|
||||
type: DataTypes.STRING,
|
||||
|
@ -34,60 +47,24 @@ module.exports = function (sequelize, DataTypes) {
|
|||
{
|
||||
fields: [ 'reporterPodId' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
listForApi
|
||||
},
|
||||
instanceMethods: {
|
||||
toFormatedJSON
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
listForApi
|
||||
]
|
||||
const instanceMethods = [
|
||||
toFormatedJSON
|
||||
]
|
||||
addMethodsToModel(VideoAbuse, classMethods, instanceMethods)
|
||||
|
||||
return VideoAbuse
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Pod, {
|
||||
foreignKey: {
|
||||
name: 'reporterPodId',
|
||||
allowNull: true
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.belongsTo(models.Video, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function listForApi (start, count, sort, callback) {
|
||||
const query = {
|
||||
offset: start,
|
||||
limit: count,
|
||||
order: [ getSort(sort) ],
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Pod,
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return this.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
})
|
||||
}
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function toFormatedJSON () {
|
||||
let reporterPodHost
|
||||
|
@ -110,3 +87,45 @@ function toFormatedJSON () {
|
|||
|
||||
return json
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
VideoAbuse.belongsTo(models.Pod, {
|
||||
foreignKey: {
|
||||
name: 'reporterPodId',
|
||||
allowNull: true
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
VideoAbuse.belongsTo(models.Video, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
listForApi = function (start, count, sort, callback) {
|
||||
const query = {
|
||||
offset: start,
|
||||
limit: count,
|
||||
order: [ getSort(sort) ],
|
||||
include: [
|
||||
{
|
||||
model: VideoAbuse['sequelize'].models.Pod,
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return VideoAbuse.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
|
31
server/models/video-blacklist-interface.ts
Normal file
31
server/models/video-blacklist-interface.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace BlacklistedVideoMethods {
|
||||
export type ToFormatedJSON = () => void
|
||||
|
||||
export type CountTotal = (callback) => void
|
||||
export type List = (callback) => void
|
||||
export type ListForApi = (start, count, sort, callback) => void
|
||||
export type LoadById = (id, callback) => void
|
||||
export type LoadByVideoId = (id, callback) => void
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoClass {
|
||||
toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
|
||||
countTotal: BlacklistedVideoMethods.CountTotal
|
||||
list: BlacklistedVideoMethods.List
|
||||
listForApi: BlacklistedVideoMethods.ListForApi
|
||||
loadById: BlacklistedVideoMethods.LoadById
|
||||
loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoAttributes {
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoInstance extends BlacklistedVideoClass, BlacklistedVideoAttributes, Sequelize.Instance<BlacklistedVideoAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoModel extends BlacklistedVideoClass, Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes> {}
|
|
@ -1,9 +1,24 @@
|
|||
import { getSort } from './utils'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel, getSort } from './utils'
|
||||
import {
|
||||
BlacklistedVideoClass,
|
||||
BlacklistedVideoInstance,
|
||||
BlacklistedVideoAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const BlacklistedVideo = sequelize.define('BlacklistedVideo',
|
||||
BlacklistedVideoMethods
|
||||
} from './video-blacklist-interface'
|
||||
|
||||
let BlacklistedVideo: Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes>
|
||||
let toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
|
||||
let countTotal: BlacklistedVideoMethods.CountTotal
|
||||
let list: BlacklistedVideoMethods.List
|
||||
let listForApi: BlacklistedVideoMethods.ListForApi
|
||||
let loadById: BlacklistedVideoMethods.LoadById
|
||||
let loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
BlacklistedVideo = sequelize.define('BlacklistedVideo',
|
||||
{},
|
||||
{
|
||||
indexes: [
|
||||
|
@ -11,29 +26,30 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'videoId' ],
|
||||
unique: true
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
countTotal,
|
||||
list,
|
||||
listForApi,
|
||||
loadById,
|
||||
loadByVideoId
|
||||
},
|
||||
instanceMethods: {
|
||||
toFormatedJSON
|
||||
},
|
||||
hooks: {}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
countTotal,
|
||||
list,
|
||||
listForApi,
|
||||
loadById,
|
||||
loadByVideoId
|
||||
]
|
||||
const instanceMethods = [
|
||||
toFormatedJSON
|
||||
]
|
||||
addMethodsToModel(BlacklistedVideo, classMethods, instanceMethods)
|
||||
|
||||
return BlacklistedVideo
|
||||
}
|
||||
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function toFormatedJSON () {
|
||||
toFormatedJSON = function () {
|
||||
return {
|
||||
id: this.id,
|
||||
videoId: this.videoId,
|
||||
|
@ -44,44 +60,44 @@ function toFormatedJSON () {
|
|||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Video, {
|
||||
BlacklistedVideo.belongsTo(models.Video, {
|
||||
foreignKey: 'videoId',
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
function countTotal (callback) {
|
||||
return this.count().asCallback(callback)
|
||||
countTotal = function (callback) {
|
||||
return BlacklistedVideo.count().asCallback(callback)
|
||||
}
|
||||
|
||||
function list (callback) {
|
||||
return this.findAll().asCallback(callback)
|
||||
list = function (callback) {
|
||||
return BlacklistedVideo.findAll().asCallback(callback)
|
||||
}
|
||||
|
||||
function listForApi (start, count, sort, callback) {
|
||||
listForApi = function (start, count, sort, callback) {
|
||||
const query = {
|
||||
offset: start,
|
||||
limit: count,
|
||||
order: [ getSort(sort) ]
|
||||
}
|
||||
|
||||
return this.findAndCountAll(query).asCallback(function (err, result) {
|
||||
return BlacklistedVideo.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
})
|
||||
}
|
||||
|
||||
function loadById (id, callback) {
|
||||
return this.findById(id).asCallback(callback)
|
||||
loadById = function (id, callback) {
|
||||
return BlacklistedVideo.findById(id).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadByVideoId (id, callback) {
|
||||
loadByVideoId = function (id, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
videoId: id
|
||||
}
|
||||
}
|
||||
|
||||
return this.find(query).asCallback(callback)
|
||||
return BlacklistedVideo.find(query).asCallback(callback)
|
||||
}
|
||||
|
|
75
server/models/video-interface.ts
Normal file
75
server/models/video-interface.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace VideoMethods {
|
||||
export type GenerateMagnetUri = () => void
|
||||
export type GetVideoFilename = () => void
|
||||
export type GetThumbnailName = () => void
|
||||
export type GetPreviewName = () => void
|
||||
export type GetTorrentName = () => void
|
||||
export type IsOwned = () => void
|
||||
export type ToFormatedJSON = () => void
|
||||
export type ToAddRemoteJSON = (callback) => void
|
||||
export type ToUpdateRemoteJSON = (callback) => void
|
||||
export type TranscodeVideofile = (callback) => void
|
||||
|
||||
export type GenerateThumbnailFromData = (video, thumbnailData, callback) => void
|
||||
export type GetDurationFromFile = (videoPath, callback) => void
|
||||
export type List = (callback) => void
|
||||
export type ListForApi = (start, count, sort, callback) => void
|
||||
export type LoadByHostAndRemoteId = (fromHost, remoteId, callback) => void
|
||||
export type ListOwnedAndPopulateAuthorAndTags = (callback) => void
|
||||
export type ListOwnedByAuthor = (author, callback) => void
|
||||
export type Load = (id, callback) => void
|
||||
export type LoadAndPopulateAuthor = (id, callback) => void
|
||||
export type LoadAndPopulateAuthorAndPodAndTags = (id, callback) => void
|
||||
export type SearchAndPopulateAuthorAndPodAndTags = (value, field, start, count, sort, callback) => void
|
||||
}
|
||||
|
||||
export interface VideoClass {
|
||||
generateMagnetUri: VideoMethods.GenerateMagnetUri
|
||||
getVideoFilename: VideoMethods.GetVideoFilename
|
||||
getThumbnailName: VideoMethods.GetThumbnailName
|
||||
getPreviewName: VideoMethods.GetPreviewName
|
||||
getTorrentName: VideoMethods.GetTorrentName
|
||||
isOwned: VideoMethods.IsOwned
|
||||
toFormatedJSON: VideoMethods.ToFormatedJSON
|
||||
toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
|
||||
toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
|
||||
transcodeVideofile: VideoMethods.TranscodeVideofile
|
||||
|
||||
generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
|
||||
getDurationFromFile: VideoMethods.GetDurationFromFile
|
||||
list: VideoMethods.List
|
||||
listForApi: VideoMethods.ListForApi
|
||||
loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
|
||||
listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
|
||||
listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
|
||||
load: VideoMethods.Load
|
||||
loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
|
||||
loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
|
||||
searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
|
||||
}
|
||||
|
||||
export interface VideoAttributes {
|
||||
name: string
|
||||
extname: string
|
||||
remoteId: string
|
||||
category: number
|
||||
licence: number
|
||||
language: number
|
||||
nsfw: boolean
|
||||
description: string
|
||||
infoHash?: string
|
||||
duration: number
|
||||
views?: number
|
||||
likes?: number
|
||||
dislikes?: number
|
||||
}
|
||||
|
||||
export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
|
||||
id: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface VideoModel extends VideoClass, Sequelize.Model<VideoInstance, VideoAttributes> {}
|
18
server/models/video-tag-interface.ts
Normal file
18
server/models/video-tag-interface.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
export namespace VideoTagMethods {
|
||||
}
|
||||
|
||||
export interface VideoTagClass {
|
||||
}
|
||||
|
||||
export interface VideoTagAttributes {
|
||||
}
|
||||
|
||||
export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> {
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export interface VideoTagModel extends VideoTagClass, Sequelize.Model<VideoTagInstance, VideoTagAttributes> {}
|
|
@ -1,5 +1,18 @@
|
|||
module.exports = function (sequelize, DataTypes) {
|
||||
const VideoTag = sequelize.define('VideoTag', {}, {
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from './utils'
|
||||
import {
|
||||
VideoTagClass,
|
||||
VideoTagInstance,
|
||||
VideoTagAttributes,
|
||||
|
||||
VideoTagMethods
|
||||
} from './video-tag-interface'
|
||||
|
||||
let VideoTag: Sequelize.Model<VideoTagInstance, VideoTagAttributes>
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
VideoTag = sequelize.define('VideoTag', {}, {
|
||||
indexes: [
|
||||
{
|
||||
fields: [ 'videoId' ]
|
||||
|
|
|
@ -8,8 +8,9 @@ import { map, values } from 'lodash'
|
|||
import { parallel, series } from 'async'
|
||||
import parseTorrent = require('parse-torrent')
|
||||
import { join } from 'path'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
const db = require('../initializers/database')
|
||||
import { database as db } from '../initializers/database'
|
||||
import {
|
||||
logger,
|
||||
isVideoNameValid,
|
||||
|
@ -32,12 +33,42 @@ import {
|
|||
THUMBNAILS_SIZE
|
||||
} from '../initializers'
|
||||
import { JobScheduler, removeVideoToFriends } from '../lib'
|
||||
import { getSort } from './utils'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
import { addMethodsToModel, getSort } from './utils'
|
||||
import {
|
||||
VideoClass,
|
||||
VideoInstance,
|
||||
VideoAttributes,
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const Video = sequelize.define('Video',
|
||||
VideoMethods
|
||||
} from './video-interface'
|
||||
|
||||
let Video: Sequelize.Model<VideoInstance, VideoAttributes>
|
||||
let generateMagnetUri: VideoMethods.GenerateMagnetUri
|
||||
let getVideoFilename: VideoMethods.GetVideoFilename
|
||||
let getThumbnailName: VideoMethods.GetThumbnailName
|
||||
let getPreviewName: VideoMethods.GetPreviewName
|
||||
let getTorrentName: VideoMethods.GetTorrentName
|
||||
let isOwned: VideoMethods.IsOwned
|
||||
let toFormatedJSON: VideoMethods.ToFormatedJSON
|
||||
let toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
|
||||
let toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
|
||||
let transcodeVideofile: VideoMethods.TranscodeVideofile
|
||||
|
||||
let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
|
||||
let getDurationFromFile: VideoMethods.GetDurationFromFile
|
||||
let list: VideoMethods.List
|
||||
let listForApi: VideoMethods.ListForApi
|
||||
let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
|
||||
let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
|
||||
let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
|
||||
let load: VideoMethods.Load
|
||||
let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
|
||||
let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
|
||||
let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
|
||||
|
||||
export default function (sequelize, DataTypes) {
|
||||
Video = sequelize.define('Video',
|
||||
{
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
|
@ -194,34 +225,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||
fields: [ 'likes' ]
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate,
|
||||
|
||||
generateThumbnailFromData,
|
||||
getDurationFromFile,
|
||||
list,
|
||||
listForApi,
|
||||
listOwnedAndPopulateAuthorAndTags,
|
||||
listOwnedByAuthor,
|
||||
load,
|
||||
loadByHostAndRemoteId,
|
||||
loadAndPopulateAuthor,
|
||||
loadAndPopulateAuthorAndPodAndTags,
|
||||
searchAndPopulateAuthorAndPodAndTags
|
||||
},
|
||||
instanceMethods: {
|
||||
generateMagnetUri,
|
||||
getVideoFilename,
|
||||
getThumbnailName,
|
||||
getPreviewName,
|
||||
getTorrentName,
|
||||
isOwned,
|
||||
toFormatedJSON,
|
||||
toAddRemoteJSON,
|
||||
toUpdateRemoteJSON,
|
||||
transcodeVideofile,
|
||||
removeFromBlacklist
|
||||
},
|
||||
hooks: {
|
||||
beforeValidate,
|
||||
beforeCreate,
|
||||
|
@ -230,99 +233,139 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
)
|
||||
|
||||
const classMethods = [
|
||||
associate,
|
||||
|
||||
generateThumbnailFromData,
|
||||
getDurationFromFile,
|
||||
list,
|
||||
listForApi,
|
||||
listOwnedAndPopulateAuthorAndTags,
|
||||
listOwnedByAuthor,
|
||||
load,
|
||||
loadByHostAndRemoteId,
|
||||
loadAndPopulateAuthor,
|
||||
loadAndPopulateAuthorAndPodAndTags,
|
||||
searchAndPopulateAuthorAndPodAndTags
|
||||
]
|
||||
const instanceMethods = [
|
||||
generateMagnetUri,
|
||||
getVideoFilename,
|
||||
getThumbnailName,
|
||||
getPreviewName,
|
||||
getTorrentName,
|
||||
isOwned,
|
||||
toFormatedJSON,
|
||||
toAddRemoteJSON,
|
||||
toUpdateRemoteJSON,
|
||||
transcodeVideofile,
|
||||
removeFromBlacklist
|
||||
]
|
||||
addMethodsToModel(Video, classMethods, instanceMethods)
|
||||
|
||||
return Video
|
||||
}
|
||||
|
||||
function beforeValidate (video, options, next) {
|
||||
function beforeValidate (video, options) {
|
||||
// Put a fake infoHash if it does not exists yet
|
||||
if (video.isOwned() && !video.infoHash) {
|
||||
// 40 hexa length
|
||||
video.infoHash = '0123456789abcdef0123456789abcdef01234567'
|
||||
}
|
||||
|
||||
return next(null)
|
||||
}
|
||||
|
||||
function beforeCreate (video, options, next) {
|
||||
const tasks = []
|
||||
function beforeCreate (video, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const tasks = []
|
||||
|
||||
if (video.isOwned()) {
|
||||
const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
|
||||
if (video.isOwned()) {
|
||||
const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
|
||||
|
||||
tasks.push(
|
||||
function createVideoTorrent (callback) {
|
||||
createTorrentFromVideo(video, videoPath, callback)
|
||||
},
|
||||
|
||||
function createVideoThumbnail (callback) {
|
||||
createThumbnail(video, videoPath, callback)
|
||||
},
|
||||
|
||||
function createVideoPreview (callback) {
|
||||
createPreview(video, videoPath, callback)
|
||||
}
|
||||
)
|
||||
|
||||
if (CONFIG.TRANSCODING.ENABLED === true) {
|
||||
tasks.push(
|
||||
function createVideoTranscoderJob (callback) {
|
||||
const dataInput = {
|
||||
id: video.id
|
||||
}
|
||||
|
||||
JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return parallel(tasks, function (err) {
|
||||
if (err) return reject(err)
|
||||
|
||||
return resolve()
|
||||
})
|
||||
}
|
||||
|
||||
return resolve()
|
||||
})
|
||||
}
|
||||
|
||||
function afterDestroy (video, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const tasks = []
|
||||
|
||||
tasks.push(
|
||||
function createVideoTorrent (callback) {
|
||||
createTorrentFromVideo(video, videoPath, callback)
|
||||
},
|
||||
|
||||
function createVideoThumbnail (callback) {
|
||||
createThumbnail(video, videoPath, callback)
|
||||
},
|
||||
|
||||
function createVideoPreview (callback) {
|
||||
createPreview(video, videoPath, callback)
|
||||
function (callback) {
|
||||
removeThumbnail(video, callback)
|
||||
}
|
||||
)
|
||||
|
||||
if (CONFIG.TRANSCODING.ENABLED === true) {
|
||||
if (video.isOwned()) {
|
||||
tasks.push(
|
||||
function createVideoTranscoderJob (callback) {
|
||||
const dataInput = {
|
||||
id: video.id
|
||||
function removeVideoFile (callback) {
|
||||
removeFile(video, callback)
|
||||
},
|
||||
|
||||
function removeVideoTorrent (callback) {
|
||||
removeTorrent(video, callback)
|
||||
},
|
||||
|
||||
function removeVideoPreview (callback) {
|
||||
removePreview(video, callback)
|
||||
},
|
||||
|
||||
function notifyFriends (callback) {
|
||||
const params = {
|
||||
remoteId: video.id
|
||||
}
|
||||
|
||||
JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
|
||||
removeVideoToFriends(params)
|
||||
|
||||
return callback()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return parallel(tasks, next)
|
||||
}
|
||||
parallel(tasks, function (err) {
|
||||
if (err) return reject(err)
|
||||
|
||||
return next()
|
||||
}
|
||||
|
||||
function afterDestroy (video, options, next) {
|
||||
const tasks = []
|
||||
|
||||
tasks.push(
|
||||
function (callback) {
|
||||
removeThumbnail(video, callback)
|
||||
}
|
||||
)
|
||||
|
||||
if (video.isOwned()) {
|
||||
tasks.push(
|
||||
function removeVideoFile (callback) {
|
||||
removeFile(video, callback)
|
||||
},
|
||||
|
||||
function removeVideoTorrent (callback) {
|
||||
removeTorrent(video, callback)
|
||||
},
|
||||
|
||||
function removeVideoPreview (callback) {
|
||||
removePreview(video, callback)
|
||||
},
|
||||
|
||||
function removeVideoToFriends (callback) {
|
||||
const params = {
|
||||
remoteId: video.id
|
||||
}
|
||||
|
||||
removeVideoToFriends(params)
|
||||
|
||||
return callback()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
parallel(tasks, next)
|
||||
return resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function associate (models) {
|
||||
this.belongsTo(models.Author, {
|
||||
Video.belongsTo(models.Author, {
|
||||
foreignKey: {
|
||||
name: 'authorId',
|
||||
allowNull: false
|
||||
|
@ -330,13 +373,13 @@ function associate (models) {
|
|||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.belongsToMany(models.Tag, {
|
||||
Video.belongsToMany(models.Tag, {
|
||||
foreignKey: 'videoId',
|
||||
through: models.VideoTag,
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
|
||||
this.hasMany(models.VideoAbuse, {
|
||||
Video.hasMany(models.VideoAbuse, {
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
|
@ -345,7 +388,7 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
function generateMagnetUri () {
|
||||
generateMagnetUri = function () {
|
||||
let baseUrlHttp
|
||||
let baseUrlWs
|
||||
|
||||
|
@ -372,18 +415,18 @@ function generateMagnetUri () {
|
|||
return magnetUtil.encode(magnetHash)
|
||||
}
|
||||
|
||||
function getVideoFilename () {
|
||||
getVideoFilename = function () {
|
||||
if (this.isOwned()) return this.id + this.extname
|
||||
|
||||
return this.remoteId + this.extname
|
||||
}
|
||||
|
||||
function getThumbnailName () {
|
||||
getThumbnailName = function () {
|
||||
// We always have a copy of the thumbnail
|
||||
return this.id + '.jpg'
|
||||
}
|
||||
|
||||
function getPreviewName () {
|
||||
getPreviewName = function () {
|
||||
const extension = '.jpg'
|
||||
|
||||
if (this.isOwned()) return this.id + extension
|
||||
|
@ -391,7 +434,7 @@ function getPreviewName () {
|
|||
return this.remoteId + extension
|
||||
}
|
||||
|
||||
function getTorrentName () {
|
||||
getTorrentName = function () {
|
||||
const extension = '.torrent'
|
||||
|
||||
if (this.isOwned()) return this.id + extension
|
||||
|
@ -399,11 +442,11 @@ function getTorrentName () {
|
|||
return this.remoteId + extension
|
||||
}
|
||||
|
||||
function isOwned () {
|
||||
isOwned = function () {
|
||||
return this.remoteId === null
|
||||
}
|
||||
|
||||
function toFormatedJSON () {
|
||||
toFormatedJSON = function () {
|
||||
let podHost
|
||||
|
||||
if (this.Author.Pod) {
|
||||
|
@ -453,43 +496,41 @@ function toFormatedJSON () {
|
|||
return json
|
||||
}
|
||||
|
||||
function toAddRemoteJSON (callback) {
|
||||
const self = this
|
||||
|
||||
toAddRemoteJSON = function (callback) {
|
||||
// Get thumbnail data to send to the other pod
|
||||
const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
|
||||
fs.readFile(thumbnailPath, function (err, thumbnailData) {
|
||||
fs.readFile(thumbnailPath, (err, thumbnailData) => {
|
||||
if (err) {
|
||||
logger.error('Cannot read the thumbnail of the video')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const remoteVideo = {
|
||||
name: self.name,
|
||||
category: self.category,
|
||||
licence: self.licence,
|
||||
language: self.language,
|
||||
nsfw: self.nsfw,
|
||||
description: self.description,
|
||||
infoHash: self.infoHash,
|
||||
remoteId: self.id,
|
||||
author: self.Author.name,
|
||||
duration: self.duration,
|
||||
name: this.name,
|
||||
category: this.category,
|
||||
licence: this.licence,
|
||||
language: this.language,
|
||||
nsfw: this.nsfw,
|
||||
description: this.description,
|
||||
infoHash: this.infoHash,
|
||||
remoteId: this.id,
|
||||
author: this.Author.name,
|
||||
duration: this.duration,
|
||||
thumbnailData: thumbnailData.toString('binary'),
|
||||
tags: map(self.Tags, 'name'),
|
||||
createdAt: self.createdAt,
|
||||
updatedAt: self.updatedAt,
|
||||
extname: self.extname,
|
||||
views: self.views,
|
||||
likes: self.likes,
|
||||
dislikes: self.dislikes
|
||||
tags: map(this.Tags, 'name'),
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt,
|
||||
extname: this.extname,
|
||||
views: this.views,
|
||||
likes: this.likes,
|
||||
dislikes: this.dislikes
|
||||
}
|
||||
|
||||
return callback(null, remoteVideo)
|
||||
})
|
||||
}
|
||||
|
||||
function toUpdateRemoteJSON (callback) {
|
||||
toUpdateRemoteJSON = function (callback) {
|
||||
const json = {
|
||||
name: this.name,
|
||||
category: this.category,
|
||||
|
@ -513,7 +554,7 @@ function toUpdateRemoteJSON (callback) {
|
|||
return json
|
||||
}
|
||||
|
||||
function transcodeVideofile (finalCallback) {
|
||||
transcodeVideofile = function (finalCallback) {
|
||||
const video = this
|
||||
|
||||
const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
|
||||
|
@ -568,7 +609,7 @@ function transcodeVideofile (finalCallback) {
|
|||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function generateThumbnailFromData (video, thumbnailData, callback) {
|
||||
generateThumbnailFromData = function (video, thumbnailData, callback) {
|
||||
// Creating the thumbnail for a remote video
|
||||
|
||||
const thumbnailName = video.getThumbnailName()
|
||||
|
@ -580,7 +621,7 @@ function generateThumbnailFromData (video, thumbnailData, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function getDurationFromFile (videoPath, callback) {
|
||||
getDurationFromFile = function (videoPath, callback) {
|
||||
ffmpeg.ffprobe(videoPath, function (err, metadata) {
|
||||
if (err) return callback(err)
|
||||
|
||||
|
@ -588,46 +629,46 @@ function getDurationFromFile (videoPath, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function list (callback) {
|
||||
return this.findAll().asCallback(callback)
|
||||
list = function (callback) {
|
||||
return Video.findAll().asCallback(callback)
|
||||
}
|
||||
|
||||
function listForApi (start, count, sort, callback) {
|
||||
listForApi = function (start, count, sort, callback) {
|
||||
// Exclude Blakclisted videos from the list
|
||||
const query = {
|
||||
distinct: true,
|
||||
offset: start,
|
||||
limit: count,
|
||||
distinct: true, // For the count, a video can have many tags
|
||||
order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ],
|
||||
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ],
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Author,
|
||||
include: [ { model: this.sequelize.models.Pod, required: false } ]
|
||||
model: Video['sequelize'].models.Author,
|
||||
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
|
||||
},
|
||||
|
||||
this.sequelize.models.Tag
|
||||
Video['sequelize'].models.Tag
|
||||
],
|
||||
where: createBaseVideosWhere.call(this)
|
||||
where: createBaseVideosWhere()
|
||||
}
|
||||
|
||||
return this.findAndCountAll(query).asCallback(function (err, result) {
|
||||
return Video.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
})
|
||||
}
|
||||
|
||||
function loadByHostAndRemoteId (fromHost, remoteId, callback) {
|
||||
loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: remoteId
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Author,
|
||||
model: Video['sequelize'].models.Author,
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Pod,
|
||||
model: Video['sequelize'].models.Pod,
|
||||
required: true,
|
||||
where: {
|
||||
host: fromHost
|
||||
|
@ -638,29 +679,29 @@ function loadByHostAndRemoteId (fromHost, remoteId, callback) {
|
|||
]
|
||||
}
|
||||
|
||||
return this.findOne(query).asCallback(callback)
|
||||
return Video.findOne(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function listOwnedAndPopulateAuthorAndTags (callback) {
|
||||
listOwnedAndPopulateAuthorAndTags = function (callback) {
|
||||
// If remoteId is null this is *our* video
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: null
|
||||
},
|
||||
include: [ this.sequelize.models.Author, this.sequelize.models.Tag ]
|
||||
include: [ Video['sequelize'].models.Author, Video['sequelize'].models.Tag ]
|
||||
}
|
||||
|
||||
return this.findAll(query).asCallback(callback)
|
||||
return Video.findAll(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function listOwnedByAuthor (author, callback) {
|
||||
listOwnedByAuthor = function (author, callback) {
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: null
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Author,
|
||||
model: Video['sequelize'].models.Author,
|
||||
where: {
|
||||
name: author
|
||||
}
|
||||
|
@ -668,58 +709,58 @@ function listOwnedByAuthor (author, callback) {
|
|||
]
|
||||
}
|
||||
|
||||
return this.findAll(query).asCallback(callback)
|
||||
return Video.findAll(query).asCallback(callback)
|
||||
}
|
||||
|
||||
function load (id, callback) {
|
||||
return this.findById(id).asCallback(callback)
|
||||
load = function (id, callback) {
|
||||
return Video.findById(id).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadAndPopulateAuthor (id, callback) {
|
||||
loadAndPopulateAuthor = function (id, callback) {
|
||||
const options = {
|
||||
include: [ this.sequelize.models.Author ]
|
||||
include: [ Video['sequelize'].models.Author ]
|
||||
}
|
||||
|
||||
return this.findById(id, options).asCallback(callback)
|
||||
return Video.findById(id, options).asCallback(callback)
|
||||
}
|
||||
|
||||
function loadAndPopulateAuthorAndPodAndTags (id, callback) {
|
||||
loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
|
||||
const options = {
|
||||
include: [
|
||||
{
|
||||
model: this.sequelize.models.Author,
|
||||
include: [ { model: this.sequelize.models.Pod, required: false } ]
|
||||
model: Video['sequelize'].models.Author,
|
||||
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
|
||||
},
|
||||
this.sequelize.models.Tag
|
||||
Video['sequelize'].models.Tag
|
||||
]
|
||||
}
|
||||
|
||||
return this.findById(id, options).asCallback(callback)
|
||||
return Video.findById(id, options).asCallback(callback)
|
||||
}
|
||||
|
||||
function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) {
|
||||
searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) {
|
||||
const podInclude: any = {
|
||||
model: this.sequelize.models.Pod,
|
||||
model: Video['sequelize'].models.Pod,
|
||||
required: false
|
||||
}
|
||||
|
||||
const authorInclude: any = {
|
||||
model: this.sequelize.models.Author,
|
||||
model: Video['sequelize'].models.Author,
|
||||
include: [
|
||||
podInclude
|
||||
]
|
||||
}
|
||||
|
||||
const tagInclude: any = {
|
||||
model: this.sequelize.models.Tag
|
||||
model: Video['sequelize'].models.Tag
|
||||
}
|
||||
|
||||
const query: any = {
|
||||
where: createBaseVideosWhere.call(this),
|
||||
distinct: true,
|
||||
where: createBaseVideosWhere(),
|
||||
offset: start,
|
||||
limit: count,
|
||||
distinct: true, // For the count, a video can have many tags
|
||||
order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ]
|
||||
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
|
||||
}
|
||||
|
||||
// Make an exact search with the magnet
|
||||
|
@ -727,8 +768,8 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
|
|||
const infoHash = magnetUtil.decode(value).infoHash
|
||||
query.where.infoHash = infoHash
|
||||
} else if (field === 'tags') {
|
||||
const escapedValue = this.sequelize.escape('%' + value + '%')
|
||||
query.where.id.$in = this.sequelize.literal(
|
||||
const escapedValue = Video['sequelize'].escape('%' + value + '%')
|
||||
query.where.id.$in = Video['sequelize'].literal(
|
||||
'(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')'
|
||||
)
|
||||
} else if (field === 'host') {
|
||||
|
@ -758,10 +799,10 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
|
|||
]
|
||||
|
||||
if (tagInclude.where) {
|
||||
// query.include.push([ this.sequelize.models.Tag ])
|
||||
// query.include.push([ Video['sequelize'].models.Tag ])
|
||||
}
|
||||
|
||||
return this.findAndCountAll(query).asCallback(function (err, result) {
|
||||
return Video.findAndCountAll(query).asCallback(function (err, result) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, result.rows, result.count)
|
||||
|
@ -773,7 +814,7 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
|
|||
function createBaseVideosWhere () {
|
||||
return {
|
||||
id: {
|
||||
$notIn: this.sequelize.literal(
|
||||
$notIn: Video['sequelize'].literal(
|
||||
'(SELECT "BlacklistedVideos"."videoId" FROM "BlacklistedVideos")'
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue