Rename Pod -> Server
This commit is contained in:
parent
51548b3181
commit
6086242524
|
@ -1,11 +1,9 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { SortMeta } from 'primeng/primeng'
|
import { SortMeta } from 'primeng/primeng'
|
||||||
|
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
|
||||||
import { ConfirmService } from '../../../core'
|
import { RestPagination, RestTable } from '../../../shared'
|
||||||
import { RestTable, RestPagination } from '../../../shared'
|
|
||||||
import { Pod } from '../../../../../../shared'
|
|
||||||
import { FollowService } from '../shared'
|
import { FollowService } from '../shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -14,7 +12,7 @@ import { FollowService } from '../shared'
|
||||||
styleUrls: [ './followers-list.component.scss' ]
|
styleUrls: [ './followers-list.component.scss' ]
|
||||||
})
|
})
|
||||||
export class FollowersListComponent extends RestTable {
|
export class FollowersListComponent extends RestTable {
|
||||||
followers: Pod[] = []
|
followers: AccountFollow[] = []
|
||||||
totalRecords = 0
|
totalRecords = 0
|
||||||
rowsPerPage = 10
|
rowsPerPage = 10
|
||||||
sort: SortMeta = { field: 'createdAt', order: 1 }
|
sort: SortMeta = { field: 'createdAt', order: 1 }
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="canMakeFriends() === false" class="alert alert-warning">
|
<div *ngIf="canMakeFriends() === false" class="alert alert-warning">
|
||||||
It seems that you are not on a HTTPS pod. Your webserver need to have TLS activated in order to follow servers.
|
It seems that you are not on a HTTPS server. Your webserver need to have TLS activated in order to follow servers.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Add following" class="btn btn-default" [disabled]="!isFormValid()">
|
<input type="submit" value="Add following" class="btn btn-default" [disabled]="!isFormValid()">
|
||||||
|
|
|
@ -94,8 +94,6 @@ export class FollowingAddComponent implements OnInit {
|
||||||
this.followService.follow(notEmptyHosts).subscribe(
|
this.followService.follow(notEmptyHosts).subscribe(
|
||||||
status => {
|
status => {
|
||||||
this.notificationsService.success('Success', 'Follow request(s) sent!')
|
this.notificationsService.success('Success', 'Follow request(s) sent!')
|
||||||
// Wait requests between pods
|
|
||||||
setTimeout(() => this.router.navigate([ '/admin/friends/list' ]), 1000)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
err => this.notificationsService.error('Error', err.message)
|
err => this.notificationsService.error('Error', err.message)
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { SortMeta } from 'primeng/primeng'
|
import { SortMeta } from 'primeng/primeng'
|
||||||
|
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
|
||||||
import { ConfirmService } from '../../../core'
|
import { RestPagination, RestTable } from '../../../shared'
|
||||||
import { RestTable, RestPagination } from '../../../shared'
|
|
||||||
import { Pod } from '../../../../../../shared'
|
|
||||||
import { FollowService } from '../shared'
|
import { FollowService } from '../shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -13,7 +10,7 @@ import { FollowService } from '../shared'
|
||||||
templateUrl: './following-list.component.html'
|
templateUrl: './following-list.component.html'
|
||||||
})
|
})
|
||||||
export class FollowingListComponent extends RestTable {
|
export class FollowingListComponent extends RestTable {
|
||||||
following: Pod[] = []
|
following: AccountFollow[] = []
|
||||||
totalRecords = 0
|
totalRecords = 0
|
||||||
rowsPerPage = 10
|
rowsPerPage = 10
|
||||||
sort: SortMeta = { field: 'createdAt', order: 1 }
|
sort: SortMeta = { field: 'createdAt', order: 1 }
|
||||||
|
|
|
@ -7,7 +7,7 @@ import 'rxjs/add/operator/map'
|
||||||
import { SortMeta } from 'primeng/primeng'
|
import { SortMeta } from 'primeng/primeng'
|
||||||
|
|
||||||
import { RestExtractor, RestPagination, RestService } from '../../../shared'
|
import { RestExtractor, RestPagination, RestService } from '../../../shared'
|
||||||
import { Pod, ResultList } from '../../../../../../shared'
|
import { AccountFollow, ResultList } from '../../../../../../shared'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FollowService {
|
export class FollowService {
|
||||||
|
@ -19,7 +19,7 @@ export class FollowService {
|
||||||
private restExtractor: RestExtractor
|
private restExtractor: RestExtractor
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getFollowing (pagination: RestPagination, sort: SortMeta): Observable<ResultList<Pod>> {
|
getFollowing (pagination: RestPagination, sort: SortMeta): Observable<ResultList<AccountFollow>> {
|
||||||
let params = new HttpParams()
|
let params = new HttpParams()
|
||||||
params = this.restService.addRestGetParams(params, pagination, sort)
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export class FollowService {
|
||||||
.catch(res => this.restExtractor.handleError(res))
|
.catch(res => this.restExtractor.handleError(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
getFollowers (pagination: RestPagination, sort: SortMeta): Observable<ResultList<Pod>> {
|
getFollowers (pagination: RestPagination, sort: SortMeta): Observable<ResultList<AccountFollow>> {
|
||||||
let params = new HttpParams()
|
let params = new HttpParams()
|
||||||
params = this.restService.addRestGetParams(params, pagination, sort)
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
>
|
>
|
||||||
<p-column field="id" header="ID" [sortable]="true"></p-column>
|
<p-column field="id" header="ID" [sortable]="true"></p-column>
|
||||||
<p-column field="reason" header="Reason"></p-column>
|
<p-column field="reason" header="Reason"></p-column>
|
||||||
<p-column field="reporterPodHost" header="Reporter pod host"></p-column>
|
<p-column field="reporterServerHost" header="Reporter server host"></p-column>
|
||||||
<p-column field="reporterUsername" header="Reporter username"></p-column>
|
<p-column field="reporterUsername" header="Reporter username"></p-column>
|
||||||
<p-column header="Video" styleClass="action-cell">
|
<p-column header="Video" styleClass="action-cell">
|
||||||
<ng-template pTemplate="body" let-videoAbuse="rowData">
|
<ng-template pTemplate="body" let-videoAbuse="rowData">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
The video load seems to be abnormally long.
|
The video load seems to be abnormally long.
|
||||||
<ul>
|
<ul>
|
||||||
<li>Maybe the server {{ video.podHost }} is down :(</li>
|
<li>Maybe the server {{ video.serverHost }} is down :(</li>
|
||||||
<li>
|
<li>
|
||||||
If not, you can report an issue on
|
If not, you can report an issue on
|
||||||
<a href="https://github.com/Chocobozzz/PeerTube/issues" title="Report an issue">
|
<a href="https://github.com/Chocobozzz/PeerTube/issues" title="Report an issue">
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
|
||||||
uuid: string
|
uuid: string
|
||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
name: string
|
name: string
|
||||||
podHost: string
|
serverHost: string
|
||||||
tags: string[]
|
tags: string[]
|
||||||
thumbnailPath: string
|
thumbnailPath: string
|
||||||
thumbnailUrl: string
|
thumbnailUrl: string
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class Video implements VideoServerModel {
|
||||||
uuid: string
|
uuid: string
|
||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
name: string
|
name: string
|
||||||
podHost: string
|
serverHost: string
|
||||||
tags: string[]
|
tags: string[]
|
||||||
thumbnailPath: string
|
thumbnailPath: string
|
||||||
thumbnailUrl: string
|
thumbnailUrl: string
|
||||||
|
@ -32,8 +32,8 @@ export class Video implements VideoServerModel {
|
||||||
dislikes: number
|
dislikes: number
|
||||||
nsfw: boolean
|
nsfw: boolean
|
||||||
|
|
||||||
private static createByString (account: string, podHost: string) {
|
private static createByString (account: string, serverHost: string) {
|
||||||
return account + '@' + podHost
|
return account + '@' + serverHost
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createDurationString (duration: number) {
|
private static createDurationString (duration: number) {
|
||||||
|
@ -67,7 +67,7 @@ export class Video implements VideoServerModel {
|
||||||
this.uuid = hash.uuid
|
this.uuid = hash.uuid
|
||||||
this.isLocal = hash.isLocal
|
this.isLocal = hash.isLocal
|
||||||
this.name = hash.name
|
this.name = hash.name
|
||||||
this.podHost = hash.podHost
|
this.serverHost = hash.serverHost
|
||||||
this.tags = hash.tags
|
this.tags = hash.tags
|
||||||
this.thumbnailPath = hash.thumbnailPath
|
this.thumbnailPath = hash.thumbnailPath
|
||||||
this.thumbnailUrl = absoluteAPIUrl + hash.thumbnailPath
|
this.thumbnailUrl = absoluteAPIUrl + hash.thumbnailPath
|
||||||
|
@ -80,7 +80,7 @@ export class Video implements VideoServerModel {
|
||||||
this.dislikes = hash.dislikes
|
this.dislikes = hash.dislikes
|
||||||
this.nsfw = hash.nsfw
|
this.nsfw = hash.nsfw
|
||||||
|
|
||||||
this.by = Video.createByString(hash.account, hash.podHost)
|
this.by = Video.createByString(hash.account, hash.serverHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoNSFWForUser (user: User) {
|
isVideoNSFWForUser (user: User) {
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
// import * as express from 'express'
|
|
||||||
//
|
|
||||||
// import { database as db } from '../../../initializers/database'
|
|
||||||
// import {
|
|
||||||
// checkSignature,
|
|
||||||
// signatureValidator,
|
|
||||||
// setBodyHostPort,
|
|
||||||
// remotePodsAddValidator,
|
|
||||||
// asyncMiddleware
|
|
||||||
// } from '../../../middlewares'
|
|
||||||
// import { sendOwnedDataToPod } from '../../../lib'
|
|
||||||
// import { getMyPublicCert, getFormattedObjects } from '../../../helpers'
|
|
||||||
// import { CONFIG } from '../../../initializers'
|
|
||||||
// import { PodInstance } from '../../../models'
|
|
||||||
// import { PodSignature, Pod as FormattedPod } from '../../../../shared'
|
|
||||||
//
|
|
||||||
// const remotePodsRouter = express.Router()
|
|
||||||
//
|
|
||||||
// remotePodsRouter.post('/remove',
|
|
||||||
// signatureValidator,
|
|
||||||
// checkSignature,
|
|
||||||
// asyncMiddleware(removePods)
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// remotePodsRouter.post('/list',
|
|
||||||
// asyncMiddleware(remotePodsList)
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// remotePodsRouter.post('/add',
|
|
||||||
// setBodyHostPort, // We need to modify the host before running the validator!
|
|
||||||
// remotePodsAddValidator,
|
|
||||||
// asyncMiddleware(addPods)
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// // ---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// export {
|
|
||||||
// remotePodsRouter
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// async function addPods (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const information = req.body
|
|
||||||
//
|
|
||||||
// const pod = db.Pod.build(information)
|
|
||||||
// const podCreated = await pod.save()
|
|
||||||
//
|
|
||||||
// await sendOwnedDataToPod(podCreated.id)
|
|
||||||
//
|
|
||||||
// const cert = await getMyPublicCert()
|
|
||||||
// return res.json({ cert, email: CONFIG.ADMIN.EMAIL })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function remotePodsList (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const pods = await db.Pod.list()
|
|
||||||
//
|
|
||||||
// return res.json(getFormattedObjects<FormattedPod, PodInstance>(pods, pods.length))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const signature: PodSignature = req.body.signature
|
|
||||||
// const host = signature.host
|
|
||||||
//
|
|
||||||
// const pod = await db.Pod.loadByHost(host)
|
|
||||||
// await pod.destroy()
|
|
||||||
//
|
|
||||||
// return res.type('json').status(204).end()
|
|
||||||
// }
|
|
|
@ -1,278 +0,0 @@
|
||||||
// import * as express from 'express'
|
|
||||||
// import * as Bluebird from 'bluebird'
|
|
||||||
// import * as Sequelize from 'sequelize'
|
|
||||||
//
|
|
||||||
// import { database as db } from '../../../initializers/database'
|
|
||||||
// import {
|
|
||||||
// REQUEST_ENDPOINT_ACTIONS,
|
|
||||||
// REQUEST_ENDPOINTS,
|
|
||||||
// REQUEST_VIDEO_EVENT_TYPES,
|
|
||||||
// REQUEST_VIDEO_QADU_TYPES
|
|
||||||
// } from '../../../initializers'
|
|
||||||
// import {
|
|
||||||
// checkSignature,
|
|
||||||
// signatureValidator,
|
|
||||||
// remoteVideosValidator,
|
|
||||||
// remoteQaduVideosValidator,
|
|
||||||
// remoteEventsVideosValidator
|
|
||||||
// } from '../../../middlewares'
|
|
||||||
// import { logger, retryTransactionWrapper, resetSequelizeInstance } from '../../../helpers'
|
|
||||||
// import { quickAndDirtyUpdatesVideoToFriends, fetchVideoChannelByHostAndUUID } from '../../../lib'
|
|
||||||
// import { PodInstance, VideoFileInstance } from '../../../models'
|
|
||||||
// import {
|
|
||||||
// RemoteVideoRequest,
|
|
||||||
// RemoteVideoCreateData,
|
|
||||||
// RemoteVideoUpdateData,
|
|
||||||
// RemoteVideoRemoveData,
|
|
||||||
// RemoteVideoReportAbuseData,
|
|
||||||
// RemoteQaduVideoRequest,
|
|
||||||
// RemoteQaduVideoData,
|
|
||||||
// RemoteVideoEventRequest,
|
|
||||||
// RemoteVideoEventData,
|
|
||||||
// RemoteVideoChannelCreateData,
|
|
||||||
// RemoteVideoChannelUpdateData,
|
|
||||||
// RemoteVideoChannelRemoveData,
|
|
||||||
// RemoteVideoAccountRemoveData,
|
|
||||||
// RemoteVideoAccountCreateData
|
|
||||||
// } from '../../../../shared'
|
|
||||||
// import { VideoInstance } from '../../../models/video/video-interface'
|
|
||||||
//
|
|
||||||
// const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
|
|
||||||
//
|
|
||||||
// // Functions to call when processing a remote request
|
|
||||||
// // FIXME: use RemoteVideoRequestType as id type
|
|
||||||
// const functionsHash: { [ id: string ]: (...args) => Promise<any> } = {}
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.ADD_VIDEO] = addRemoteVideoRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.UPDATE_VIDEO] = updateRemoteVideoRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.REMOVE_VIDEO] = removeRemoteVideoRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.ADD_CHANNEL] = addRemoteVideoChannelRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.UPDATE_CHANNEL] = updateRemoteVideoChannelRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.REMOVE_CHANNEL] = removeRemoteVideoChannelRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.REPORT_ABUSE] = reportAbuseRemoteVideoRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.ADD_ACCOUNT] = addRemoteVideoAccountRetryWrapper
|
|
||||||
// functionsHash[ENDPOINT_ACTIONS.REMOVE_ACCOUNT] = removeRemoteVideoAccountRetryWrapper
|
|
||||||
//
|
|
||||||
// const remoteVideosRouter = express.Router()
|
|
||||||
//
|
|
||||||
// remoteVideosRouter.post('/',
|
|
||||||
// signatureValidator,
|
|
||||||
// checkSignature,
|
|
||||||
// remoteVideosValidator,
|
|
||||||
// remoteVideos
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// remoteVideosRouter.post('/qadu',
|
|
||||||
// signatureValidator,
|
|
||||||
// checkSignature,
|
|
||||||
// remoteQaduVideosValidator,
|
|
||||||
// remoteVideosQadu
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// remoteVideosRouter.post('/events',
|
|
||||||
// signatureValidator,
|
|
||||||
// checkSignature,
|
|
||||||
// remoteEventsVideosValidator,
|
|
||||||
// remoteVideosEvents
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// // ---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// export {
|
|
||||||
// remoteVideosRouter
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const requests: RemoteVideoRequest[] = req.body.data
|
|
||||||
// const fromPod = res.locals.secure.pod
|
|
||||||
//
|
|
||||||
// // We need to process in the same order to keep consistency
|
|
||||||
// Bluebird.each(requests, request => {
|
|
||||||
// const data = request.data
|
|
||||||
//
|
|
||||||
// // Get the function we need to call in order to process the request
|
|
||||||
// const fun = functionsHash[request.type]
|
|
||||||
// if (fun === undefined) {
|
|
||||||
// logger.error('Unknown remote request type %s.', request.type)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return fun.call(this, data, fromPod)
|
|
||||||
// })
|
|
||||||
// .catch(err => logger.error('Error managing remote videos.', err))
|
|
||||||
//
|
|
||||||
// // Don't block the other pod
|
|
||||||
// return res.type('json').status(204).end()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const requests: RemoteQaduVideoRequest[] = req.body.data
|
|
||||||
// const fromPod = res.locals.secure.pod
|
|
||||||
//
|
|
||||||
// Bluebird.each(requests, request => {
|
|
||||||
// const videoData = request.data
|
|
||||||
//
|
|
||||||
// return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod)
|
|
||||||
// })
|
|
||||||
// .catch(err => logger.error('Error managing remote videos.', err))
|
|
||||||
//
|
|
||||||
// return res.type('json').status(204).end()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
// const requests: RemoteVideoEventRequest[] = req.body.data
|
|
||||||
// const fromPod = res.locals.secure.pod
|
|
||||||
//
|
|
||||||
// Bluebird.each(requests, request => {
|
|
||||||
// const eventData = request.data
|
|
||||||
//
|
|
||||||
// return processVideosEventsRetryWrapper(eventData, fromPod)
|
|
||||||
// })
|
|
||||||
// .catch(err => logger.error('Error managing remote videos.', err))
|
|
||||||
//
|
|
||||||
// return res.type('json').status(204).end()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromPod: PodInstance) {
|
|
||||||
// const options = {
|
|
||||||
// arguments: [ eventData, fromPod ],
|
|
||||||
// errorMessage: 'Cannot process videos events with many retries.'
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// await retryTransactionWrapper(processVideosEvents, options)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
|
|
||||||
// await db.sequelize.transaction(async t => {
|
|
||||||
// const sequelizeOptions = { transaction: t }
|
|
||||||
// const videoInstance = await fetchLocalVideoByUUID(eventData.uuid, t)
|
|
||||||
//
|
|
||||||
// let columnToUpdate
|
|
||||||
// let qaduType
|
|
||||||
//
|
|
||||||
// switch (eventData.eventType) {
|
|
||||||
// case REQUEST_VIDEO_EVENT_TYPES.VIEWS:
|
|
||||||
// columnToUpdate = 'views'
|
|
||||||
// qaduType = REQUEST_VIDEO_QADU_TYPES.VIEWS
|
|
||||||
// break
|
|
||||||
//
|
|
||||||
// case REQUEST_VIDEO_EVENT_TYPES.LIKES:
|
|
||||||
// columnToUpdate = 'likes'
|
|
||||||
// qaduType = REQUEST_VIDEO_QADU_TYPES.LIKES
|
|
||||||
// break
|
|
||||||
//
|
|
||||||
// case REQUEST_VIDEO_EVENT_TYPES.DISLIKES:
|
|
||||||
// columnToUpdate = 'dislikes'
|
|
||||||
// qaduType = REQUEST_VIDEO_QADU_TYPES.DISLIKES
|
|
||||||
// break
|
|
||||||
//
|
|
||||||
// default:
|
|
||||||
// throw new Error('Unknown video event type.')
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const query = {}
|
|
||||||
// query[columnToUpdate] = eventData.count
|
|
||||||
//
|
|
||||||
// await videoInstance.increment(query, sequelizeOptions)
|
|
||||||
//
|
|
||||||
// const qadusParams = [
|
|
||||||
// {
|
|
||||||
// videoId: videoInstance.id,
|
|
||||||
// type: qaduType
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// await quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// logger.info('Remote video event processed for video with uuid %s.', eventData.uuid)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function quickAndDirtyUpdateVideoRetryWrapper (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
|
|
||||||
// const options = {
|
|
||||||
// arguments: [ videoData, fromPod ],
|
|
||||||
// errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// await retryTransactionWrapper(quickAndDirtyUpdateVideo, options)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
|
|
||||||
// let videoUUID = ''
|
|
||||||
//
|
|
||||||
// await db.sequelize.transaction(async t => {
|
|
||||||
// const videoInstance = await fetchVideoByHostAndUUID(fromPod.host, videoData.uuid, t)
|
|
||||||
// const sequelizeOptions = { transaction: t }
|
|
||||||
//
|
|
||||||
// videoUUID = videoInstance.uuid
|
|
||||||
//
|
|
||||||
// if (videoData.views) {
|
|
||||||
// videoInstance.set('views', videoData.views)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (videoData.likes) {
|
|
||||||
// videoInstance.set('likes', videoData.likes)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (videoData.dislikes) {
|
|
||||||
// videoInstance.set('dislikes', videoData.dislikes)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// await videoInstance.save(sequelizeOptions)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// logger.info('Remote video with uuid %s quick and dirty updated', videoUUID)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function reportAbuseRemoteVideoRetryWrapper (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
|
|
||||||
// const options = {
|
|
||||||
// arguments: [ reportData, fromPod ],
|
|
||||||
// errorMessage: 'Cannot create remote abuse video with many retries.'
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// await retryTransactionWrapper(reportAbuseRemoteVideo, options)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
|
|
||||||
// logger.debug('Reporting remote abuse for video %s.', reportData.videoUUID)
|
|
||||||
//
|
|
||||||
// await db.sequelize.transaction(async t => {
|
|
||||||
// const videoInstance = await fetchLocalVideoByUUID(reportData.videoUUID, t)
|
|
||||||
// const videoAbuseData = {
|
|
||||||
// reporterUsername: reportData.reporterUsername,
|
|
||||||
// reason: reportData.reportReason,
|
|
||||||
// reporterPodId: fromPod.id,
|
|
||||||
// videoId: videoInstance.id
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// await db.VideoAbuse.create(videoAbuseData)
|
|
||||||
//
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// logger.info('Remote abuse for video uuid %s created', reportData.videoUUID)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function fetchLocalVideoByUUID (id: string, t: Sequelize.Transaction) {
|
|
||||||
// try {
|
|
||||||
// const video = await db.Video.loadLocalVideoByUUID(id, t)
|
|
||||||
//
|
|
||||||
// if (!video) throw new Error('Video ' + id + ' not found')
|
|
||||||
//
|
|
||||||
// return video
|
|
||||||
// } catch (err) {
|
|
||||||
// logger.error('Cannot load owned video from id.', { error: err.stack, id })
|
|
||||||
// throw err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// async function fetchVideoByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) {
|
|
||||||
// try {
|
|
||||||
// const video = await db.Video.loadByHostAndUUID(podHost, uuid, t)
|
|
||||||
// if (!video) throw new Error('Video not found')
|
|
||||||
//
|
|
||||||
// return video
|
|
||||||
// } catch (err) {
|
|
||||||
// logger.error('Cannot load video from host and uuid.', { error: err.stack, podHost, uuid })
|
|
||||||
// throw err
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -4,7 +4,7 @@ import { badRequest } from '../../helpers'
|
||||||
|
|
||||||
import { oauthClientsRouter } from './oauth-clients'
|
import { oauthClientsRouter } from './oauth-clients'
|
||||||
import { configRouter } from './config'
|
import { configRouter } from './config'
|
||||||
import { applicationRouter } from './application'
|
import { applicationRouter } from './server'
|
||||||
import { usersRouter } from './users'
|
import { usersRouter } from './users'
|
||||||
import { videosRouter } from './videos'
|
import { videosRouter } from './videos'
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ import { database as db } from '../../../initializers/database'
|
||||||
import { sendFollow } from '../../../lib/activitypub/send-request'
|
import { sendFollow } from '../../../lib/activitypub/send-request'
|
||||||
import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares'
|
import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares'
|
||||||
import { authenticate } from '../../../middlewares/oauth'
|
import { authenticate } from '../../../middlewares/oauth'
|
||||||
import { setBodyHostsPort } from '../../../middlewares/pods'
|
import { setBodyHostsPort } from '../../../middlewares/servers'
|
||||||
import { setFollowingSort } from '../../../middlewares/sort'
|
import { setFollowingSort } from '../../../middlewares/sort'
|
||||||
import { ensureUserHasRight } from '../../../middlewares/user-right'
|
import { ensureUserHasRight } from '../../../middlewares/user-right'
|
||||||
import { followValidator } from '../../../middlewares/validators/pods'
|
import { followValidator } from '../../../middlewares/validators/servers'
|
||||||
import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort'
|
import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort'
|
||||||
|
|
||||||
const applicationFollowsRouter = express.Router()
|
const applicationFollowsRouter = express.Router()
|
|
@ -70,12 +70,12 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
|
||||||
reporterUsername,
|
reporterUsername,
|
||||||
reason: body.reason,
|
reason: body.reason,
|
||||||
videoId: videoInstance.id,
|
videoId: videoInstance.id,
|
||||||
reporterPodId: null // This is our pod that reported this abuse
|
reporterServerId: null // This is our server that reported this abuse
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.sequelize.transaction(async t => {
|
await db.sequelize.transaction(async t => {
|
||||||
const abuse = await db.VideoAbuse.create(abuseToCreate, { transaction: t })
|
const abuse = await db.VideoAbuse.create(abuseToCreate, { transaction: t })
|
||||||
// We send the information to the destination pod
|
// We send the information to the destination server
|
||||||
if (videoInstance.isOwned() === false) {
|
if (videoInstance.isOwned() === false) {
|
||||||
const reportData = {
|
const reportData = {
|
||||||
reporterUsername,
|
reporterUsername,
|
||||||
|
@ -84,7 +84,7 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// await friends.reportAbuseVideoToFriend(reportData, videoInstance, t)
|
// await friends.reportAbuseVideoToFriend(reportData, videoInstance, t)
|
||||||
// TODO: send abuse to origin pod
|
// TODO: send abuse to origin server
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
|
||||||
|
|
||||||
// Let transcoding job send the video to friends because the video file extension might change
|
// Let transcoding job send the video to friends because the video file extension might change
|
||||||
if (CONFIG.TRANSCODING.ENABLED === true) return undefined
|
if (CONFIG.TRANSCODING.ENABLED === true) return undefined
|
||||||
// Don't send video to remote pods, it is private
|
// Don't send video to remote servers, it is private
|
||||||
if (video.privacy === VideoPrivacy.PRIVATE) return undefined
|
if (video.privacy === VideoPrivacy.PRIVATE) return undefined
|
||||||
|
|
||||||
await sendAddVideo(video, t)
|
await sendAddVideo(video, t)
|
||||||
|
@ -287,7 +287,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
|
||||||
await sendUpdateVideoChannel(videoInstance, t)
|
await sendUpdateVideoChannel(videoInstance, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video is not private anymore, send a create action to remote pods
|
// Video is not private anymore, send a create action to remote servers
|
||||||
if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) {
|
if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) {
|
||||||
await sendAddVideo(videoInstance, t)
|
await sendAddVideo(videoInstance, t)
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ async function removeVideo (req: express.Request, res: express.Response) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
const resultList = await db.Video.searchAndPopulateAccountAndPodAndTags(
|
const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
|
||||||
req.params.value,
|
req.params.value,
|
||||||
req.query.field,
|
req.query.field,
|
||||||
req.query.start,
|
req.query.start,
|
||||||
|
|
|
@ -83,7 +83,7 @@ async function rateVideo (req: express.Request, res: express.Response) {
|
||||||
await videoInstance.increment(incrementQuery, sequelizeOptions)
|
await videoInstance.increment(incrementQuery, sequelizeOptions)
|
||||||
|
|
||||||
if (videoInstance.isOwned() === false) {
|
if (videoInstance.isOwned() === false) {
|
||||||
// TODO: Send a event to original pod
|
// TODO: Send a event to original server
|
||||||
} else {
|
} else {
|
||||||
// TODO: Send update to followers
|
// TODO: Send update to followers
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,9 +110,9 @@ async function generateWatchHtmlPage (req: express.Request, res: express.Respons
|
||||||
|
|
||||||
// Let Angular application handle errors
|
// Let Angular application handle errors
|
||||||
if (validator.isUUID(videoId, 4)) {
|
if (validator.isUUID(videoId, 4)) {
|
||||||
videoPromise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(videoId)
|
videoPromise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(videoId)
|
||||||
} else if (validator.isInt(videoId)) {
|
} else if (validator.isInt(videoId)) {
|
||||||
videoPromise = db.Video.loadAndPopulateAccountAndPodAndTags(+videoId)
|
videoPromise = db.Video.loadAndPopulateAccountAndServerAndTags(+videoId)
|
||||||
} else {
|
} else {
|
||||||
return res.sendFile(indexPath)
|
return res.sendFile(indexPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { asyncMiddleware } from '../middlewares'
|
||||||
const staticRouter = express.Router()
|
const staticRouter = express.Router()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cors is very important to let other pods access torrent and video files
|
Cors is very important to let other servers access torrent and video files
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
|
const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
|
||||||
|
|
|
@ -35,7 +35,7 @@ async function getOrCreateAccount (accountUrl: string) {
|
||||||
|
|
||||||
// We don't have this account in our database, fetch it on remote
|
// We don't have this account in our database, fetch it on remote
|
||||||
if (!account) {
|
if (!account) {
|
||||||
const res = await fetchRemoteAccountAndCreatePod(accountUrl)
|
const res = await fetchRemoteAccountAndCreateServer(accountUrl)
|
||||||
if (res === undefined) throw new Error('Cannot fetch remote account.')
|
if (res === undefined) throw new Error('Cannot fetch remote account.')
|
||||||
|
|
||||||
// Save our new account in database
|
// Save our new account in database
|
||||||
|
@ -46,7 +46,7 @@ async function getOrCreateAccount (accountUrl: string) {
|
||||||
return account
|
return account
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
|
async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
|
||||||
const options = {
|
const options = {
|
||||||
uri: accountUrl,
|
uri: accountUrl,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
@ -90,7 +90,7 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
const accountHost = url.parse(account.url).host
|
const accountHost = url.parse(account.url).host
|
||||||
const podOptions = {
|
const serverOptions = {
|
||||||
where: {
|
where: {
|
||||||
host: accountHost
|
host: accountHost
|
||||||
},
|
},
|
||||||
|
@ -98,15 +98,15 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
|
||||||
host: accountHost
|
host: accountHost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const [ pod ] = await db.Pod.findOrCreate(podOptions)
|
const [ server ] = await db.Server.findOrCreate(serverOptions)
|
||||||
account.set('podId', pod.id)
|
account.set('serverId', server.id)
|
||||||
|
|
||||||
return { account, pod }
|
return { account, server }
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchRemoteVideoPreview (video: VideoInstance) {
|
function fetchRemoteVideoPreview (video: VideoInstance) {
|
||||||
// FIXME: use url
|
// FIXME: use url
|
||||||
const host = video.VideoChannel.Account.Pod.host
|
const host = video.VideoChannel.Account.Server.host
|
||||||
const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName())
|
const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName())
|
||||||
|
|
||||||
return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
|
return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
|
||||||
|
@ -163,7 +163,7 @@ function activityPubCollectionPagination (url: string, page: number, result: Res
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
fetchRemoteAccountAndCreatePod,
|
fetchRemoteAccountAndCreateServer,
|
||||||
activityPubContextify,
|
activityPubContextify,
|
||||||
activityPubCollectionPagination,
|
activityPubCollectionPagination,
|
||||||
getActivityPubUrl,
|
getActivityPubUrl,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { AccountInstance } from '../../models'
|
||||||
import { logger } from '../logger'
|
import { logger } from '../logger'
|
||||||
|
|
||||||
import { isUserUsernameValid } from './users'
|
import { isUserUsernameValid } from './users'
|
||||||
import { isHostValid } from './pods'
|
import { isHostValid } from './servers'
|
||||||
|
|
||||||
function isAccountNameValid (value: string) {
|
function isAccountNameValid (value: string) {
|
||||||
return isUserUsernameValid(value)
|
return isUserUsernameValid(value)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export * from './activitypub'
|
export * from './activitypub'
|
||||||
export * from './misc'
|
export * from './misc'
|
||||||
export * from './pods'
|
export * from './servers'
|
||||||
export * from './pods'
|
export * from './servers'
|
||||||
export * from './users'
|
export * from './users'
|
||||||
export * from './accounts'
|
export * from './accounts'
|
||||||
export * from './video-channels'
|
export * from './video-channels'
|
||||||
|
|
|
@ -171,9 +171,9 @@ function isVideoFileInfoHashValid (value: string) {
|
||||||
function checkVideoExists (id: string, res: express.Response, callback: () => void) {
|
function checkVideoExists (id: string, res: express.Response, callback: () => void) {
|
||||||
let promise: Promise<VideoInstance>
|
let promise: Promise<VideoInstance>
|
||||||
if (validator.isInt(id)) {
|
if (validator.isInt(id)) {
|
||||||
promise = db.Video.loadAndPopulateAccountAndPodAndTags(+id)
|
promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id)
|
||||||
} else { // UUID
|
} else { // UUID
|
||||||
promise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(id)
|
promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then(video => {
|
promise.then(video => {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as WebFinger from 'webfinger.js'
|
||||||
import { isTestInstance } from './core-utils'
|
import { isTestInstance } from './core-utils'
|
||||||
import { isActivityPubUrlValid } from './custom-validators'
|
import { isActivityPubUrlValid } from './custom-validators'
|
||||||
import { WebFingerData } from '../../shared'
|
import { WebFingerData } from '../../shared'
|
||||||
import { fetchRemoteAccountAndCreatePod } from './activitypub'
|
import { fetchRemoteAccountAndCreateServer } from './activitypub'
|
||||||
|
|
||||||
const webfinger = new WebFinger({
|
const webfinger = new WebFinger({
|
||||||
webfist_fallback: false,
|
webfist_fallback: false,
|
||||||
|
@ -22,8 +22,8 @@ async function getAccountFromWebfinger (nameWithHost: string) {
|
||||||
throw new Error('Cannot find self link or href is not a valid URL.')
|
throw new Error('Cannot find self link or href is not a valid URL.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await fetchRemoteAccountAndCreatePod(selfLink.href)
|
const res = await fetchRemoteAccountAndCreateServer(selfLink.href)
|
||||||
if (res === undefined) throw new Error('Cannot fetch and create pod of remote account ' + selfLink.href)
|
if (res === undefined) throw new Error('Cannot fetch and create server of remote account ' + selfLink.href)
|
||||||
|
|
||||||
return res.account
|
return res.account
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@ import { root, isTestInstance } from '../helpers/core-utils'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
VideoRateType,
|
VideoRateType,
|
||||||
RequestEndpoint,
|
|
||||||
RequestVideoEventType,
|
|
||||||
RequestVideoQaduType,
|
|
||||||
RemoteVideoRequestType,
|
|
||||||
JobState,
|
JobState,
|
||||||
JobCategory
|
JobCategory
|
||||||
} from '../../shared/models'
|
} from '../../shared/models'
|
||||||
|
@ -220,7 +216,7 @@ const VIDEO_MIMETYPE_EXT = {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Score a pod has when we create it as a friend
|
// Score a server has when we create it as a friend
|
||||||
const FRIEND_SCORE = {
|
const FRIEND_SCORE = {
|
||||||
BASE: 100,
|
BASE: 100,
|
||||||
MAX: 1000
|
MAX: 1000
|
||||||
|
@ -243,7 +239,7 @@ const ACTIVITY_PUB = {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Number of points we add/remove from a friend after a successful/bad request
|
// Number of points we add/remove from a friend after a successful/bad request
|
||||||
const PODS_SCORE = {
|
const SERVERS_SCORE = {
|
||||||
PENALTY: -10,
|
PENALTY: -10,
|
||||||
BONUS: 10
|
BONUS: 10
|
||||||
}
|
}
|
||||||
|
@ -352,7 +348,7 @@ export {
|
||||||
OAUTH_LIFETIME,
|
OAUTH_LIFETIME,
|
||||||
OPENGRAPH_AND_OEMBED_COMMENT,
|
OPENGRAPH_AND_OEMBED_COMMENT,
|
||||||
PAGINATION_COUNT_DEFAULT,
|
PAGINATION_COUNT_DEFAULT,
|
||||||
PODS_SCORE,
|
SERVERS_SCORE,
|
||||||
PREVIEWS_SIZE,
|
PREVIEWS_SIZE,
|
||||||
REMOTE_SCHEME,
|
REMOTE_SCHEME,
|
||||||
ACTIVITY_PUB_ACCEPT_HEADER,
|
ACTIVITY_PUB_ACCEPT_HEADER,
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { UserModel } from '../models/account/user-interface'
|
||||||
import { AccountVideoRateModel } from '../models/account/account-video-rate-interface'
|
import { AccountVideoRateModel } from '../models/account/account-video-rate-interface'
|
||||||
import { AccountFollowModel } from '../models/account/account-follow-interface'
|
import { AccountFollowModel } from '../models/account/account-follow-interface'
|
||||||
import { TagModel } from './../models/video/tag-interface'
|
import { TagModel } from './../models/video/tag-interface'
|
||||||
import { PodModel } from './../models/pod/pod-interface'
|
import { ServerModel } from '../models/server/server-interface'
|
||||||
import { OAuthTokenModel } from './../models/oauth/oauth-token-interface'
|
import { OAuthTokenModel } from './../models/oauth/oauth-token-interface'
|
||||||
import { OAuthClientModel } from './../models/oauth/oauth-client-interface'
|
import { OAuthClientModel } from './../models/oauth/oauth-client-interface'
|
||||||
import { JobModel } from './../models/job/job-interface'
|
import { JobModel } from './../models/job/job-interface'
|
||||||
|
@ -38,7 +38,7 @@ const database: {
|
||||||
Job?: JobModel,
|
Job?: JobModel,
|
||||||
OAuthClient?: OAuthClientModel,
|
OAuthClient?: OAuthClientModel,
|
||||||
OAuthToken?: OAuthTokenModel,
|
OAuthToken?: OAuthTokenModel,
|
||||||
Pod?: PodModel,
|
Server?: ServerModel,
|
||||||
Tag?: TagModel,
|
Tag?: TagModel,
|
||||||
AccountVideoRate?: AccountVideoRateModel,
|
AccountVideoRate?: AccountVideoRateModel,
|
||||||
AccountFollow?: AccountFollowModel,
|
AccountFollow?: AccountFollowModel,
|
||||||
|
|
|
@ -42,7 +42,7 @@ class VideosPreviewCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadPreviews (key: string) {
|
private async loadPreviews (key: string) {
|
||||||
const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(key)
|
const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(key)
|
||||||
if (!video) return undefined
|
if (!video) return undefined
|
||||||
|
|
||||||
if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName())
|
if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName())
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { JobScheduler } from '../job-scheduler'
|
||||||
import { TranscodingJobPayload } from './transcoding-job-scheduler'
|
import { TranscodingJobPayload } from './transcoding-job-scheduler'
|
||||||
|
|
||||||
async function process (data: TranscodingJobPayload, jobId: number) {
|
async function process (data: TranscodingJobPayload, jobId: number) {
|
||||||
const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID)
|
const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID)
|
||||||
// No video, maybe deleted?
|
// No video, maybe deleted?
|
||||||
if (!video) {
|
if (!video) {
|
||||||
logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid })
|
logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid })
|
||||||
|
@ -31,7 +31,7 @@ async function onSuccess (jobId: number, video: VideoInstance, jobScheduler: Job
|
||||||
logger.info('Job %d is a success.', jobId)
|
logger.info('Job %d is a success.', jobId)
|
||||||
|
|
||||||
// Maybe the video changed in database, refresh it
|
// Maybe the video changed in database, refresh it
|
||||||
const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid)
|
const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(video.uuid)
|
||||||
// Video does not exist anymore
|
// Video does not exist anymore
|
||||||
if (!videoDatabase) return undefined
|
if (!videoDatabase) return undefined
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { VideoInstance } from '../../../models'
|
||||||
import { sendUpdateVideo } from '../../activitypub/send-request'
|
import { sendUpdateVideo } from '../../activitypub/send-request'
|
||||||
|
|
||||||
async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) {
|
async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) {
|
||||||
const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID)
|
const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID)
|
||||||
// No video, maybe deleted?
|
// No video, maybe deleted?
|
||||||
if (!video) {
|
if (!video) {
|
||||||
logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid })
|
logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid })
|
||||||
|
@ -28,7 +28,7 @@ async function onSuccess (jobId: number, video: VideoInstance) {
|
||||||
logger.info('Job %d is a success.', jobId)
|
logger.info('Job %d is a success.', jobId)
|
||||||
|
|
||||||
// Maybe the video changed in database, refresh it
|
// Maybe the video changed in database, refresh it
|
||||||
const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid)
|
const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(video.uuid)
|
||||||
// Video does not exist anymore
|
// Video does not exist anymore
|
||||||
if (!videoDatabase) return undefined
|
if (!videoDatabase) return undefined
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ async function createLocalAccount (name: string, userId: number, applicationId:
|
||||||
followingUrl: url + '/following',
|
followingUrl: url + '/following',
|
||||||
userId,
|
userId,
|
||||||
applicationId,
|
applicationId,
|
||||||
podId: null // It is our pod
|
serverId: null // It is our server
|
||||||
})
|
})
|
||||||
|
|
||||||
return accountInstance.save({ transaction: t })
|
return accountInstance.save({ transaction: t })
|
||||||
|
|
|
@ -30,14 +30,14 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
|
||||||
return videoChannelCreated
|
return videoChannelCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchVideoChannelByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) {
|
async function fetchVideoChannelByHostAndUUID (serverHost: string, uuid: string, t: Sequelize.Transaction) {
|
||||||
try {
|
try {
|
||||||
const videoChannel = await db.VideoChannel.loadByHostAndUUID(podHost, uuid, t)
|
const videoChannel = await db.VideoChannel.loadByHostAndUUID(serverHost, uuid, t)
|
||||||
if (!videoChannel) throw new Error('Video channel not found')
|
if (!videoChannel) throw new Error('Video channel not found')
|
||||||
|
|
||||||
return videoChannel
|
return videoChannel
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Cannot load video channel from host and uuid.', { error: err.stack, podHost, uuid })
|
logger.error('Cannot load video channel from host and uuid.', { error: err.stack, serverHost, uuid })
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { NextFunction, Request, Response, RequestHandler } from 'express'
|
import { NextFunction, Request, Response, RequestHandler } from 'express'
|
||||||
import { ActivityPubSignature } from '../../shared'
|
import { ActivityPubSignature } from '../../shared'
|
||||||
import { isSignatureVerified, logger } from '../helpers'
|
import { isSignatureVerified, logger } from '../helpers'
|
||||||
import { fetchRemoteAccountAndCreatePod } from '../helpers/activitypub'
|
import { fetchRemoteAccountAndCreateServer } from '../helpers/activitypub'
|
||||||
import { database as db, ACTIVITY_PUB_ACCEPT_HEADER } from '../initializers'
|
import { database as db, ACTIVITY_PUB_ACCEPT_HEADER } from '../initializers'
|
||||||
import { each, eachSeries, waterfall } from 'async'
|
import { each, eachSeries, waterfall } from 'async'
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ async function checkSignature (req: Request, res: Response, next: NextFunction)
|
||||||
|
|
||||||
// We don't have this account in our database, fetch it on remote
|
// We don't have this account in our database, fetch it on remote
|
||||||
if (!account) {
|
if (!account) {
|
||||||
const accountResult = await fetchRemoteAccountAndCreatePod(signatureObject.creator)
|
const accountResult = await fetchRemoteAccountAndCreateServer(signatureObject.creator)
|
||||||
|
|
||||||
if (!accountResult) {
|
if (!accountResult) {
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
|
|
|
@ -3,7 +3,7 @@ export * from './activitypub'
|
||||||
export * from './async'
|
export * from './async'
|
||||||
export * from './oauth'
|
export * from './oauth'
|
||||||
export * from './pagination'
|
export * from './pagination'
|
||||||
export * from './pods'
|
export * from './servers'
|
||||||
export * from './search'
|
export * from './search'
|
||||||
export * from './sort'
|
export * from './sort'
|
||||||
export * from './user-right'
|
export * from './user-right'
|
||||||
|
|
|
@ -4,12 +4,6 @@ import * as express from 'express'
|
||||||
import { SortType } from '../helpers'
|
import { SortType } from '../helpers'
|
||||||
import { database } from '../initializers'
|
import { database } from '../initializers'
|
||||||
|
|
||||||
function setPodsSort (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
if (!req.query.sort) req.query.sort = '-createdAt'
|
|
||||||
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
|
function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
if (!req.query.sort) req.query.sort = '-createdAt'
|
if (!req.query.sort) req.query.sort = '-createdAt'
|
||||||
|
|
||||||
|
@ -70,7 +64,6 @@ function setBlacklistSort (req: express.Request, res: express.Response, next: ex
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
setPodsSort,
|
|
||||||
setUsersSort,
|
setUsersSort,
|
||||||
setVideoAbusesSort,
|
setVideoAbusesSort,
|
||||||
setVideoChannelsSort,
|
setVideoChannelsSort,
|
||||||
|
|
|
@ -2,7 +2,7 @@ export * from './account'
|
||||||
export * from './oembed'
|
export * from './oembed'
|
||||||
export * from './activitypub'
|
export * from './activitypub'
|
||||||
export * from './pagination'
|
export * from './pagination'
|
||||||
export * from './pods'
|
export * from './servers'
|
||||||
export * from './sort'
|
export * from './sort'
|
||||||
export * from './users'
|
export * from './users'
|
||||||
export * from './videos'
|
export * from './videos'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { body } from 'express-validator/check'
|
import { body } from 'express-validator/check'
|
||||||
import { isEachUniqueHostValid } from '../../helpers/custom-validators/pods'
|
import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers'
|
||||||
import { isTestInstance } from '../../helpers/core-utils'
|
import { isTestInstance } from '../../helpers/core-utils'
|
||||||
import { CONFIG } from '../../initializers/constants'
|
import { CONFIG } from '../../initializers/constants'
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
|
@ -50,7 +50,7 @@ const videoChannelsUpdateValidator = [
|
||||||
// We need to make additional checks
|
// We need to make additional checks
|
||||||
if (res.locals.videoChannel.isOwned() === false) {
|
if (res.locals.videoChannel.isOwned() === false) {
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Cannot update video channel of another pod' })
|
.json({ error: 'Cannot update video channel of another server' })
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () =>
|
||||||
// Retrieve the user who did the request
|
// Retrieve the user who did the request
|
||||||
if (res.locals.videoChannel.isOwned() === false) {
|
if (res.locals.videoChannel.isOwned() === false) {
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Cannot remove video channel of another pod.' })
|
.json({ error: 'Cannot remove video channel of another server.' })
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ const videosUpdateValidator = [
|
||||||
// We need to make additional checks
|
// We need to make additional checks
|
||||||
if (video.isOwned() === false) {
|
if (video.isOwned() === false) {
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Cannot update video of another pod' })
|
.json({ error: 'Cannot update video of another server' })
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac
|
||||||
// Retrieve the user who did the request
|
// Retrieve the user who did the request
|
||||||
if (res.locals.video.isOwned() === false) {
|
if (res.locals.video.isOwned() === false) {
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Cannot remove video of another pod, blacklist it' })
|
.json({ error: 'Cannot remove video of another server, blacklist it' })
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ listFollowingForApi = function (id: number, start: number, count: number, sort:
|
||||||
model: AccountFollow['sequelize'].models.Account,
|
model: AccountFollow['sequelize'].models.Account,
|
||||||
as: 'AccountFollowing',
|
as: 'AccountFollowing',
|
||||||
required: true,
|
required: true,
|
||||||
include: [ AccountFollow['sequelize'].models.Pod ]
|
include: [ AccountFollow['sequelize'].models.Server ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ listFollowersForApi = function (id: number, start: number, count: number, sort:
|
||||||
model: AccountFollow[ 'sequelize' ].models.Account,
|
model: AccountFollow[ 'sequelize' ].models.Account,
|
||||||
required: true,
|
required: true,
|
||||||
as: 'AccountFollower',
|
as: 'AccountFollower',
|
||||||
include: [ AccountFollow['sequelize'].models.Pod ]
|
include: [ AccountFollow['sequelize'].models.Server ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: AccountFollow['sequelize'].models.Account,
|
model: AccountFollow['sequelize'].models.Account,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import * as Bluebird from 'bluebird'
|
import * as Bluebird from 'bluebird'
|
||||||
import * as Sequelize from 'sequelize'
|
import * as Sequelize from 'sequelize'
|
||||||
import { Account as FormattedAccount, ActivityPubActor } from '../../../shared'
|
import { Account as FormattedAccount, ActivityPubActor } from '../../../shared'
|
||||||
import { ResultList } from '../../../shared/models/result-list.model'
|
import { ServerInstance } from '../server/server-interface'
|
||||||
import { PodInstance } from '../pod/pod-interface'
|
|
||||||
import { VideoChannelInstance } from '../video/video-channel-interface'
|
import { VideoChannelInstance } from '../video/video-channel-interface'
|
||||||
|
|
||||||
export namespace AccountMethods {
|
export namespace AccountMethods {
|
||||||
|
@ -11,7 +10,7 @@ export namespace AccountMethods {
|
||||||
export type Load = (id: number) => Bluebird<AccountInstance>
|
export type Load = (id: number) => Bluebird<AccountInstance>
|
||||||
export type LoadByUUID = (uuid: string) => Bluebird<AccountInstance>
|
export type LoadByUUID = (uuid: string) => Bluebird<AccountInstance>
|
||||||
export type LoadByUrl = (url: string, transaction?: Sequelize.Transaction) => Bluebird<AccountInstance>
|
export type LoadByUrl = (url: string, transaction?: Sequelize.Transaction) => Bluebird<AccountInstance>
|
||||||
export type LoadAccountByPodAndUUID = (uuid: string, podId: number, transaction: Sequelize.Transaction) => Bluebird<AccountInstance>
|
export type LoadAccountByServerAndUUID = (uuid: string, serverId: number, transaction: Sequelize.Transaction) => Bluebird<AccountInstance>
|
||||||
export type LoadLocalByName = (name: string) => Bluebird<AccountInstance>
|
export type LoadLocalByName = (name: string) => Bluebird<AccountInstance>
|
||||||
export type LoadByNameAndHost = (name: string, host: string) => Bluebird<AccountInstance>
|
export type LoadByNameAndHost = (name: string, host: string) => Bluebird<AccountInstance>
|
||||||
export type ListOwned = () => Bluebird<AccountInstance[]>
|
export type ListOwned = () => Bluebird<AccountInstance[]>
|
||||||
|
@ -27,7 +26,7 @@ export namespace AccountMethods {
|
||||||
|
|
||||||
export interface AccountClass {
|
export interface AccountClass {
|
||||||
loadApplication: AccountMethods.LoadApplication
|
loadApplication: AccountMethods.LoadApplication
|
||||||
loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID
|
loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
|
||||||
load: AccountMethods.Load
|
load: AccountMethods.Load
|
||||||
loadByUUID: AccountMethods.LoadByUUID
|
loadByUUID: AccountMethods.LoadByUUID
|
||||||
loadByUrl: AccountMethods.LoadByUrl
|
loadByUrl: AccountMethods.LoadByUrl
|
||||||
|
@ -51,7 +50,7 @@ export interface AccountAttributes {
|
||||||
|
|
||||||
uuid?: string
|
uuid?: string
|
||||||
|
|
||||||
podId?: number
|
serverId?: number
|
||||||
userId?: number
|
userId?: number
|
||||||
applicationId?: number
|
applicationId?: number
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,7 @@ export interface AccountInstance extends AccountClass, AccountAttributes, Sequel
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
|
|
||||||
Pod: PodInstance
|
Server: ServerInstance
|
||||||
VideoChannels: VideoChannelInstance[]
|
VideoChannels: VideoChannelInstance[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { sendDeleteAccount } from '../../lib/activitypub/send-request'
|
||||||
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
||||||
|
|
||||||
let Account: Sequelize.Model<AccountInstance, AccountAttributes>
|
let Account: Sequelize.Model<AccountInstance, AccountAttributes>
|
||||||
let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID
|
let loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
|
||||||
let load: AccountMethods.Load
|
let load: AccountMethods.Load
|
||||||
let loadApplication: AccountMethods.LoadApplication
|
let loadApplication: AccountMethods.LoadApplication
|
||||||
let loadByUUID: AccountMethods.LoadByUUID
|
let loadByUUID: AccountMethods.LoadByUUID
|
||||||
|
@ -170,7 +170,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
|
||||||
fields: [ 'name' ]
|
fields: [ 'name' ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: [ 'podId' ]
|
fields: [ 'serverId' ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: [ 'userId' ],
|
fields: [ 'userId' ],
|
||||||
|
@ -181,7 +181,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: [ 'name', 'podId', 'applicationId' ],
|
fields: [ 'name', 'serverId', 'applicationId' ],
|
||||||
unique: true
|
unique: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -191,7 +191,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
|
||||||
|
|
||||||
const classMethods = [
|
const classMethods = [
|
||||||
associate,
|
associate,
|
||||||
loadAccountByPodAndUUID,
|
loadAccountByServerAndUUID,
|
||||||
loadApplication,
|
loadApplication,
|
||||||
load,
|
load,
|
||||||
loadByUUID,
|
loadByUUID,
|
||||||
|
@ -217,9 +217,9 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function associate (models) {
|
function associate (models) {
|
||||||
Account.belongsTo(models.Pod, {
|
Account.belongsTo(models.Server, {
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
name: 'podId',
|
name: 'serverId',
|
||||||
allowNull: true
|
allowNull: true
|
||||||
},
|
},
|
||||||
onDelete: 'cascade'
|
onDelete: 'cascade'
|
||||||
|
@ -278,19 +278,28 @@ function afterDestroy (account: AccountInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
toFormattedJSON = function (this: AccountInstance) {
|
toFormattedJSON = function (this: AccountInstance) {
|
||||||
let host = this.Pod ? this.Pod.host : CONFIG.WEBSERVER.HOST
|
let host = CONFIG.WEBSERVER.HOST
|
||||||
|
let score: number
|
||||||
|
|
||||||
|
if (this.Server) {
|
||||||
|
host = this.Server.host
|
||||||
|
score = this.Server.score as number
|
||||||
|
}
|
||||||
|
|
||||||
const json = {
|
const json = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
host,
|
host,
|
||||||
name: this.name
|
score,
|
||||||
|
name: this.name,
|
||||||
|
createdAt: this.createdAt,
|
||||||
|
updatedAt: this.updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
toActivityPubObject = function (this: AccountInstance) {
|
toActivityPubObject = function (this: AccountInstance) {
|
||||||
const type = this.podId ? 'Application' as 'Application' : 'Person' as 'Person'
|
const type = this.serverId ? 'Application' as 'Application' : 'Person' as 'Person'
|
||||||
|
|
||||||
const json = {
|
const json = {
|
||||||
type,
|
type,
|
||||||
|
@ -317,7 +326,7 @@ toActivityPubObject = function (this: AccountInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
isOwned = function (this: AccountInstance) {
|
isOwned = function (this: AccountInstance) {
|
||||||
return this.podId === null
|
return this.serverId === null
|
||||||
}
|
}
|
||||||
|
|
||||||
getFollowerSharedInboxUrls = function (this: AccountInstance) {
|
getFollowerSharedInboxUrls = function (this: AccountInstance) {
|
||||||
|
@ -356,7 +365,7 @@ getPublicKeyUrl = function (this: AccountInstance) {
|
||||||
listOwned = function () {
|
listOwned = function () {
|
||||||
const query: Sequelize.FindOptions<AccountAttributes> = {
|
const query: Sequelize.FindOptions<AccountAttributes> = {
|
||||||
where: {
|
where: {
|
||||||
podId: null
|
serverId: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +426,7 @@ loadByNameAndHost = function (name: string, host: string) {
|
||||||
},
|
},
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Account['sequelize'].models.Pod,
|
model: Account['sequelize'].models.Server,
|
||||||
required: true,
|
required: true,
|
||||||
where: {
|
where: {
|
||||||
host
|
host
|
||||||
|
@ -440,10 +449,10 @@ loadByUrl = function (url: string, transaction?: Sequelize.Transaction) {
|
||||||
return Account.findOne(query)
|
return Account.findOne(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAccountByPodAndUUID = function (uuid: string, podId: number, transaction: Sequelize.Transaction) {
|
loadAccountByServerAndUUID = function (uuid: string, serverId: number, transaction: Sequelize.Transaction) {
|
||||||
const query: Sequelize.FindOptions<AccountAttributes> = {
|
const query: Sequelize.FindOptions<AccountAttributes> = {
|
||||||
where: {
|
where: {
|
||||||
podId,
|
serverId,
|
||||||
uuid
|
uuid
|
||||||
},
|
},
|
||||||
transaction
|
transaction
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export * from './application'
|
export * from './application'
|
||||||
export * from './job'
|
export * from './job'
|
||||||
export * from './oauth'
|
export * from './oauth'
|
||||||
export * from './pod'
|
export * from './server'
|
||||||
export * from './account'
|
export * from './account'
|
||||||
export * from './video'
|
export * from './video'
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './pod-interface'
|
|
|
@ -1,61 +0,0 @@
|
||||||
import * as Sequelize from 'sequelize'
|
|
||||||
import * as Promise from 'bluebird'
|
|
||||||
|
|
||||||
// Don't use barrel, import just what we need
|
|
||||||
import { Pod as FormattedPod } from '../../../shared/models/pods/pod.model'
|
|
||||||
import { ResultList } from '../../../shared/models/result-list.model'
|
|
||||||
|
|
||||||
export namespace PodMethods {
|
|
||||||
export type ToFormattedJSON = (this: PodInstance) => FormattedPod
|
|
||||||
|
|
||||||
export type CountAll = () => Promise<number>
|
|
||||||
|
|
||||||
export type IncrementScores = (ids: number[], value: number) => Promise<[ number, PodInstance[] ]>
|
|
||||||
|
|
||||||
export type List = () => Promise<PodInstance[]>
|
|
||||||
|
|
||||||
export type ListForApi = (start: number, count: number, sort: string) => Promise< ResultList<PodInstance> >
|
|
||||||
|
|
||||||
export type ListAllIds = (transaction: Sequelize.Transaction) => Promise<number[]>
|
|
||||||
|
|
||||||
export type ListRandomPodIdsWithRequest = (limit: number, tableWithPods: string, tableWithPodsJoins: string) => Promise<number[]>
|
|
||||||
|
|
||||||
export type ListBadPods = () => Promise<PodInstance[]>
|
|
||||||
|
|
||||||
export type Load = (id: number) => Promise<PodInstance>
|
|
||||||
|
|
||||||
export type LoadByHost = (host: string) => Promise<PodInstance>
|
|
||||||
|
|
||||||
export type RemoveAll = () => Promise<number>
|
|
||||||
|
|
||||||
export type UpdatePodsScore = (goodPods: number[], badPods: number[]) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PodClass {
|
|
||||||
countAll: PodMethods.CountAll
|
|
||||||
incrementScores: PodMethods.IncrementScores
|
|
||||||
list: PodMethods.List
|
|
||||||
listForApi: PodMethods.ListForApi
|
|
||||||
listAllIds: PodMethods.ListAllIds
|
|
||||||
listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
|
|
||||||
listBadPods: PodMethods.ListBadPods
|
|
||||||
load: PodMethods.Load
|
|
||||||
loadByHost: PodMethods.LoadByHost
|
|
||||||
removeAll: PodMethods.RemoveAll
|
|
||||||
updatePodsScore: PodMethods.UpdatePodsScore
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PodAttributes {
|
|
||||||
id?: number
|
|
||||||
host?: string
|
|
||||||
score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
|
|
||||||
createdAt: Date
|
|
||||||
updatedAt: Date
|
|
||||||
|
|
||||||
toFormattedJSON: PodMethods.ToFormattedJSON,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}
|
|
|
@ -1,248 +0,0 @@
|
||||||
import { map } from 'lodash'
|
|
||||||
import * as Sequelize from 'sequelize'
|
|
||||||
|
|
||||||
import { FRIEND_SCORE, PODS_SCORE } from '../../initializers'
|
|
||||||
import { logger, isHostValid } from '../../helpers'
|
|
||||||
|
|
||||||
import { addMethodsToModel, getSort } from '../utils'
|
|
||||||
import {
|
|
||||||
PodInstance,
|
|
||||||
PodAttributes,
|
|
||||||
|
|
||||||
PodMethods
|
|
||||||
} from './pod-interface'
|
|
||||||
|
|
||||||
let Pod: Sequelize.Model<PodInstance, PodAttributes>
|
|
||||||
let toFormattedJSON: PodMethods.ToFormattedJSON
|
|
||||||
let countAll: PodMethods.CountAll
|
|
||||||
let incrementScores: PodMethods.IncrementScores
|
|
||||||
let list: PodMethods.List
|
|
||||||
let listForApi: PodMethods.ListForApi
|
|
||||||
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: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
|
||||||
Pod = sequelize.define<PodInstance, PodAttributes>('Pod',
|
|
||||||
{
|
|
||||||
host: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
isHost: value => {
|
|
||||||
const res = isHostValid(value)
|
|
||||||
if (res === false) throw new Error('Host not valid.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
score: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
defaultValue: FRIEND_SCORE.BASE,
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
isInt: true,
|
|
||||||
max: FRIEND_SCORE.MAX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
indexes: [
|
|
||||||
{
|
|
||||||
fields: [ 'host' ],
|
|
||||||
unique: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fields: [ 'score' ]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const classMethods = [
|
|
||||||
countAll,
|
|
||||||
incrementScores,
|
|
||||||
list,
|
|
||||||
listForApi,
|
|
||||||
listAllIds,
|
|
||||||
listRandomPodIdsWithRequest,
|
|
||||||
listBadPods,
|
|
||||||
load,
|
|
||||||
loadByHost,
|
|
||||||
updatePodsScore,
|
|
||||||
removeAll
|
|
||||||
]
|
|
||||||
const instanceMethods = [ toFormattedJSON ]
|
|
||||||
addMethodsToModel(Pod, classMethods, instanceMethods)
|
|
||||||
|
|
||||||
return Pod
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------ METHODS ------------------------------
|
|
||||||
|
|
||||||
toFormattedJSON = function (this: PodInstance) {
|
|
||||||
const json = {
|
|
||||||
id: this.id,
|
|
||||||
host: this.host,
|
|
||||||
score: this.score as number,
|
|
||||||
createdAt: this.createdAt
|
|
||||||
}
|
|
||||||
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------ Statics ------------------------------
|
|
||||||
|
|
||||||
countAll = function () {
|
|
||||||
return Pod.count()
|
|
||||||
}
|
|
||||||
|
|
||||||
incrementScores = function (ids: number[], value: number) {
|
|
||||||
const update = {
|
|
||||||
score: Sequelize.literal('score +' + value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Sequelize.Op.in]: ids
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// In this case score is a literal and not an integer so we do not validate it
|
|
||||||
validate: false
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.update(update, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
list = function () {
|
|
||||||
return Pod.findAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
listForApi = function (start: number, count: number, sort: string) {
|
|
||||||
const query = {
|
|
||||||
offset: start,
|
|
||||||
limit: count,
|
|
||||||
order: [ getSort(sort) ]
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.findAndCountAll(query).then(({ rows, count }) => {
|
|
||||||
return {
|
|
||||||
data: rows,
|
|
||||||
total: count
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listAllIds = function (transaction: Sequelize.Transaction) {
|
|
||||||
const query = {
|
|
||||||
attributes: [ 'id' ],
|
|
||||||
transaction
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.findAll(query).then(pods => {
|
|
||||||
return map(pods, 'id')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listRandomPodIdsWithRequest = function (limit: number, tableWithPods: string, tableWithPodsJoins: string) {
|
|
||||||
return Pod.count().then(count => {
|
|
||||||
// Optimization...
|
|
||||||
if (count === 0) return []
|
|
||||||
|
|
||||||
let start = Math.floor(Math.random() * count) - limit
|
|
||||||
if (start < 0) start = 0
|
|
||||||
|
|
||||||
const subQuery = `(SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins})`
|
|
||||||
const query = {
|
|
||||||
attributes: [ 'id' ],
|
|
||||||
order: [
|
|
||||||
[ 'id', 'ASC' ]
|
|
||||||
],
|
|
||||||
offset: start,
|
|
||||||
limit: limit,
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Sequelize.Op.in]: Sequelize.literal(subQuery)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.findAll(query).then(pods => {
|
|
||||||
return map(pods, 'id')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listBadPods = function () {
|
|
||||||
const query = {
|
|
||||||
where: {
|
|
||||||
score: {
|
|
||||||
[Sequelize.Op.lte]: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.findAll(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
load = function (id: number) {
|
|
||||||
return Pod.findById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadByHost = function (host: string) {
|
|
||||||
const query = {
|
|
||||||
where: {
|
|
||||||
host: host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pod.findOne(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeAll = function () {
|
|
||||||
return Pod.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePodsScore = function (goodPods: number[], badPods: number[]) {
|
|
||||||
logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
|
|
||||||
|
|
||||||
if (goodPods.length !== 0) {
|
|
||||||
incrementScores(goodPods, PODS_SCORE.BONUS).catch(err => {
|
|
||||||
logger.error('Cannot increment scores of good pods.', err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badPods.length !== 0) {
|
|
||||||
incrementScores(badPods, PODS_SCORE.PENALTY)
|
|
||||||
.then(() => removeBadPods())
|
|
||||||
.catch(err => {
|
|
||||||
if (err) logger.error('Cannot decrement scores of bad pods.', err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Remove pods with a score of 0 (too many requests where they were unreachable)
|
|
||||||
async function removeBadPods () {
|
|
||||||
try {
|
|
||||||
const pods = await listBadPods()
|
|
||||||
|
|
||||||
const podsRemovePromises = pods.map(pod => pod.destroy())
|
|
||||||
await Promise.all(podsRemovePromises)
|
|
||||||
|
|
||||||
const numberOfPodsRemoved = pods.length
|
|
||||||
|
|
||||||
if (numberOfPodsRemoved) {
|
|
||||||
logger.info('Removed %d pods.', numberOfPodsRemoved)
|
|
||||||
} else {
|
|
||||||
logger.info('No need to remove bad pods.')
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logger.error('Cannot remove bad pods.', err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './server-interface'
|
|
@ -0,0 +1,56 @@
|
||||||
|
import * as Sequelize from 'sequelize'
|
||||||
|
import * as Promise from 'bluebird'
|
||||||
|
|
||||||
|
// Don't use barrel, import just what we need
|
||||||
|
import { ResultList } from '../../../shared/models/result-list.model'
|
||||||
|
|
||||||
|
export namespace ServerMethods {
|
||||||
|
export type CountAll = () => Promise<number>
|
||||||
|
|
||||||
|
export type IncrementScores = (ids: number[], value: number) => Promise<[ number, ServerInstance[] ]>
|
||||||
|
|
||||||
|
export type List = () => Promise<ServerInstance[]>
|
||||||
|
|
||||||
|
export type ListForApi = (start: number, count: number, sort: string) => Promise< ResultList<ServerInstance> >
|
||||||
|
|
||||||
|
export type ListAllIds = (transaction: Sequelize.Transaction) => Promise<number[]>
|
||||||
|
|
||||||
|
export type ListRandomServerIdsWithRequest = (limit: number, tableWithServers: string, tableWithServersJoins: string) => Promise<number[]>
|
||||||
|
|
||||||
|
export type ListBadServers = () => Promise<ServerInstance[]>
|
||||||
|
|
||||||
|
export type Load = (id: number) => Promise<ServerInstance>
|
||||||
|
|
||||||
|
export type LoadByHost = (host: string) => Promise<ServerInstance>
|
||||||
|
|
||||||
|
export type RemoveAll = () => Promise<number>
|
||||||
|
|
||||||
|
export type UpdateServersScore = (goodServers: number[], badServers: number[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerClass {
|
||||||
|
countAll: ServerMethods.CountAll
|
||||||
|
incrementScores: ServerMethods.IncrementScores
|
||||||
|
list: ServerMethods.List
|
||||||
|
listForApi: ServerMethods.ListForApi
|
||||||
|
listAllIds: ServerMethods.ListAllIds
|
||||||
|
listRandomServerIdsWithRequest: ServerMethods.ListRandomServerIdsWithRequest
|
||||||
|
listBadServers: ServerMethods.ListBadServers
|
||||||
|
load: ServerMethods.Load
|
||||||
|
loadByHost: ServerMethods.LoadByHost
|
||||||
|
removeAll: ServerMethods.RemoveAll
|
||||||
|
updateServersScore: ServerMethods.UpdateServersScore
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerAttributes {
|
||||||
|
id?: number
|
||||||
|
host?: string
|
||||||
|
score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerInstance extends ServerClass, ServerAttributes, Sequelize.Instance<ServerAttributes> {
|
||||||
|
createdAt: Date
|
||||||
|
updatedAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerModel extends ServerClass, Sequelize.Model<ServerInstance, ServerAttributes> {}
|
|
@ -0,0 +1,233 @@
|
||||||
|
import { map } from 'lodash'
|
||||||
|
import * as Sequelize from 'sequelize'
|
||||||
|
|
||||||
|
import { FRIEND_SCORE, SERVERS_SCORE } from '../../initializers'
|
||||||
|
import { logger, isHostValid } from '../../helpers'
|
||||||
|
|
||||||
|
import { addMethodsToModel, getSort } from '../utils'
|
||||||
|
import {
|
||||||
|
ServerInstance,
|
||||||
|
ServerAttributes,
|
||||||
|
|
||||||
|
ServerMethods
|
||||||
|
} from './server-interface'
|
||||||
|
|
||||||
|
let Server: Sequelize.Model<ServerInstance, ServerAttributes>
|
||||||
|
let countAll: ServerMethods.CountAll
|
||||||
|
let incrementScores: ServerMethods.IncrementScores
|
||||||
|
let list: ServerMethods.List
|
||||||
|
let listForApi: ServerMethods.ListForApi
|
||||||
|
let listAllIds: ServerMethods.ListAllIds
|
||||||
|
let listRandomServerIdsWithRequest: ServerMethods.ListRandomServerIdsWithRequest
|
||||||
|
let listBadServers: ServerMethods.ListBadServers
|
||||||
|
let load: ServerMethods.Load
|
||||||
|
let loadByHost: ServerMethods.LoadByHost
|
||||||
|
let removeAll: ServerMethods.RemoveAll
|
||||||
|
let updateServersScore: ServerMethods.UpdateServersScore
|
||||||
|
|
||||||
|
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||||
|
Server = sequelize.define<ServerInstance, ServerAttributes>('Server',
|
||||||
|
{
|
||||||
|
host: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
isHost: value => {
|
||||||
|
const res = isHostValid(value)
|
||||||
|
if (res === false) throw new Error('Host not valid.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
score: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
defaultValue: FRIEND_SCORE.BASE,
|
||||||
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
isInt: true,
|
||||||
|
max: FRIEND_SCORE.MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
fields: [ 'host' ],
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: [ 'score' ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const classMethods = [
|
||||||
|
countAll,
|
||||||
|
incrementScores,
|
||||||
|
list,
|
||||||
|
listForApi,
|
||||||
|
listAllIds,
|
||||||
|
listRandomServerIdsWithRequest,
|
||||||
|
listBadServers,
|
||||||
|
load,
|
||||||
|
loadByHost,
|
||||||
|
updateServersScore,
|
||||||
|
removeAll
|
||||||
|
]
|
||||||
|
addMethodsToModel(Server, classMethods)
|
||||||
|
|
||||||
|
return Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------ Statics ------------------------------
|
||||||
|
|
||||||
|
countAll = function () {
|
||||||
|
return Server.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
incrementScores = function (ids: number[], value: number) {
|
||||||
|
const update = {
|
||||||
|
score: Sequelize.literal('score +' + value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
[Sequelize.Op.in]: ids
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// In this case score is a literal and not an integer so we do not validate it
|
||||||
|
validate: false
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.update(update, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
list = function () {
|
||||||
|
return Server.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
listForApi = function (start: number, count: number, sort: string) {
|
||||||
|
const query = {
|
||||||
|
offset: start,
|
||||||
|
limit: count,
|
||||||
|
order: [ getSort(sort) ]
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.findAndCountAll(query).then(({ rows, count }) => {
|
||||||
|
return {
|
||||||
|
data: rows,
|
||||||
|
total: count
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listAllIds = function (transaction: Sequelize.Transaction) {
|
||||||
|
const query = {
|
||||||
|
attributes: [ 'id' ],
|
||||||
|
transaction
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.findAll(query).then(servers => {
|
||||||
|
return map(servers, 'id')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listRandomServerIdsWithRequest = function (limit: number, tableWithServers: string, tableWithServersJoins: string) {
|
||||||
|
return Server.count().then(count => {
|
||||||
|
// Optimization...
|
||||||
|
if (count === 0) return []
|
||||||
|
|
||||||
|
let start = Math.floor(Math.random() * count) - limit
|
||||||
|
if (start < 0) start = 0
|
||||||
|
|
||||||
|
const subQuery = `(SELECT DISTINCT "${tableWithServers}"."serverId" FROM "${tableWithServers}" ${tableWithServersJoins})`
|
||||||
|
const query = {
|
||||||
|
attributes: [ 'id' ],
|
||||||
|
order: [
|
||||||
|
[ 'id', 'ASC' ]
|
||||||
|
],
|
||||||
|
offset: start,
|
||||||
|
limit: limit,
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
[Sequelize.Op.in]: Sequelize.literal(subQuery)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.findAll(query).then(servers => {
|
||||||
|
return map(servers, 'id')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listBadServers = function () {
|
||||||
|
const query = {
|
||||||
|
where: {
|
||||||
|
score: {
|
||||||
|
[Sequelize.Op.lte]: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.findAll(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
load = function (id: number) {
|
||||||
|
return Server.findById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadByHost = function (host: string) {
|
||||||
|
const query = {
|
||||||
|
where: {
|
||||||
|
host: host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Server.findOne(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAll = function () {
|
||||||
|
return Server.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateServersScore = function (goodServers: number[], badServers: number[]) {
|
||||||
|
logger.info('Updating %d good servers and %d bad servers scores.', goodServers.length, badServers.length)
|
||||||
|
|
||||||
|
if (goodServers.length !== 0) {
|
||||||
|
incrementScores(goodServers, SERVERS_SCORE.BONUS).catch(err => {
|
||||||
|
logger.error('Cannot increment scores of good servers.', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badServers.length !== 0) {
|
||||||
|
incrementScores(badServers, SERVERS_SCORE.PENALTY)
|
||||||
|
.then(() => removeBadServers())
|
||||||
|
.catch(err => {
|
||||||
|
if (err) logger.error('Cannot decrement scores of bad servers.', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Remove servers with a score of 0 (too many requests where they were unreachable)
|
||||||
|
async function removeBadServers () {
|
||||||
|
try {
|
||||||
|
const servers = await listBadServers()
|
||||||
|
|
||||||
|
const serversRemovePromises = servers.map(server => server.destroy())
|
||||||
|
await Promise.all(serversRemovePromises)
|
||||||
|
|
||||||
|
const numberOfServersRemoved = servers.length
|
||||||
|
|
||||||
|
if (numberOfServersRemoved) {
|
||||||
|
logger.info('Removed %d servers.', numberOfServersRemoved)
|
||||||
|
} else {
|
||||||
|
logger.info('No need to remove bad servers.')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Cannot remove bad servers.', err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import * as Sequelize from 'sequelize'
|
import * as Sequelize from 'sequelize'
|
||||||
import * as Promise from 'bluebird'
|
import * as Promise from 'bluebird'
|
||||||
|
|
||||||
import { PodInstance } from '../pod/pod-interface'
|
import { ServerInstance } from '../server/server-interface'
|
||||||
import { ResultList } from '../../../shared'
|
import { ResultList } from '../../../shared'
|
||||||
|
|
||||||
// Don't use barrel, import just what we need
|
// Don't use barrel, import just what we need
|
||||||
|
@ -28,7 +28,7 @@ export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttribute
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
|
|
||||||
Pod: PodInstance
|
Server: ServerInstance
|
||||||
|
|
||||||
toFormattedJSON: VideoAbuseMethods.ToFormattedJSON
|
toFormattedJSON: VideoAbuseMethods.ToFormattedJSON
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
||||||
fields: [ 'videoId' ]
|
fields: [ 'videoId' ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fields: [ 'reporterPodId' ]
|
fields: [ 'reporterServerId' ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -67,18 +67,18 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
||||||
// ------------------------------ METHODS ------------------------------
|
// ------------------------------ METHODS ------------------------------
|
||||||
|
|
||||||
toFormattedJSON = function (this: VideoAbuseInstance) {
|
toFormattedJSON = function (this: VideoAbuseInstance) {
|
||||||
let reporterPodHost
|
let reporterServerHost
|
||||||
|
|
||||||
if (this.Pod) {
|
if (this.Server) {
|
||||||
reporterPodHost = this.Pod.host
|
reporterServerHost = this.Server.host
|
||||||
} else {
|
} else {
|
||||||
// It means it's our video
|
// It means it's our video
|
||||||
reporterPodHost = CONFIG.WEBSERVER.HOST
|
reporterServerHost = CONFIG.WEBSERVER.HOST
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = {
|
const json = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
reporterPodHost,
|
reporterServerHost,
|
||||||
reason: this.reason,
|
reason: this.reason,
|
||||||
reporterUsername: this.reporterUsername,
|
reporterUsername: this.reporterUsername,
|
||||||
videoId: this.videoId,
|
videoId: this.videoId,
|
||||||
|
@ -91,9 +91,9 @@ toFormattedJSON = function (this: VideoAbuseInstance) {
|
||||||
// ------------------------------ STATICS ------------------------------
|
// ------------------------------ STATICS ------------------------------
|
||||||
|
|
||||||
function associate (models) {
|
function associate (models) {
|
||||||
VideoAbuse.belongsTo(models.Pod, {
|
VideoAbuse.belongsTo(models.Server, {
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
name: 'reporterPodId',
|
name: 'reporterServerId',
|
||||||
allowNull: true
|
allowNull: true
|
||||||
},
|
},
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE'
|
||||||
|
@ -115,7 +115,7 @@ listForApi = function (start: number, count: number, sort: string) {
|
||||||
order: [ getSort(sort) ],
|
order: [ getSort(sort) ],
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoAbuse['sequelize'].models.Pod,
|
model: VideoAbuse['sequelize'].models.Server,
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,7 +22,7 @@ export namespace VideoChannelMethods {
|
||||||
export type LoadAndPopulateAccount = (id: number) => Promise<VideoChannelInstance>
|
export type LoadAndPopulateAccount = (id: number) => Promise<VideoChannelInstance>
|
||||||
export type LoadByUUIDAndPopulateAccount = (uuid: string) => Promise<VideoChannelInstance>
|
export type LoadByUUIDAndPopulateAccount = (uuid: string) => Promise<VideoChannelInstance>
|
||||||
export type LoadByUUID = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
export type LoadByUUID = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
||||||
export type LoadByHostAndUUID = (uuid: string, podHost: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
export type LoadByHostAndUUID = (uuid: string, serverHost: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
||||||
export type LoadAndPopulateAccountAndVideos = (id: number) => Promise<VideoChannelInstance>
|
export type LoadAndPopulateAccountAndVideos = (id: number) => Promise<VideoChannelInstance>
|
||||||
export type LoadByUrl = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
export type LoadByUrl = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
||||||
export type LoadByUUIDOrUrl = (uuid: string, url: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
export type LoadByUUIDOrUrl = (uuid: string, url: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
|
||||||
|
|
|
@ -218,7 +218,7 @@ listForApi = function (start: number, count: number, sort: string) {
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
required: true,
|
required: true,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ listByAccount = function (accountId: number) {
|
||||||
id: accountId
|
id: accountId
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Tran
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Pod,
|
model: VideoChannel['sequelize'].models.Server,
|
||||||
required: true,
|
required: true,
|
||||||
where: {
|
where: {
|
||||||
host: fromHost
|
host: fromHost
|
||||||
|
@ -322,7 +322,7 @@ loadByIdAndAccount = function (id: number, accountId: number) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ loadAndPopulateAccount = function (id: number) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,7 @@ loadByUUIDAndPopulateAccount = function (uuid: string) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ loadAndPopulateAccountAndVideos = function (id: number) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: VideoChannel['sequelize'].models.Account,
|
model: VideoChannel['sequelize'].models.Account,
|
||||||
include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
|
include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
|
||||||
},
|
},
|
||||||
VideoChannel['sequelize'].models.Video
|
VideoChannel['sequelize'].models.Video
|
||||||
]
|
]
|
||||||
|
|
|
@ -46,7 +46,7 @@ export namespace VideoMethods {
|
||||||
|
|
||||||
export type ListForApi = (start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
export type ListForApi = (start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
||||||
export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
||||||
export type SearchAndPopulateAccountAndPodAndTags = (
|
export type SearchAndPopulateAccountAndServerAndTags = (
|
||||||
value: string,
|
value: string,
|
||||||
field: string,
|
field: string,
|
||||||
start: number,
|
start: number,
|
||||||
|
@ -60,8 +60,8 @@ export namespace VideoMethods {
|
||||||
export type LoadLocalVideoByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
export type LoadLocalVideoByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||||
export type LoadByHostAndUUID = (fromHost: string, uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
export type LoadByHostAndUUID = (fromHost: string, uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||||
export type LoadAndPopulateAccount = (id: number) => Bluebird<VideoInstance>
|
export type LoadAndPopulateAccount = (id: number) => Bluebird<VideoInstance>
|
||||||
export type LoadAndPopulateAccountAndPodAndTags = (id: number) => Bluebird<VideoInstance>
|
export type LoadAndPopulateAccountAndServerAndTags = (id: number) => Bluebird<VideoInstance>
|
||||||
export type LoadByUUIDAndPopulateAccountAndPodAndTags = (uuid: string) => Bluebird<VideoInstance>
|
export type LoadByUUIDAndPopulateAccountAndServerAndTags = (uuid: string) => Bluebird<VideoInstance>
|
||||||
export type LoadByUUIDOrURL = (uuid: string, url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
export type LoadByUUIDOrURL = (uuid: string, url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||||
|
|
||||||
export type RemoveThumbnail = (this: VideoInstance) => Promise<void>
|
export type RemoveThumbnail = (this: VideoInstance) => Promise<void>
|
||||||
|
@ -79,14 +79,14 @@ export interface VideoClass {
|
||||||
listOwnedByAccount: VideoMethods.ListOwnedByAccount
|
listOwnedByAccount: VideoMethods.ListOwnedByAccount
|
||||||
load: VideoMethods.Load
|
load: VideoMethods.Load
|
||||||
loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
|
loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
|
||||||
loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags
|
loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
|
||||||
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
||||||
loadByUUID: VideoMethods.LoadByUUID
|
loadByUUID: VideoMethods.LoadByUUID
|
||||||
loadByUrl: VideoMethods.LoadByUrl
|
loadByUrl: VideoMethods.LoadByUrl
|
||||||
loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
||||||
loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
||||||
loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags
|
loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
|
||||||
searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags
|
searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoAttributes {
|
export interface VideoAttributes {
|
||||||
|
|
|
@ -88,9 +88,9 @@ let loadByUUID: VideoMethods.LoadByUUID
|
||||||
let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
||||||
let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
||||||
let loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
|
let loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
|
||||||
let loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags
|
let loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
|
||||||
let loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags
|
let loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
|
||||||
let searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags
|
let searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
|
||||||
let removeThumbnail: VideoMethods.RemoveThumbnail
|
let removeThumbnail: VideoMethods.RemoveThumbnail
|
||||||
let removePreview: VideoMethods.RemovePreview
|
let removePreview: VideoMethods.RemovePreview
|
||||||
let removeFile: VideoMethods.RemoveFile
|
let removeFile: VideoMethods.RemoveFile
|
||||||
|
@ -275,13 +275,13 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
||||||
listOwnedByAccount,
|
listOwnedByAccount,
|
||||||
load,
|
load,
|
||||||
loadAndPopulateAccount,
|
loadAndPopulateAccount,
|
||||||
loadAndPopulateAccountAndPodAndTags,
|
loadAndPopulateAccountAndServerAndTags,
|
||||||
loadByHostAndUUID,
|
loadByHostAndUUID,
|
||||||
loadByUUIDOrURL,
|
loadByUUIDOrURL,
|
||||||
loadByUUID,
|
loadByUUID,
|
||||||
loadLocalVideoByUUID,
|
loadLocalVideoByUUID,
|
||||||
loadByUUIDAndPopulateAccountAndPodAndTags,
|
loadByUUIDAndPopulateAccountAndServerAndTags,
|
||||||
searchAndPopulateAccountAndPodAndTags
|
searchAndPopulateAccountAndServerAndTags
|
||||||
]
|
]
|
||||||
const instanceMethods = [
|
const instanceMethods = [
|
||||||
createPreview,
|
createPreview,
|
||||||
|
@ -477,13 +477,13 @@ getPreviewPath = function (this: VideoInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
toFormattedJSON = function (this: VideoInstance) {
|
toFormattedJSON = function (this: VideoInstance) {
|
||||||
let podHost
|
let serverHost
|
||||||
|
|
||||||
if (this.VideoChannel.Account.Pod) {
|
if (this.VideoChannel.Account.Server) {
|
||||||
podHost = this.VideoChannel.Account.Pod.host
|
serverHost = this.VideoChannel.Account.Server.host
|
||||||
} else {
|
} else {
|
||||||
// It means it's our video
|
// It means it's our video
|
||||||
podHost = CONFIG.WEBSERVER.HOST
|
serverHost = CONFIG.WEBSERVER.HOST
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = {
|
const json = {
|
||||||
|
@ -498,7 +498,7 @@ toFormattedJSON = function (this: VideoInstance) {
|
||||||
languageLabel: this.getLanguageLabel(),
|
languageLabel: this.getLanguageLabel(),
|
||||||
nsfw: this.nsfw,
|
nsfw: this.nsfw,
|
||||||
description: this.getTruncatedDescription(),
|
description: this.getTruncatedDescription(),
|
||||||
podHost,
|
serverHost,
|
||||||
isLocal: this.isOwned(),
|
isLocal: this.isOwned(),
|
||||||
account: this.VideoChannel.Account.name,
|
account: this.VideoChannel.Account.name,
|
||||||
duration: this.duration,
|
duration: this.duration,
|
||||||
|
@ -519,7 +519,7 @@ toFormattedJSON = function (this: VideoInstance) {
|
||||||
toFormattedDetailsJSON = function (this: VideoInstance) {
|
toFormattedDetailsJSON = function (this: VideoInstance) {
|
||||||
const formattedJson = this.toFormattedJSON()
|
const formattedJson = this.toFormattedJSON()
|
||||||
|
|
||||||
// Maybe our pod is not up to date and there are new privacy settings since our version
|
// Maybe our server is not up to date and there are new privacy settings since our version
|
||||||
let privacyLabel = VIDEO_PRIVACIES[this.privacy]
|
let privacyLabel = VIDEO_PRIVACIES[this.privacy]
|
||||||
if (!privacyLabel) privacyLabel = 'Unknown'
|
if (!privacyLabel) privacyLabel = 'Unknown'
|
||||||
|
|
||||||
|
@ -721,7 +721,7 @@ getDescriptionPath = function (this: VideoInstance) {
|
||||||
getCategoryLabel = function (this: VideoInstance) {
|
getCategoryLabel = function (this: VideoInstance) {
|
||||||
let categoryLabel = VIDEO_CATEGORIES[this.category]
|
let categoryLabel = VIDEO_CATEGORIES[this.category]
|
||||||
|
|
||||||
// Maybe our pod is not up to date and there are new categories since our version
|
// Maybe our server is not up to date and there are new categories since our version
|
||||||
if (!categoryLabel) categoryLabel = 'Misc'
|
if (!categoryLabel) categoryLabel = 'Misc'
|
||||||
|
|
||||||
return categoryLabel
|
return categoryLabel
|
||||||
|
@ -730,7 +730,7 @@ getCategoryLabel = function (this: VideoInstance) {
|
||||||
getLicenceLabel = function (this: VideoInstance) {
|
getLicenceLabel = function (this: VideoInstance) {
|
||||||
let licenceLabel = VIDEO_LICENCES[this.licence]
|
let licenceLabel = VIDEO_LICENCES[this.licence]
|
||||||
|
|
||||||
// Maybe our pod is not up to date and there are new licences since our version
|
// Maybe our server is not up to date and there are new licences since our version
|
||||||
if (!licenceLabel) licenceLabel = 'Unknown'
|
if (!licenceLabel) licenceLabel = 'Unknown'
|
||||||
|
|
||||||
return licenceLabel
|
return licenceLabel
|
||||||
|
@ -830,7 +830,7 @@ listForApi = function (start: number, count: number, sort: string) {
|
||||||
model: Video['sequelize'].models.Account,
|
model: Video['sequelize'].models.Account,
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Video['sequelize'].models.Pod,
|
model: Video['sequelize'].models.Server,
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -866,7 +866,7 @@ loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Tran
|
||||||
model: Video['sequelize'].models.Account,
|
model: Video['sequelize'].models.Account,
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Video['sequelize'].models.Pod,
|
model: Video['sequelize'].models.Server,
|
||||||
required: true,
|
required: true,
|
||||||
where: {
|
where: {
|
||||||
host: fromHost
|
host: fromHost
|
||||||
|
@ -989,7 +989,7 @@ loadAndPopulateAccount = function (id: number) {
|
||||||
return Video.findById(id, options)
|
return Video.findById(id, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAndPopulateAccountAndPodAndTags = function (id: number) {
|
loadAndPopulateAccountAndServerAndTags = function (id: number) {
|
||||||
const options = {
|
const options = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -997,7 +997,7 @@ loadAndPopulateAccountAndPodAndTags = function (id: number) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Video['sequelize'].models.Account,
|
model: Video['sequelize'].models.Account,
|
||||||
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
|
include: [ { model: Video['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1009,7 +1009,7 @@ loadAndPopulateAccountAndPodAndTags = function (id: number) {
|
||||||
return Video.findById(id, options)
|
return Video.findById(id, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
|
loadByUUIDAndPopulateAccountAndServerAndTags = function (uuid: string) {
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
uuid
|
uuid
|
||||||
|
@ -1020,7 +1020,7 @@ loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Video['sequelize'].models.Account,
|
model: Video['sequelize'].models.Account,
|
||||||
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
|
include: [ { model: Video['sequelize'].models.Server, required: false } ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1032,15 +1032,15 @@ loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
|
||||||
return Video.findOne(options)
|
return Video.findOne(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAndPopulateAccountAndPodAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
|
searchAndPopulateAccountAndServerAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
|
||||||
const podInclude: Sequelize.IncludeOptions = {
|
const serverInclude: Sequelize.IncludeOptions = {
|
||||||
model: Video['sequelize'].models.Pod,
|
model: Video['sequelize'].models.Server,
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
|
|
||||||
const accountInclude: Sequelize.IncludeOptions = {
|
const accountInclude: Sequelize.IncludeOptions = {
|
||||||
model: Video['sequelize'].models.Account,
|
model: Video['sequelize'].models.Account,
|
||||||
include: [ podInclude ]
|
include: [ serverInclude ]
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoChannelInclude: Sequelize.IncludeOptions = {
|
const videoChannelInclude: Sequelize.IncludeOptions = {
|
||||||
|
@ -1071,13 +1071,13 @@ searchAndPopulateAccountAndPodAndTags = function (value: string, field: string,
|
||||||
)`
|
)`
|
||||||
)
|
)
|
||||||
} else if (field === 'host') {
|
} else if (field === 'host') {
|
||||||
// FIXME: Include our pod? (not stored in the database)
|
// FIXME: Include our server? (not stored in the database)
|
||||||
podInclude.where = {
|
serverInclude.where = {
|
||||||
host: {
|
host: {
|
||||||
[Sequelize.Op.iLike]: '%' + value + '%'
|
[Sequelize.Op.iLike]: '%' + value + '%'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
podInclude.required = true
|
serverInclude.required = true
|
||||||
} else if (field === 'account') {
|
} else if (field === 'account') {
|
||||||
accountInclude.where = {
|
accountInclude.where = {
|
||||||
name: {
|
name: {
|
||||||
|
@ -1123,8 +1123,8 @@ function getBaseUrls (video: VideoInstance) {
|
||||||
baseUrlHttp = CONFIG.WEBSERVER.URL
|
baseUrlHttp = CONFIG.WEBSERVER.URL
|
||||||
baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
||||||
} else {
|
} else {
|
||||||
baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Pod.host
|
baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Server.host
|
||||||
baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Pod.host
|
baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Server.host
|
||||||
}
|
}
|
||||||
|
|
||||||
return { baseUrlHttp, baseUrlWs }
|
return { baseUrlHttp, baseUrlWs }
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
export type FollowState = 'pending' | 'accepted'
|
export type FollowState = 'pending' | 'accepted'
|
||||||
|
|
||||||
|
export interface AccountFollow {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
score?: number // Used for followers
|
||||||
|
host: string
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
export * from './accounts'
|
export * from './accounts'
|
||||||
export * from './activitypub'
|
export * from './activitypub'
|
||||||
export * from './pods'
|
|
||||||
export * from './users'
|
export * from './users'
|
||||||
export * from './videos'
|
export * from './videos'
|
||||||
export * from './job.model'
|
export * from './job.model'
|
||||||
export * from './oauth-client-local.model'
|
export * from './oauth-client-local.model'
|
||||||
export * from './result-list.model'
|
export * from './result-list.model'
|
||||||
export * from './request-scheduler.model'
|
|
||||||
export * from './server-config.model'
|
export * from './server-config.model'
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export * from './pod-signature.model'
|
|
||||||
export * from './pod.model'
|
|
||||||
export * from './remote-video'
|
|
|
@ -1,4 +0,0 @@
|
||||||
export interface PodSignature {
|
|
||||||
host: string
|
|
||||||
signature: string
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
export interface Pod {
|
|
||||||
id: number,
|
|
||||||
host: string,
|
|
||||||
score: number,
|
|
||||||
createdAt: Date
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
export * from './remote-qadu-video-request.model'
|
|
||||||
export * from './remote-video-author-create-request.model'
|
|
||||||
export * from './remote-video-author-remove-request.model'
|
|
||||||
export * from './remote-video-event-request.model'
|
|
||||||
export * from './remote-video-request.model'
|
|
||||||
export * from './remote-video-create-request.model'
|
|
||||||
export * from './remote-video-update-request.model'
|
|
||||||
export * from './remote-video-remove-request.model'
|
|
||||||
export * from './remote-video-channel-create-request.model'
|
|
||||||
export * from './remote-video-channel-update-request.model'
|
|
||||||
export * from './remote-video-channel-remove-request.model'
|
|
||||||
export * from './remote-video-report-abuse-request.model'
|
|
|
@ -1,10 +0,0 @@
|
||||||
export interface RemoteQaduVideoData {
|
|
||||||
uuid: string
|
|
||||||
views?: number
|
|
||||||
likes?: number
|
|
||||||
dislikes?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteQaduVideoRequest {
|
|
||||||
data: RemoteQaduVideoData
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoAuthorCreateData {
|
|
||||||
uuid: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoAuthorCreateRequest extends RemoteVideoRequest {
|
|
||||||
type: 'add-author'
|
|
||||||
data: RemoteVideoAuthorCreateData
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoAuthorRemoveData {
|
|
||||||
uuid: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoAuthorRemoveRequest extends RemoteVideoRequest {
|
|
||||||
type: 'remove-author'
|
|
||||||
data: RemoteVideoAuthorRemoveData
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelCreateData {
|
|
||||||
uuid: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
createdAt: Date
|
|
||||||
updatedAt: Date
|
|
||||||
ownerUUID: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelCreateRequest extends RemoteVideoRequest {
|
|
||||||
type: 'add-channel'
|
|
||||||
data: RemoteVideoChannelCreateData
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelRemoveData {
|
|
||||||
uuid: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelRemoveRequest extends RemoteVideoRequest {
|
|
||||||
type: 'remove-channel'
|
|
||||||
data: RemoteVideoChannelRemoveData
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelUpdateData {
|
|
||||||
uuid: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
createdAt: Date
|
|
||||||
updatedAt: Date
|
|
||||||
ownerUUID: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoChannelUpdateRequest extends RemoteVideoRequest {
|
|
||||||
type: 'update-channel'
|
|
||||||
data: RemoteVideoChannelUpdateData
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoCreateData {
|
|
||||||
uuid: string
|
|
||||||
channelUUID: string
|
|
||||||
tags: string[]
|
|
||||||
name: string
|
|
||||||
category: number
|
|
||||||
licence: number
|
|
||||||
language: number
|
|
||||||
nsfw: boolean
|
|
||||||
truncatedDescription: string
|
|
||||||
duration: number
|
|
||||||
createdAt: Date
|
|
||||||
updatedAt: Date
|
|
||||||
views: number
|
|
||||||
likes: number
|
|
||||||
dislikes: number
|
|
||||||
privacy: number
|
|
||||||
thumbnailData: string
|
|
||||||
files: {
|
|
||||||
infoHash: string
|
|
||||||
extname: string
|
|
||||||
resolution: number
|
|
||||||
size: number
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoCreateRequest extends RemoteVideoRequest {
|
|
||||||
type: 'add-video'
|
|
||||||
data: RemoteVideoCreateData
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
export type RemoteVideoEventType = 'views' | 'likes' | 'dislikes'
|
|
||||||
|
|
||||||
export interface RemoteVideoEventData {
|
|
||||||
uuid: string
|
|
||||||
eventType: RemoteVideoEventType
|
|
||||||
count: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoEventRequest {
|
|
||||||
data: RemoteVideoEventData
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoRemoveData {
|
|
||||||
uuid: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoRemoveRequest extends RemoteVideoRequest {
|
|
||||||
type: 'remove-video'
|
|
||||||
data: RemoteVideoRemoveData
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoReportAbuseData {
|
|
||||||
videoUUID: string
|
|
||||||
reporterUsername: string
|
|
||||||
reportReason: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoReportAbuseRequest extends RemoteVideoRequest {
|
|
||||||
type: 'report-abuse'
|
|
||||||
data: RemoteVideoReportAbuseData
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
export interface RemoteVideoRequest {
|
|
||||||
type: RemoteVideoRequestType
|
|
||||||
data: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RemoteVideoRequestType = 'add-video' | 'update-video' | 'remove-video' |
|
|
||||||
'add-channel' | 'update-channel' | 'remove-channel' |
|
|
||||||
'report-abuse' |
|
|
||||||
'add-author' | 'remove-author'
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { RemoteVideoRequest } from './remote-video-request.model'
|
|
||||||
|
|
||||||
export interface RemoteVideoUpdateData {
|
|
||||||
uuid: string
|
|
||||||
tags: string[]
|
|
||||||
name: string
|
|
||||||
category: number
|
|
||||||
licence: number
|
|
||||||
language: number
|
|
||||||
nsfw: boolean
|
|
||||||
truncatedDescription: string
|
|
||||||
duration: number
|
|
||||||
createdAt: Date
|
|
||||||
updatedAt: Date
|
|
||||||
views: number
|
|
||||||
likes: number
|
|
||||||
dislikes: number
|
|
||||||
privacy: number
|
|
||||||
files: {
|
|
||||||
infoHash: string
|
|
||||||
extname: string
|
|
||||||
resolution: number
|
|
||||||
size: number
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RemoteVideoUpdateRequest extends RemoteVideoRequest {
|
|
||||||
type: 'update-video'
|
|
||||||
data: RemoteVideoUpdateData
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
export type RequestEndpoint = 'videos'
|
|
||||||
|
|
||||||
export type RequestVideoQaduType = 'likes' | 'dislikes' | 'views'
|
|
||||||
|
|
||||||
export type RequestVideoEventType = 'likes' | 'dislikes' | 'views'
|
|
||||||
|
|
||||||
export type RequestSchedulerStatsAttributes = {
|
|
||||||
totalRequests: number
|
|
||||||
requestsLimitPods: number
|
|
||||||
requestsLimitPerPod: number
|
|
||||||
remainingMilliSeconds: number
|
|
||||||
milliSecondsInterval: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RequestSchedulerStats {
|
|
||||||
requestScheduler: RequestSchedulerStatsAttributes
|
|
||||||
requestVideoQaduScheduler: RequestSchedulerStatsAttributes
|
|
||||||
requestVideoEventScheduler: RequestSchedulerStatsAttributes
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
export interface VideoAbuse {
|
export interface VideoAbuse {
|
||||||
id: number
|
id: number
|
||||||
reporterPodHost: string
|
reporterServerHost: string
|
||||||
reason: string
|
reason: string
|
||||||
reporterUsername: string
|
reporterUsername: string
|
||||||
videoId: number
|
videoId: number
|
||||||
|
|
|
@ -26,7 +26,7 @@ export interface Video {
|
||||||
duration: number
|
duration: number
|
||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
name: string
|
name: string
|
||||||
podHost: string
|
serverHost: string
|
||||||
tags: string[]
|
tags: string[]
|
||||||
thumbnailPath: string
|
thumbnailPath: string
|
||||||
previewPath: string
|
previewPath: string
|
||||||
|
|
Loading…
Reference in New Issue