Rename Pod -> Server

This commit is contained in:
Chocobozzz 2017-11-15 11:00:25 +01:00
parent 51548b3181
commit 6086242524
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
77 changed files with 456 additions and 1047 deletions

View File

@ -1,11 +1,9 @@
import { Component, OnInit } from '@angular/core'
import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications'
import { SortMeta } from 'primeng/primeng'
import { ConfirmService } from '../../../core'
import { RestTable, RestPagination } from '../../../shared'
import { Pod } from '../../../../../../shared'
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
import { RestPagination, RestTable } from '../../../shared'
import { FollowService } from '../shared'
@Component({
@ -14,7 +12,7 @@ import { FollowService } from '../shared'
styleUrls: [ './followers-list.component.scss' ]
})
export class FollowersListComponent extends RestTable {
followers: Pod[] = []
followers: AccountFollow[] = []
totalRecords = 0
rowsPerPage = 10
sort: SortMeta = { field: 'createdAt', order: 1 }

View File

@ -26,7 +26,7 @@
</div>
<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>
<input type="submit" value="Add following" class="btn btn-default" [disabled]="!isFormValid()">

View File

@ -94,8 +94,6 @@ export class FollowingAddComponent implements OnInit {
this.followService.follow(notEmptyHosts).subscribe(
status => {
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)

View File

@ -1,11 +1,8 @@
import { Component, OnInit } from '@angular/core'
import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications'
import { SortMeta } from 'primeng/primeng'
import { ConfirmService } from '../../../core'
import { RestTable, RestPagination } from '../../../shared'
import { Pod } from '../../../../../../shared'
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
import { RestPagination, RestTable } from '../../../shared'
import { FollowService } from '../shared'
@Component({
@ -13,7 +10,7 @@ import { FollowService } from '../shared'
templateUrl: './following-list.component.html'
})
export class FollowingListComponent extends RestTable {
following: Pod[] = []
following: AccountFollow[] = []
totalRecords = 0
rowsPerPage = 10
sort: SortMeta = { field: 'createdAt', order: 1 }

View File

@ -7,7 +7,7 @@ import 'rxjs/add/operator/map'
import { SortMeta } from 'primeng/primeng'
import { RestExtractor, RestPagination, RestService } from '../../../shared'
import { Pod, ResultList } from '../../../../../../shared'
import { AccountFollow, ResultList } from '../../../../../../shared'
@Injectable()
export class FollowService {
@ -19,7 +19,7 @@ export class FollowService {
private restExtractor: RestExtractor
) {}
getFollowing (pagination: RestPagination, sort: SortMeta): Observable<ResultList<Pod>> {
getFollowing (pagination: RestPagination, sort: SortMeta): Observable<ResultList<AccountFollow>> {
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort)
@ -28,7 +28,7 @@ export class FollowService {
.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()
params = this.restService.addRestGetParams(params, pagination, sort)

View File

@ -9,7 +9,7 @@
>
<p-column field="id" header="ID" [sortable]="true"></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 header="Video" styleClass="action-cell">
<ng-template pTemplate="body" let-videoAbuse="rowData">

View File

@ -2,7 +2,7 @@
<div class="alert alert-danger">
The video load seems to be abnormally long.
<ul>
<li>Maybe the server {{ video.podHost }} is down :(</li>
<li>Maybe the server {{ video.serverHost }} is down :(</li>
<li>
If not, you can report an issue on
<a href="https://github.com/Chocobozzz/PeerTube/issues" title="Report an issue">

View File

@ -27,7 +27,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
uuid: string
isLocal: boolean
name: string
podHost: string
serverHost: string
tags: string[]
thumbnailPath: string
thumbnailUrl: string

View File

@ -19,7 +19,7 @@ export class Video implements VideoServerModel {
uuid: string
isLocal: boolean
name: string
podHost: string
serverHost: string
tags: string[]
thumbnailPath: string
thumbnailUrl: string
@ -32,8 +32,8 @@ export class Video implements VideoServerModel {
dislikes: number
nsfw: boolean
private static createByString (account: string, podHost: string) {
return account + '@' + podHost
private static createByString (account: string, serverHost: string) {
return account + '@' + serverHost
}
private static createDurationString (duration: number) {
@ -67,7 +67,7 @@ export class Video implements VideoServerModel {
this.uuid = hash.uuid
this.isLocal = hash.isLocal
this.name = hash.name
this.podHost = hash.podHost
this.serverHost = hash.serverHost
this.tags = hash.tags
this.thumbnailPath = hash.thumbnailPath
this.thumbnailUrl = absoluteAPIUrl + hash.thumbnailPath
@ -80,7 +80,7 @@ export class Video implements VideoServerModel {
this.dislikes = hash.dislikes
this.nsfw = hash.nsfw
this.by = Video.createByString(hash.account, hash.podHost)
this.by = Video.createByString(hash.account, hash.serverHost)
}
isVideoNSFWForUser (user: User) {

View File

@ -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()
// }

View File

@ -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
// }
// }

View File

@ -4,7 +4,7 @@ import { badRequest } from '../../helpers'
import { oauthClientsRouter } from './oauth-clients'
import { configRouter } from './config'
import { applicationRouter } from './application'
import { applicationRouter } from './server'
import { usersRouter } from './users'
import { videosRouter } from './videos'

View File

@ -9,10 +9,10 @@ import { database as db } from '../../../initializers/database'
import { sendFollow } from '../../../lib/activitypub/send-request'
import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares'
import { authenticate } from '../../../middlewares/oauth'
import { setBodyHostsPort } from '../../../middlewares/pods'
import { setBodyHostsPort } from '../../../middlewares/servers'
import { setFollowingSort } from '../../../middlewares/sort'
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'
const applicationFollowsRouter = express.Router()

View File

@ -70,12 +70,12 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
reporterUsername,
reason: body.reason,
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 => {
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) {
const reportData = {
reporterUsername,
@ -84,7 +84,7 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
}
// await friends.reportAbuseVideoToFriend(reportData, videoInstance, t)
// TODO: send abuse to origin pod
// TODO: send abuse to origin server
}
})

View File

@ -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
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
await sendAddVideo(video, t)
@ -287,7 +287,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
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) {
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) {
const resultList = await db.Video.searchAndPopulateAccountAndPodAndTags(
const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
req.params.value,
req.query.field,
req.query.start,

View File

@ -83,7 +83,7 @@ async function rateVideo (req: express.Request, res: express.Response) {
await videoInstance.increment(incrementQuery, sequelizeOptions)
if (videoInstance.isOwned() === false) {
// TODO: Send a event to original pod
// TODO: Send a event to original server
} else {
// TODO: Send update to followers
}

View File

@ -110,9 +110,9 @@ async function generateWatchHtmlPage (req: express.Request, res: express.Respons
// Let Angular application handle errors
if (validator.isUUID(videoId, 4)) {
videoPromise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(videoId)
videoPromise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(videoId)
} else if (validator.isInt(videoId)) {
videoPromise = db.Video.loadAndPopulateAccountAndPodAndTags(+videoId)
videoPromise = db.Video.loadAndPopulateAccountAndServerAndTags(+videoId)
} else {
return res.sendFile(indexPath)
}

View File

@ -12,7 +12,7 @@ import { asyncMiddleware } from '../middlewares'
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

View File

@ -35,7 +35,7 @@ async function getOrCreateAccount (accountUrl: string) {
// We don't have this account in our database, fetch it on remote
if (!account) {
const res = await fetchRemoteAccountAndCreatePod(accountUrl)
const res = await fetchRemoteAccountAndCreateServer(accountUrl)
if (res === undefined) throw new Error('Cannot fetch remote account.')
// Save our new account in database
@ -46,7 +46,7 @@ async function getOrCreateAccount (accountUrl: string) {
return account
}
async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
const options = {
uri: accountUrl,
method: 'GET',
@ -90,7 +90,7 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
})
const accountHost = url.parse(account.url).host
const podOptions = {
const serverOptions = {
where: {
host: accountHost
},
@ -98,15 +98,15 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
host: accountHost
}
}
const [ pod ] = await db.Pod.findOrCreate(podOptions)
account.set('podId', pod.id)
const [ server ] = await db.Server.findOrCreate(serverOptions)
account.set('serverId', server.id)
return { account, pod }
return { account, server }
}
function fetchRemoteVideoPreview (video: VideoInstance) {
// 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())
return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
@ -163,7 +163,7 @@ function activityPubCollectionPagination (url: string, page: number, result: Res
// ---------------------------------------------------------------------------
export {
fetchRemoteAccountAndCreatePod,
fetchRemoteAccountAndCreateServer,
activityPubContextify,
activityPubCollectionPagination,
getActivityPubUrl,

View File

@ -8,7 +8,7 @@ import { AccountInstance } from '../../models'
import { logger } from '../logger'
import { isUserUsernameValid } from './users'
import { isHostValid } from './pods'
import { isHostValid } from './servers'
function isAccountNameValid (value: string) {
return isUserUsernameValid(value)

View File

@ -1,7 +1,7 @@
export * from './activitypub'
export * from './misc'
export * from './pods'
export * from './pods'
export * from './servers'
export * from './servers'
export * from './users'
export * from './accounts'
export * from './video-channels'

View File

@ -171,9 +171,9 @@ function isVideoFileInfoHashValid (value: string) {
function checkVideoExists (id: string, res: express.Response, callback: () => void) {
let promise: Promise<VideoInstance>
if (validator.isInt(id)) {
promise = db.Video.loadAndPopulateAccountAndPodAndTags(+id)
promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id)
} else { // UUID
promise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(id)
promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id)
}
promise.then(video => {

View File

@ -3,7 +3,7 @@ import * as WebFinger from 'webfinger.js'
import { isTestInstance } from './core-utils'
import { isActivityPubUrlValid } from './custom-validators'
import { WebFingerData } from '../../shared'
import { fetchRemoteAccountAndCreatePod } from './activitypub'
import { fetchRemoteAccountAndCreateServer } from './activitypub'
const webfinger = new WebFinger({
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.')
}
const res = await fetchRemoteAccountAndCreatePod(selfLink.href)
if (res === undefined) throw new Error('Cannot fetch and create pod of remote account ' + selfLink.href)
const res = await fetchRemoteAccountAndCreateServer(selfLink.href)
if (res === undefined) throw new Error('Cannot fetch and create server of remote account ' + selfLink.href)
return res.account
}

View File

@ -6,10 +6,6 @@ import { root, isTestInstance } from '../helpers/core-utils'
import {
VideoRateType,
RequestEndpoint,
RequestVideoEventType,
RequestVideoQaduType,
RemoteVideoRequestType,
JobState,
JobCategory
} 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 = {
BASE: 100,
MAX: 1000
@ -243,7 +239,7 @@ const ACTIVITY_PUB = {
// ---------------------------------------------------------------------------
// Number of points we add/remove from a friend after a successful/bad request
const PODS_SCORE = {
const SERVERS_SCORE = {
PENALTY: -10,
BONUS: 10
}
@ -352,7 +348,7 @@ export {
OAUTH_LIFETIME,
OPENGRAPH_AND_OEMBED_COMMENT,
PAGINATION_COUNT_DEFAULT,
PODS_SCORE,
SERVERS_SCORE,
PREVIEWS_SIZE,
REMOTE_SCHEME,
ACTIVITY_PUB_ACCEPT_HEADER,

View File

@ -18,7 +18,7 @@ import { UserModel } from '../models/account/user-interface'
import { AccountVideoRateModel } from '../models/account/account-video-rate-interface'
import { AccountFollowModel } from '../models/account/account-follow-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 { OAuthClientModel } from './../models/oauth/oauth-client-interface'
import { JobModel } from './../models/job/job-interface'
@ -38,7 +38,7 @@ const database: {
Job?: JobModel,
OAuthClient?: OAuthClientModel,
OAuthToken?: OAuthTokenModel,
Pod?: PodModel,
Server?: ServerModel,
Tag?: TagModel,
AccountVideoRate?: AccountVideoRateModel,
AccountFollow?: AccountFollowModel,

View File

@ -42,7 +42,7 @@ class VideosPreviewCache {
}
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.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName())

View File

@ -8,7 +8,7 @@ import { JobScheduler } from '../job-scheduler'
import { TranscodingJobPayload } from './transcoding-job-scheduler'
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?
if (!video) {
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)
// 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
if (!videoDatabase) return undefined

View File

@ -5,7 +5,7 @@ import { VideoInstance } from '../../../models'
import { sendUpdateVideo } from '../../activitypub/send-request'
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?
if (!video) {
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)
// 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
if (!videoDatabase) return undefined

View File

@ -46,7 +46,7 @@ async function createLocalAccount (name: string, userId: number, applicationId:
followingUrl: url + '/following',
userId,
applicationId,
podId: null // It is our pod
serverId: null // It is our server
})
return accountInstance.save({ transaction: t })

View File

@ -30,14 +30,14 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
return videoChannelCreated
}
async function fetchVideoChannelByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) {
async function fetchVideoChannelByHostAndUUID (serverHost: string, uuid: string, t: Sequelize.Transaction) {
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')
return videoChannel
} 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
}
}

View File

@ -1,7 +1,7 @@
import { NextFunction, Request, Response, RequestHandler } from 'express'
import { ActivityPubSignature } from '../../shared'
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 { 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
if (!account) {
const accountResult = await fetchRemoteAccountAndCreatePod(signatureObject.creator)
const accountResult = await fetchRemoteAccountAndCreateServer(signatureObject.creator)
if (!accountResult) {
return res.sendStatus(403)

View File

@ -3,7 +3,7 @@ export * from './activitypub'
export * from './async'
export * from './oauth'
export * from './pagination'
export * from './pods'
export * from './servers'
export * from './search'
export * from './sort'
export * from './user-right'

View File

@ -4,12 +4,6 @@ import * as express from 'express'
import { SortType } from '../helpers'
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) {
if (!req.query.sort) req.query.sort = '-createdAt'
@ -70,7 +64,6 @@ function setBlacklistSort (req: express.Request, res: express.Response, next: ex
// ---------------------------------------------------------------------------
export {
setPodsSort,
setUsersSort,
setVideoAbusesSort,
setVideoChannelsSort,

View File

@ -2,7 +2,7 @@ export * from './account'
export * from './oembed'
export * from './activitypub'
export * from './pagination'
export * from './pods'
export * from './servers'
export * from './sort'
export * from './users'
export * from './videos'

View File

@ -1,6 +1,6 @@
import * as express from 'express'
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 { CONFIG } from '../../initializers/constants'
import { logger } from '../../helpers/logger'

View File

@ -50,7 +50,7 @@ const videoChannelsUpdateValidator = [
// We need to make additional checks
if (res.locals.videoChannel.isOwned() === false) {
return res.status(403)
.json({ error: 'Cannot update video channel of another pod' })
.json({ error: 'Cannot update video channel of another server' })
.end()
}
@ -113,7 +113,7 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () =>
// Retrieve the user who did the request
if (res.locals.videoChannel.isOwned() === false) {
return res.status(403)
.json({ error: 'Cannot remove video channel of another pod.' })
.json({ error: 'Cannot remove video channel of another server.' })
.end()
}

View File

@ -127,7 +127,7 @@ const videosUpdateValidator = [
// We need to make additional checks
if (video.isOwned() === false) {
return res.status(403)
.json({ error: 'Cannot update video of another pod' })
.json({ error: 'Cannot update video of another server' })
.end()
}
@ -250,7 +250,7 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac
// Retrieve the user who did the request
if (res.locals.video.isOwned() === false) {
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()
}

View File

@ -101,7 +101,7 @@ listFollowingForApi = function (id: number, start: number, count: number, sort:
model: AccountFollow['sequelize'].models.Account,
as: 'AccountFollowing',
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,
required: true,
as: 'AccountFollower',
include: [ AccountFollow['sequelize'].models.Pod ]
include: [ AccountFollow['sequelize'].models.Server ]
},
{
model: AccountFollow['sequelize'].models.Account,

View File

@ -1,8 +1,7 @@
import * as Bluebird from 'bluebird'
import * as Sequelize from 'sequelize'
import { Account as FormattedAccount, ActivityPubActor } from '../../../shared'
import { ResultList } from '../../../shared/models/result-list.model'
import { PodInstance } from '../pod/pod-interface'
import { ServerInstance } from '../server/server-interface'
import { VideoChannelInstance } from '../video/video-channel-interface'
export namespace AccountMethods {
@ -11,7 +10,7 @@ export namespace AccountMethods {
export type Load = (id: number) => Bluebird<AccountInstance>
export type LoadByUUID = (uuid: string) => 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 LoadByNameAndHost = (name: string, host: string) => Bluebird<AccountInstance>
export type ListOwned = () => Bluebird<AccountInstance[]>
@ -27,7 +26,7 @@ export namespace AccountMethods {
export interface AccountClass {
loadApplication: AccountMethods.LoadApplication
loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID
loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
load: AccountMethods.Load
loadByUUID: AccountMethods.LoadByUUID
loadByUrl: AccountMethods.LoadByUrl
@ -51,7 +50,7 @@ export interface AccountAttributes {
uuid?: string
podId?: number
serverId?: number
userId?: number
applicationId?: number
}
@ -69,7 +68,7 @@ export interface AccountInstance extends AccountClass, AccountAttributes, Sequel
createdAt: Date
updatedAt: Date
Pod: PodInstance
Server: ServerInstance
VideoChannels: VideoChannelInstance[]
}

View File

@ -26,7 +26,7 @@ import { sendDeleteAccount } from '../../lib/activitypub/send-request'
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants'
let Account: Sequelize.Model<AccountInstance, AccountAttributes>
let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID
let loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
let load: AccountMethods.Load
let loadApplication: AccountMethods.LoadApplication
let loadByUUID: AccountMethods.LoadByUUID
@ -170,7 +170,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
fields: [ 'name' ]
},
{
fields: [ 'podId' ]
fields: [ 'serverId' ]
},
{
fields: [ 'userId' ],
@ -181,7 +181,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
unique: true
},
{
fields: [ 'name', 'podId', 'applicationId' ],
fields: [ 'name', 'serverId', 'applicationId' ],
unique: true
}
],
@ -191,7 +191,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
const classMethods = [
associate,
loadAccountByPodAndUUID,
loadAccountByServerAndUUID,
loadApplication,
load,
loadByUUID,
@ -217,9 +217,9 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
// ---------------------------------------------------------------------------
function associate (models) {
Account.belongsTo(models.Pod, {
Account.belongsTo(models.Server, {
foreignKey: {
name: 'podId',
name: 'serverId',
allowNull: true
},
onDelete: 'cascade'
@ -278,19 +278,28 @@ function afterDestroy (account: 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 = {
id: this.id,
host,
name: this.name
score,
name: this.name,
createdAt: this.createdAt,
updatedAt: this.updatedAt
}
return json
}
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 = {
type,
@ -317,7 +326,7 @@ toActivityPubObject = function (this: AccountInstance) {
}
isOwned = function (this: AccountInstance) {
return this.podId === null
return this.serverId === null
}
getFollowerSharedInboxUrls = function (this: AccountInstance) {
@ -356,7 +365,7 @@ getPublicKeyUrl = function (this: AccountInstance) {
listOwned = function () {
const query: Sequelize.FindOptions<AccountAttributes> = {
where: {
podId: null
serverId: null
}
}
@ -417,7 +426,7 @@ loadByNameAndHost = function (name: string, host: string) {
},
include: [
{
model: Account['sequelize'].models.Pod,
model: Account['sequelize'].models.Server,
required: true,
where: {
host
@ -440,10 +449,10 @@ loadByUrl = function (url: string, transaction?: Sequelize.Transaction) {
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> = {
where: {
podId,
serverId,
uuid
},
transaction

View File

@ -1,6 +1,6 @@
export * from './application'
export * from './job'
export * from './oauth'
export * from './pod'
export * from './server'
export * from './account'
export * from './video'

View File

@ -1 +0,0 @@
export * from './pod-interface'

View File

@ -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> {}

View File

@ -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)
}
}

View File

@ -0,0 +1 @@
export * from './server-interface'

View File

@ -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> {}

View File

@ -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)
}
}

View File

@ -1,7 +1,7 @@
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
import { PodInstance } from '../pod/pod-interface'
import { ServerInstance } from '../server/server-interface'
import { ResultList } from '../../../shared'
// Don't use barrel, import just what we need
@ -28,7 +28,7 @@ export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttribute
createdAt: Date
updatedAt: Date
Pod: PodInstance
Server: ServerInstance
toFormattedJSON: VideoAbuseMethods.ToFormattedJSON
}

View File

@ -45,7 +45,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
fields: [ 'videoId' ]
},
{
fields: [ 'reporterPodId' ]
fields: [ 'reporterServerId' ]
}
]
}
@ -67,18 +67,18 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
// ------------------------------ METHODS ------------------------------
toFormattedJSON = function (this: VideoAbuseInstance) {
let reporterPodHost
let reporterServerHost
if (this.Pod) {
reporterPodHost = this.Pod.host
if (this.Server) {
reporterServerHost = this.Server.host
} else {
// It means it's our video
reporterPodHost = CONFIG.WEBSERVER.HOST
reporterServerHost = CONFIG.WEBSERVER.HOST
}
const json = {
id: this.id,
reporterPodHost,
reporterServerHost,
reason: this.reason,
reporterUsername: this.reporterUsername,
videoId: this.videoId,
@ -91,9 +91,9 @@ toFormattedJSON = function (this: VideoAbuseInstance) {
// ------------------------------ STATICS ------------------------------
function associate (models) {
VideoAbuse.belongsTo(models.Pod, {
VideoAbuse.belongsTo(models.Server, {
foreignKey: {
name: 'reporterPodId',
name: 'reporterServerId',
allowNull: true
},
onDelete: 'CASCADE'
@ -115,7 +115,7 @@ listForApi = function (start: number, count: number, sort: string) {
order: [ getSort(sort) ],
include: [
{
model: VideoAbuse['sequelize'].models.Pod,
model: VideoAbuse['sequelize'].models.Server,
required: false
}
]

View File

@ -22,7 +22,7 @@ export namespace VideoChannelMethods {
export type LoadAndPopulateAccount = (id: number) => Promise<VideoChannelInstance>
export type LoadByUUIDAndPopulateAccount = (uuid: string) => 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 LoadByUrl = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
export type LoadByUUIDOrUrl = (uuid: string, url: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>

View File

@ -218,7 +218,7 @@ listForApi = function (start: number, count: number, sort: string) {
{
model: VideoChannel['sequelize'].models.Account,
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
},
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,
include: [
{
model: VideoChannel['sequelize'].models.Pod,
model: VideoChannel['sequelize'].models.Server,
required: true,
where: {
host: fromHost
@ -322,7 +322,7 @@ loadByIdAndAccount = function (id: number, accountId: number) {
include: [
{
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: [
{
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: [
{
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: [
{
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
]

View File

@ -46,7 +46,7 @@ export namespace VideoMethods {
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 SearchAndPopulateAccountAndPodAndTags = (
export type SearchAndPopulateAccountAndServerAndTags = (
value: string,
field: string,
start: number,
@ -60,8 +60,8 @@ export namespace VideoMethods {
export type LoadLocalVideoByUUID = (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 LoadAndPopulateAccountAndPodAndTags = (id: number) => Bluebird<VideoInstance>
export type LoadByUUIDAndPopulateAccountAndPodAndTags = (uuid: string) => Bluebird<VideoInstance>
export type LoadAndPopulateAccountAndServerAndTags = (id: number) => Bluebird<VideoInstance>
export type LoadByUUIDAndPopulateAccountAndServerAndTags = (uuid: string) => Bluebird<VideoInstance>
export type LoadByUUIDOrURL = (uuid: string, url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
export type RemoveThumbnail = (this: VideoInstance) => Promise<void>
@ -79,14 +79,14 @@ export interface VideoClass {
listOwnedByAccount: VideoMethods.ListOwnedByAccount
load: VideoMethods.Load
loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags
loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
loadByUUID: VideoMethods.LoadByUUID
loadByUrl: VideoMethods.LoadByUrl
loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags
searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags
loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
}
export interface VideoAttributes {

View File

@ -88,9 +88,9 @@ let loadByUUID: VideoMethods.LoadByUUID
let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
let loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
let loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags
let loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags
let searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags
let loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
let loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
let searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
let removeThumbnail: VideoMethods.RemoveThumbnail
let removePreview: VideoMethods.RemovePreview
let removeFile: VideoMethods.RemoveFile
@ -275,13 +275,13 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
listOwnedByAccount,
load,
loadAndPopulateAccount,
loadAndPopulateAccountAndPodAndTags,
loadAndPopulateAccountAndServerAndTags,
loadByHostAndUUID,
loadByUUIDOrURL,
loadByUUID,
loadLocalVideoByUUID,
loadByUUIDAndPopulateAccountAndPodAndTags,
searchAndPopulateAccountAndPodAndTags
loadByUUIDAndPopulateAccountAndServerAndTags,
searchAndPopulateAccountAndServerAndTags
]
const instanceMethods = [
createPreview,
@ -477,13 +477,13 @@ getPreviewPath = function (this: VideoInstance) {
}
toFormattedJSON = function (this: VideoInstance) {
let podHost
let serverHost
if (this.VideoChannel.Account.Pod) {
podHost = this.VideoChannel.Account.Pod.host
if (this.VideoChannel.Account.Server) {
serverHost = this.VideoChannel.Account.Server.host
} else {
// It means it's our video
podHost = CONFIG.WEBSERVER.HOST
serverHost = CONFIG.WEBSERVER.HOST
}
const json = {
@ -498,7 +498,7 @@ toFormattedJSON = function (this: VideoInstance) {
languageLabel: this.getLanguageLabel(),
nsfw: this.nsfw,
description: this.getTruncatedDescription(),
podHost,
serverHost,
isLocal: this.isOwned(),
account: this.VideoChannel.Account.name,
duration: this.duration,
@ -519,7 +519,7 @@ toFormattedJSON = function (this: VideoInstance) {
toFormattedDetailsJSON = function (this: VideoInstance) {
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]
if (!privacyLabel) privacyLabel = 'Unknown'
@ -721,7 +721,7 @@ getDescriptionPath = function (this: VideoInstance) {
getCategoryLabel = function (this: VideoInstance) {
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'
return categoryLabel
@ -730,7 +730,7 @@ getCategoryLabel = function (this: VideoInstance) {
getLicenceLabel = function (this: VideoInstance) {
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'
return licenceLabel
@ -830,7 +830,7 @@ listForApi = function (start: number, count: number, sort: string) {
model: Video['sequelize'].models.Account,
include: [
{
model: Video['sequelize'].models.Pod,
model: Video['sequelize'].models.Server,
required: false
}
]
@ -866,7 +866,7 @@ loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Tran
model: Video['sequelize'].models.Account,
include: [
{
model: Video['sequelize'].models.Pod,
model: Video['sequelize'].models.Server,
required: true,
where: {
host: fromHost
@ -989,7 +989,7 @@ loadAndPopulateAccount = function (id: number) {
return Video.findById(id, options)
}
loadAndPopulateAccountAndPodAndTags = function (id: number) {
loadAndPopulateAccountAndServerAndTags = function (id: number) {
const options = {
include: [
{
@ -997,7 +997,7 @@ loadAndPopulateAccountAndPodAndTags = function (id: number) {
include: [
{
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)
}
loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
loadByUUIDAndPopulateAccountAndServerAndTags = function (uuid: string) {
const options = {
where: {
uuid
@ -1020,7 +1020,7 @@ loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
include: [
{
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)
}
searchAndPopulateAccountAndPodAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
const podInclude: Sequelize.IncludeOptions = {
model: Video['sequelize'].models.Pod,
searchAndPopulateAccountAndServerAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
const serverInclude: Sequelize.IncludeOptions = {
model: Video['sequelize'].models.Server,
required: false
}
const accountInclude: Sequelize.IncludeOptions = {
model: Video['sequelize'].models.Account,
include: [ podInclude ]
include: [ serverInclude ]
}
const videoChannelInclude: Sequelize.IncludeOptions = {
@ -1071,13 +1071,13 @@ searchAndPopulateAccountAndPodAndTags = function (value: string, field: string,
)`
)
} else if (field === 'host') {
// FIXME: Include our pod? (not stored in the database)
podInclude.where = {
// FIXME: Include our server? (not stored in the database)
serverInclude.where = {
host: {
[Sequelize.Op.iLike]: '%' + value + '%'
}
}
podInclude.required = true
serverInclude.required = true
} else if (field === 'account') {
accountInclude.where = {
name: {
@ -1123,8 +1123,8 @@ function getBaseUrls (video: VideoInstance) {
baseUrlHttp = CONFIG.WEBSERVER.URL
baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
} else {
baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Pod.host
baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Pod.host
baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Server.host
baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Server.host
}
return { baseUrlHttp, baseUrlWs }

View File

@ -1 +1,8 @@
export type FollowState = 'pending' | 'accepted'
export interface AccountFollow {
id: number
name: string
score?: number // Used for followers
host: string
}

View File

@ -1,10 +1,8 @@
export * from './accounts'
export * from './activitypub'
export * from './pods'
export * from './users'
export * from './videos'
export * from './job.model'
export * from './oauth-client-local.model'
export * from './result-list.model'
export * from './request-scheduler.model'
export * from './server-config.model'

View File

@ -1,3 +0,0 @@
export * from './pod-signature.model'
export * from './pod.model'
export * from './remote-video'

View File

@ -1,4 +0,0 @@
export interface PodSignature {
host: string
signature: string
}

View File

@ -1,6 +0,0 @@
export interface Pod {
id: number,
host: string,
score: number,
createdAt: Date
}

View File

@ -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'

View File

@ -1,10 +0,0 @@
export interface RemoteQaduVideoData {
uuid: string
views?: number
likes?: number
dislikes?: number
}
export interface RemoteQaduVideoRequest {
data: RemoteQaduVideoData
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -1,11 +0,0 @@
export type RemoteVideoEventType = 'views' | 'likes' | 'dislikes'
export interface RemoteVideoEventData {
uuid: string
eventType: RemoteVideoEventType
count: number
}
export interface RemoteVideoEventRequest {
data: RemoteVideoEventData
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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'

View File

@ -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
}

View File

@ -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
}

View File

@ -1,6 +1,6 @@
export interface VideoAbuse {
id: number
reporterPodHost: string
reporterServerHost: string
reason: string
reporterUsername: string
videoId: number

View File

@ -26,7 +26,7 @@ export interface Video {
duration: number
isLocal: boolean
name: string
podHost: string
serverHost: string
tags: string[]
thumbnailPath: string
previewPath: string