Better typescript typing for a better world

This commit is contained in:
Chocobozzz 2017-07-10 19:43:21 +02:00
parent 7a214f746b
commit 4771e0008d
59 changed files with 400 additions and 166 deletions

View File

@ -15,7 +15,7 @@ import { FriendService } from '../shared'
}) })
export class FriendAddComponent implements OnInit { export class FriendAddComponent implements OnInit {
form: FormGroup form: FormGroup
hosts = [ ] hosts: string[] = [ ]
error: string = null error: string = null
constructor ( constructor (

View File

@ -3,6 +3,7 @@ import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map' import 'rxjs/add/operator/map'
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared' import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared'
import { UserCreate } from '../../../../../../shared'
@Injectable() @Injectable()
export class UserService { export class UserService {
@ -13,14 +14,8 @@ export class UserService {
private restExtractor: RestExtractor private restExtractor: RestExtractor
) {} ) {}
addUser (username: string, password: string, email: string) { addUser (userCreate: UserCreate) {
const body = { return this.authHttp.post(UserService.BASE_USERS_URL, userCreate)
username,
email,
password
}
return this.authHttp.post(UserService.BASE_USERS_URL, body)
.map(this.restExtractor.extractDataBool) .map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError) .catch(this.restExtractor.handleError)
} }

View File

@ -11,6 +11,7 @@ import {
USER_EMAIL, USER_EMAIL,
USER_PASSWORD USER_PASSWORD
} from '../../../shared' } from '../../../shared'
import { UserCreate } from '../../../../../../shared'
@Component({ @Component({
selector: 'my-user-add', selector: 'my-user-add',
@ -57,11 +58,11 @@ export class UserAddComponent extends FormReactive implements OnInit {
addUser () { addUser () {
this.error = null this.error = null
const { username, password, email } = this.form.value const userCreate: UserCreate = this.form.value
this.userService.addUser(username, password, email).subscribe( this.userService.addUser(userCreate).subscribe(
() => { () => {
this.notificationsService.success('Success', `User ${username} created.`) this.notificationsService.success('Success', `User ${userCreate.username} created.`)
this.router.navigate([ '/admin/users/list' ]) this.router.navigate([ '/admin/users/list' ])
}, },

View File

@ -11,6 +11,7 @@ import {
UserService, UserService,
USER_PASSWORD USER_PASSWORD
} from '../../shared' } from '../../shared'
import { UserUpdate } from '../../../../../shared'
@Component({ @Component({
selector: 'my-account-details', selector: 'my-account-details',
@ -50,7 +51,7 @@ export class AccountDetailsComponent extends FormReactive implements OnInit {
updateDetails () { updateDetails () {
const displayNSFW = this.form.value['displayNSFW'] const displayNSFW = this.form.value['displayNSFW']
const details = { const details: UserUpdate = {
displayNSFW displayNSFW
} }

View File

@ -1,5 +1,5 @@
// Do not use the barrel (dependency loop) // Do not use the barrel (dependency loop)
import { UserRole } from '../../../../../shared/models/user.model' import { UserRole } from '../../../../../shared/models/users/user-role.type'
import { User } from '../../shared/users/user.model' import { User } from '../../shared/users/user.model'
export type TokenOptions = { export type TokenOptions = {

View File

@ -6,6 +6,7 @@ import 'rxjs/add/operator/map'
import { AuthService } from '../../core' import { AuthService } from '../../core'
import { AuthHttp } from '../auth' import { AuthHttp } from '../auth'
import { RestExtractor } from '../rest' import { RestExtractor } from '../rest'
import { UserCreate, UserUpdate } from '../../../../../shared'
@Injectable() @Injectable()
export class UserService { export class UserService {
@ -27,7 +28,7 @@ export class UserService {
changePassword (newPassword: string) { changePassword (newPassword: string) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id const url = UserService.BASE_USERS_URL + this.authService.getUser().id
const body = { const body: UserUpdate = {
password: newPassword password: newPassword
} }
@ -36,7 +37,7 @@ export class UserService {
.catch((res) => this.restExtractor.handleError(res)) .catch((res) => this.restExtractor.handleError(res))
} }
updateDetails (details: { displayNSFW: boolean }) { updateDetails (details: UserUpdate) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id const url = UserService.BASE_USERS_URL + this.authService.getUser().id
return this.authHttp.put(url, details) return this.authHttp.put(url, details)
@ -44,14 +45,8 @@ export class UserService {
.catch((res) => this.restExtractor.handleError(res)) .catch((res) => this.restExtractor.handleError(res))
} }
signup (username: string, password: string, email: string) { signup (userCreate: UserCreate) {
const body = { return this.http.post(UserService.BASE_USERS_URL + 'register', userCreate)
username,
email,
password
}
return this.http.post(UserService.BASE_USERS_URL + 'register', body)
.map(this.restExtractor.extractDataBool) .map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError) .catch(this.restExtractor.handleError)
} }

View File

@ -12,6 +12,7 @@ import {
USER_EMAIL, USER_EMAIL,
USER_PASSWORD USER_PASSWORD
} from '../shared' } from '../shared'
import { UserCreate } from '../../../../shared'
@Component({ @Component({
selector: 'my-signup', selector: 'my-signup',
@ -58,11 +59,11 @@ export class SignupComponent extends FormReactive implements OnInit {
signup () { signup () {
this.error = null this.error = null
const { username, password, email } = this.form.value const userCreate: UserCreate = this.form.value
this.userService.signup(username, password, email).subscribe( this.userService.signup(userCreate).subscribe(
() => { () => {
this.notificationsService.success('Success', `Registration for ${username} complete.`) this.notificationsService.success('Success', `Registration for ${userCreate.username} complete.`)
this.router.navigate([ '/videos/list' ]) this.router.navigate([ '/videos/list' ])
}, },

View File

@ -16,7 +16,13 @@ import {
UserService UserService
} from '../../shared' } from '../../shared'
import { Video } from './video.model' import { Video } from './video.model'
import { UserVideoRate, VideoRateType } from '../../../../../shared' import {
UserVideoRate,
VideoRateType,
VideoUpdate,
VideoAbuseCreate,
UserVideoRateUpdate
} from '../../../../../shared'
@Injectable() @Injectable()
export class VideoService { export class VideoService {
@ -35,42 +41,15 @@ export class VideoService {
) {} ) {}
loadVideoCategories () { loadVideoCategories () {
return this.http.get(VideoService.BASE_VIDEO_URL + 'categories') return this.loadVideoAttributeEnum('categories', this.videoCategories)
.map(this.restExtractor.extractDataGet)
.subscribe(data => {
Object.keys(data).forEach(categoryKey => {
this.videoCategories.push({
id: parseInt(categoryKey, 10),
label: data[categoryKey]
})
})
})
} }
loadVideoLicences () { loadVideoLicences () {
return this.http.get(VideoService.BASE_VIDEO_URL + 'licences') return this.loadVideoAttributeEnum('licences', this.videoLicences)
.map(this.restExtractor.extractDataGet)
.subscribe(data => {
Object.keys(data).forEach(licenceKey => {
this.videoLicences.push({
id: parseInt(licenceKey, 10),
label: data[licenceKey]
})
})
})
} }
loadVideoLanguages () { loadVideoLanguages () {
return this.http.get(VideoService.BASE_VIDEO_URL + 'languages') return this.loadVideoAttributeEnum('languages', this.videoLanguages)
.map(this.restExtractor.extractDataGet)
.subscribe(data => {
Object.keys(data).forEach(languageKey => {
this.videoLanguages.push({
id: parseInt(languageKey, 10),
label: data[languageKey]
})
})
})
} }
getVideo (id: string): Observable<Video> { getVideo (id: string): Observable<Video> {
@ -83,13 +62,14 @@ export class VideoService {
updateVideo (video: Video) { updateVideo (video: Video) {
const language = video.language ? video.language : null const language = video.language ? video.language : null
const body = { const body: VideoUpdate = {
name: video.name, name: video.name,
category: video.category, category: video.category,
licence: video.licence, licence: video.licence,
language, language,
description: video.description, description: video.description,
tags: video.tags tags: video.tags,
nsfw: video.nsfw
} }
const headers = new Headers({ 'Content-Type': 'application/json' }) const headers = new Headers({ 'Content-Type': 'application/json' })
@ -128,7 +108,7 @@ export class VideoService {
reportVideo (id: string, reason: string) { reportVideo (id: string, reason: string) {
const url = VideoService.BASE_VIDEO_URL + id + '/abuse' const url = VideoService.BASE_VIDEO_URL + id + '/abuse'
const body = { const body: VideoAbuseCreate = {
reason reason
} }
@ -161,7 +141,7 @@ export class VideoService {
private setVideoRate (id: string, rateType: VideoRateType) { private setVideoRate (id: string, rateType: VideoRateType) {
const url = VideoService.BASE_VIDEO_URL + id + '/rate' const url = VideoService.BASE_VIDEO_URL + id + '/rate'
const body = { const body: UserVideoRateUpdate = {
rating: rateType rating: rateType
} }
@ -180,4 +160,17 @@ export class VideoService {
return { videos, totalVideos } return { videos, totalVideos }
} }
private loadVideoAttributeEnum (attributeName: 'categories' | 'licences' | 'languages', hashToPopulate: { id: number, label: string }[]) {
return this.http.get(VideoService.BASE_VIDEO_URL + attributeName)
.map(this.restExtractor.extractDataGet)
.subscribe(data => {
Object.keys(data).forEach(dataKey => {
hashToPopulate.push({
id: parseInt(dataKey, 10),
label: data[dataKey]
})
})
})
}
} }

View File

@ -16,6 +16,7 @@ import {
VIDEO_TAGS VIDEO_TAGS
} from '../../shared' } from '../../shared'
import { VideoService } from '../shared' import { VideoService } from '../shared'
import { VideoCreate } from '../../../../../shared'
@Component({ @Component({
selector: 'my-videos-add', selector: 'my-videos-add',
@ -98,23 +99,25 @@ export class VideoAddComponent extends FormReactive implements OnInit {
removeAfterUpload: true removeAfterUpload: true
}) })
this.uploader.onBuildItemForm = (item, form) => { this.uploader.onBuildItemForm = (item, form: FormData) => {
const name = this.form.value['name'] const formValue: VideoCreate = this.form.value
const nsfw = this.form.value['nsfw']
const category = this.form.value['category'] const name = formValue.name
const licence = this.form.value['licence'] const nsfw = formValue.nsfw
const language = this.form.value['language'] const category = formValue.category
const description = this.form.value['description'] const licence = formValue.licence
const tags = this.form.value['tags'] const language = formValue.language
const description = formValue.description
const tags = formValue.tags
form.append('name', name) form.append('name', name)
form.append('category', category) form.append('category', '' + category)
form.append('nsfw', nsfw) form.append('nsfw', '' + nsfw)
form.append('licence', licence) form.append('licence', '' + licence)
// Language is optional // Language is optional
if (language) { if (language) {
form.append('language', language) form.append('language', '' + language)
} }
form.append('description', description) form.append('description', description)

View File

@ -2,4 +2,4 @@
cd client || exit -1 cd client || exit -1
npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot --open

View File

@ -1,5 +1,5 @@
#!/usr/bin/env sh #!/usr/bin/env sh
NODE_ENV=test concurrently \ NODE_ENV=test concurrently -k \
"npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \ "npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \
"npm run tsc -- --sourceMap -w" "npm run tsc -- --sourceMap -w"

View File

@ -2,6 +2,7 @@ import * as express from 'express'
import { database as db } from '../../../initializers/database' import { database as db } from '../../../initializers/database'
import { checkSignature, signatureValidator } from '../../../middlewares' import { checkSignature, signatureValidator } from '../../../middlewares'
import { PodSignature } from '../../../../shared'
const remotePodsRouter = express.Router() const remotePodsRouter = express.Router()
@ -21,12 +22,11 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function removePods (req: express.Request, res: express.Response, next: express.NextFunction) { function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
const host = req.body.signature.host const signature: PodSignature = req.body.signature
const host = signature.host
db.Pod.loadByHost(host) db.Pod.loadByHost(host)
.then(pod => { .then(pod => pod.destroy())
return pod.destroy()
})
.then(() => res.type('json').status(204).end()) .then(() => res.type('json').status(204).end())
.catch(err => next(err)) .catch(err => next(err))
} }

View File

@ -18,6 +18,17 @@ import {
import { logger, retryTransactionWrapper } from '../../../helpers' import { logger, retryTransactionWrapper } from '../../../helpers'
import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib' import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
import { PodInstance, VideoInstance } from '../../../models' import { PodInstance, VideoInstance } from '../../../models'
import {
RemoteVideoRequest,
RemoteVideoCreateData,
RemoteVideoUpdateData,
RemoteVideoRemoveData,
RemoteVideoReportAbuseData,
RemoteQaduVideoRequest,
RemoteQaduVideoData,
RemoteVideoEventRequest,
RemoteVideoEventData
} from '../../../../shared'
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
@ -60,11 +71,11 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) { function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const requests = req.body.data const requests: RemoteVideoRequest[] = req.body.data
const fromPod = res.locals.secure.pod const fromPod = res.locals.secure.pod
// We need to process in the same order to keep consistency // We need to process in the same order to keep consistency
Promise.each(requests, (request: any) => { Promise.each(requests, request => {
const data = request.data const data = request.data
// Get the function we need to call in order to process the request // Get the function we need to call in order to process the request
@ -83,10 +94,10 @@ function remoteVideos (req: express.Request, res: express.Response, next: expres
} }
function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) { function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
const requests = req.body.data const requests: RemoteQaduVideoRequest[] = req.body.data
const fromPod = res.locals.secure.pod const fromPod = res.locals.secure.pod
Promise.each(requests, (request: any) => { Promise.each(requests, request => {
const videoData = request.data const videoData = request.data
return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod) return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod)
@ -97,10 +108,10 @@ function remoteVideosQadu (req: express.Request, res: express.Response, next: ex
} }
function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) { function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
const requests = req.body.data const requests: RemoteVideoEventRequest[] = req.body.data
const fromPod = res.locals.secure.pod const fromPod = res.locals.secure.pod
Promise.each(requests, (request: any) => { Promise.each(requests, request => {
const eventData = request.data const eventData = request.data
return processVideosEventsRetryWrapper(eventData, fromPod) return processVideosEventsRetryWrapper(eventData, fromPod)
@ -110,7 +121,7 @@ function remoteVideosEvents (req: express.Request, res: express.Response, next:
return res.type('json').status(204).end() return res.type('json').status(204).end()
} }
function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance) { function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromPod: PodInstance) {
const options = { const options = {
arguments: [ eventData, fromPod ], arguments: [ eventData, fromPod ],
errorMessage: 'Cannot process videos events with many retries.' errorMessage: 'Cannot process videos events with many retries.'
@ -119,7 +130,7 @@ function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance)
return retryTransactionWrapper(processVideosEvents, options) return retryTransactionWrapper(processVideosEvents, options)
} }
function processVideosEvents (eventData: any, fromPod: PodInstance) { function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
return fetchOwnedVideo(eventData.remoteId) return fetchOwnedVideo(eventData.remoteId)
@ -172,7 +183,7 @@ function processVideosEvents (eventData: any, fromPod: PodInstance) {
}) })
} }
function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInstance) { function quickAndDirtyUpdateVideoRetryWrapper (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
const options = { const options = {
arguments: [ videoData, fromPod ], arguments: [ videoData, fromPod ],
errorMessage: 'Cannot update quick and dirty the remote video with many retries.' errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
@ -181,7 +192,7 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInsta
return retryTransactionWrapper(quickAndDirtyUpdateVideo, options) return retryTransactionWrapper(quickAndDirtyUpdateVideo, options)
} }
function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance) { function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
let videoName let videoName
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
@ -211,7 +222,7 @@ function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance) {
} }
// Handle retries on fail // Handle retries on fail
function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstance) { function addRemoteVideoRetryWrapper (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
const options = { const options = {
arguments: [ videoToCreateData, fromPod ], arguments: [ videoToCreateData, fromPod ],
errorMessage: 'Cannot insert the remote video with many retries.' errorMessage: 'Cannot insert the remote video with many retries.'
@ -220,7 +231,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstanc
return retryTransactionWrapper(addRemoteVideo, options) return retryTransactionWrapper(addRemoteVideo, options)
} }
function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance) { function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
logger.debug('Adding remote video "%s".', videoToCreateData.remoteId) logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
@ -293,7 +304,7 @@ function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance) {
} }
// Handle retries on fail // Handle retries on fail
function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: PodInstance) { function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
const options = { const options = {
arguments: [ videoAttributesToUpdate, fromPod ], arguments: [ videoAttributesToUpdate, fromPod ],
errorMessage: 'Cannot update the remote video with many retries' errorMessage: 'Cannot update the remote video with many retries'
@ -302,7 +313,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: P
return retryTransactionWrapper(updateRemoteVideo, options) return retryTransactionWrapper(updateRemoteVideo, options)
} }
function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance) { function updateRemoteVideo (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId) logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
@ -346,7 +357,7 @@ function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance)
}) })
} }
function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance) { function removeRemoteVideo (videoToRemoveData: RemoteVideoRemoveData, fromPod: PodInstance) {
// We need the instance because we have to remove some other stuffs (thumbnail etc) // We need the instance because we have to remove some other stuffs (thumbnail etc)
return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId) return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId)
.then(video => { .then(video => {
@ -358,7 +369,7 @@ function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance) {
}) })
} }
function reportAbuseRemoteVideo (reportData: any, fromPod: PodInstance) { function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
return fetchOwnedVideo(reportData.videoRemoteId) return fetchOwnedVideo(reportData.videoRemoteId)
.then(video => { .then(video => {
logger.debug('Reporting remote abuse for video %s.', video.id) logger.debug('Reporting remote abuse for video %s.', video.id)

View File

@ -17,7 +17,7 @@ import {
setUsersSort, setUsersSort,
token token
} from '../../middlewares' } from '../../middlewares'
import { UserVideoRate as FormatedUserVideoRate } from '../../../shared' import { UserVideoRate as FormatedUserVideoRate, UserCreate, UserUpdate } from '../../../shared'
const usersRouter = express.Router() const usersRouter = express.Router()
@ -78,10 +78,12 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function createUser (req: express.Request, res: express.Response, next: express.NextFunction) { function createUser (req: express.Request, res: express.Response, next: express.NextFunction) {
const body: UserCreate = req.body
const user = db.User.build({ const user = db.User.build({
username: req.body.username, username: body.username,
password: req.body.password, password: body.password,
email: req.body.email, email: body.email,
displayNSFW: false, displayNSFW: false,
role: USER_ROLES.USER role: USER_ROLES.USER
}) })
@ -132,10 +134,12 @@ function removeUser (req: express.Request, res: express.Response, next: express.
} }
function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) { function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
const body: UserUpdate = req.body
db.User.loadByUsername(res.locals.oauth.token.user.username) db.User.loadByUsername(res.locals.oauth.token.user.username)
.then(user => { .then(user => {
if (req.body.password) user.password = req.body.password if (body.password) user.password = body.password
if (req.body.displayNSFW !== undefined) user.displayNSFW = req.body.displayNSFW if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW
return user.save() return user.save()
}) })

View File

@ -17,6 +17,7 @@ import {
setPagination setPagination
} from '../../../middlewares' } from '../../../middlewares'
import { VideoInstance } from '../../../models' import { VideoInstance } from '../../../models'
import { VideoAbuseCreate } from '../../../../shared'
const abuseVideoRouter = express.Router() const abuseVideoRouter = express.Router()
@ -63,10 +64,11 @@ function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Respon
function reportVideoAbuse (req: express.Request, res: express.Response) { function reportVideoAbuse (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video const videoInstance = res.locals.video
const reporterUsername = res.locals.oauth.token.User.username const reporterUsername = res.locals.oauth.token.User.username
const body: VideoAbuseCreate = req.body
const abuse = { const abuse = {
reporterUsername, reporterUsername,
reason: req.body.reason, reason: body.reason,
videoId: videoInstance.id, videoId: videoInstance.id,
reporterPodId: null // This is our pod that reported this abuse reporterPodId: null // This is our pod that reported this abuse
} }

View File

@ -39,6 +39,7 @@ import {
renamePromise renamePromise
} from '../../../helpers' } from '../../../helpers'
import { TagInstance } from '../../../models' import { TagInstance } from '../../../models'
import { VideoCreate, VideoUpdate } from '../../../../shared'
import { abuseVideoRouter } from './abuse' import { abuseVideoRouter } from './abuse'
import { blacklistRouter } from './blacklist' import { blacklistRouter } from './blacklist'
@ -155,7 +156,7 @@ function addVideoRetryWrapper (req: express.Request, res: express.Response, next
} }
function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File) { function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File) {
const videoInfos = req.body const videoInfos: VideoCreate = req.body
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
const user = res.locals.oauth.token.User const user = res.locals.oauth.token.User
@ -257,7 +258,7 @@ function updateVideoRetryWrapper (req: express.Request, res: express.Response, n
function updateVideo (req: express.Request, res: express.Response) { function updateVideo (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video const videoInstance = res.locals.video
const videoFieldsSave = videoInstance.toJSON() const videoFieldsSave = videoInstance.toJSON()
const videoInfosToUpdate = req.body const videoInfosToUpdate: VideoUpdate = req.body
return db.sequelize.transaction(t => { return db.sequelize.transaction(t => {
let tagsPromise: Promise<TagInstance[]> let tagsPromise: Promise<TagInstance[]>

View File

@ -1,4 +1,5 @@
import * as express from 'express' import * as express from 'express'
import * as Promise from 'bluebird'
import { database as db } from '../../../initializers/database' import { database as db } from '../../../initializers/database'
import { import {
@ -18,6 +19,7 @@ import {
authenticate, authenticate,
videoRateValidator videoRateValidator
} from '../../../middlewares' } from '../../../middlewares'
import { UserVideoRateUpdate, VideoRateType } from '../../../../shared'
const rateVideoRouter = express.Router() const rateVideoRouter = express.Router()
@ -47,7 +49,8 @@ function rateVideoRetryWrapper (req: express.Request, res: express.Response, nex
} }
function rateVideo (req: express.Request, res: express.Response) { function rateVideo (req: express.Request, res: express.Response) {
const rateType = req.body.rating const body: UserVideoRateUpdate = req.body
const rateType = body.rating
const videoInstance = res.locals.video const videoInstance = res.locals.video
const userInstance = res.locals.oauth.token.User const userInstance = res.locals.oauth.token.User
@ -62,24 +65,34 @@ function rateVideo (req: express.Request, res: express.Response) {
if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
let promise: Promise<any>
// There was a previous rate, update it // There was a previous rate, update it
if (previousRate) { if (previousRate) {
// We will remove the previous rate, so we will need to remove it from the video attribute // We will remove the previous rate, so we will need to remove it from the video attribute
if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement-- if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
previousRate.type = rateType if (rateType === 'none') { // Destroy previous rate
promise = previousRate.destroy()
} else { // Update previous rate
previousRate.type = rateType as VideoRateType
return previousRate.save(options).then(() => ({ t, likesToIncrement, dislikesToIncrement })) promise = previousRate.save()
} else { // There was not a previous rate, insert a new one }
} else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate
const query = { const query = {
userId: userInstance.id, userId: userInstance.id,
videoId: videoInstance.id, videoId: videoInstance.id,
type: rateType type: rateType
} }
return db.UserVideoRate.create(query, options).then(() => ({ likesToIncrement, dislikesToIncrement })) promise = db.UserVideoRate.create(query, options)
} else {
promise = Promise.resolve()
} }
return promise.then(() => ({ likesToIncrement, dislikesToIncrement }))
}) })
.then(({ likesToIncrement, dislikesToIncrement }) => { .then(({ likesToIncrement, dislikesToIncrement }) => {
const options = { transaction: t } const options = { transaction: t }

View File

@ -8,6 +8,7 @@ import {
CONFIG CONFIG
} from '../initializers' } from '../initializers'
import { PodInstance } from '../models' import { PodInstance } from '../models'
import { PodSignature } from '../../shared'
import { sign } from './peertube-crypto' import { sign } from './peertube-crypto'
type MakeRetryRequestParams = { type MakeRetryRequestParams = {
@ -37,9 +38,18 @@ type MakeSecureRequestParams = {
} }
function makeSecureRequest (params: MakeSecureRequestParams) { function makeSecureRequest (params: MakeSecureRequestParams) {
return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => { return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => {
const requestParams = { const requestParams: {
url: string,
json: {
signature: PodSignature,
data: any
}
} = {
url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path, url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
json: {} json: {
signature: null,
data: null
}
} }
if (params.method !== 'POST') { if (params.method !== 'POST') {
@ -58,14 +68,14 @@ function makeSecureRequest (params: MakeSecureRequestParams) {
} }
sign(dataToSign).then(signature => { sign(dataToSign).then(signature => {
requestParams.json['signature'] = { requestParams.json.signature = {
host, // Which host we pretend to be host, // Which host we pretend to be
signature signature
} }
// If there are data informations // If there are data informations
if (params.data) { if (params.data) {
requestParams.json['data'] = params.data requestParams.json.data = params.data
} }
request.post(requestParams, (err, response, body) => err ? rej(err) : res({ response, body })) request.post(requestParams, (err, response, body) => err ? rej(err) : res({ response, body }))

View File

@ -34,7 +34,11 @@ import {
import { import {
RequestEndpoint, RequestEndpoint,
RequestVideoEventType, RequestVideoEventType,
RequestVideoQaduType RequestVideoQaduType,
RemoteVideoCreateData,
RemoteVideoUpdateData,
RemoteVideoRemoveData,
RemoteVideoReportAbuseData
} from '../../shared' } from '../../shared'
type QaduParam = { videoId: string, type: RequestVideoQaduType } type QaduParam = { videoId: string, type: RequestVideoQaduType }
@ -52,7 +56,7 @@ function activateSchedulers () {
requestVideoEventScheduler.activate() requestVideoEventScheduler.activate()
} }
function addVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) { function addVideoToFriends (videoData: RemoteVideoCreateData, transaction: Sequelize.Transaction) {
const options = { const options = {
type: ENDPOINT_ACTIONS.ADD, type: ENDPOINT_ACTIONS.ADD,
endpoint: REQUEST_ENDPOINTS.VIDEOS, endpoint: REQUEST_ENDPOINTS.VIDEOS,
@ -62,7 +66,7 @@ function addVideoToFriends (videoData: Object, transaction: Sequelize.Transactio
return createRequest(options) return createRequest(options)
} }
function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) { function updateVideoToFriends (videoData: RemoteVideoUpdateData, transaction: Sequelize.Transaction) {
const options = { const options = {
type: ENDPOINT_ACTIONS.UPDATE, type: ENDPOINT_ACTIONS.UPDATE,
endpoint: REQUEST_ENDPOINTS.VIDEOS, endpoint: REQUEST_ENDPOINTS.VIDEOS,
@ -72,7 +76,7 @@ function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transac
return createRequest(options) return createRequest(options)
} }
function removeVideoToFriends (videoParams: Object) { function removeVideoToFriends (videoParams: RemoteVideoRemoveData) {
const options = { const options = {
type: ENDPOINT_ACTIONS.REMOVE, type: ENDPOINT_ACTIONS.REMOVE,
endpoint: REQUEST_ENDPOINTS.VIDEOS, endpoint: REQUEST_ENDPOINTS.VIDEOS,
@ -82,7 +86,7 @@ function removeVideoToFriends (videoParams: Object) {
return createRequest(options) return createRequest(options)
} }
function reportAbuseVideoToFriend (reportData: Object, video: VideoInstance, transaction: Sequelize.Transaction) { function reportAbuseVideoToFriend (reportData: RemoteVideoReportAbuseData, video: VideoInstance, transaction: Sequelize.Transaction) {
const options = { const options = {
type: ENDPOINT_ACTIONS.REPORT_ABUSE, type: ENDPOINT_ACTIONS.REPORT_ABUSE,
endpoint: REQUEST_ENDPOINTS.VIDEOS, endpoint: REQUEST_ENDPOINTS.VIDEOS,

View File

@ -10,6 +10,15 @@ import {
REQUESTS_INTERVAL REQUESTS_INTERVAL
} from '../../initializers' } from '../../initializers'
interface RequestsObjects<U> {
[ id: string ]: {
toPod: PodInstance
endpoint: string
ids: number[] // ids
datas: U[]
}
}
abstract class AbstractRequestScheduler <T> { abstract class AbstractRequestScheduler <T> {
requestInterval: number requestInterval: number
limitPods: number limitPods: number
@ -27,7 +36,7 @@ abstract class AbstractRequestScheduler <T> {
abstract getRequestModel (): AbstractRequestClass<T> abstract getRequestModel (): AbstractRequestClass<T>
abstract getRequestToPodModel (): AbstractRequestToPodClass abstract getRequestToPodModel (): AbstractRequestToPodClass
abstract buildRequestObjects (requestsGrouped: T): {} abstract buildRequestsObjects (requestsGrouped: T): RequestsObjects<any>
activate () { activate () {
logger.info('Requests scheduler activated.') logger.info('Requests scheduler activated.')
@ -67,7 +76,7 @@ abstract class AbstractRequestScheduler <T> {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Make a requests to friends of a certain type // Make a requests to friends of a certain type
protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: Object) { protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: any) {
const params = { const params = {
toPod: toPod, toPod: toPod,
method: 'POST' as 'POST', method: 'POST' as 'POST',
@ -95,7 +104,7 @@ abstract class AbstractRequestScheduler <T> {
return this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod) return this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod)
.then((requestsGrouped: T) => { .then((requestsGrouped: T) => {
// We want to group requests by destinations pod and endpoint // We want to group requests by destinations pod and endpoint
const requestsToMake = this.buildRequestObjects(requestsGrouped) const requestsToMake = this.buildRequestsObjects(requestsGrouped)
// If there are no requests, abort // If there are no requests, abort
if (isEmpty(requestsToMake) === true) { if (isEmpty(requestsToMake) === true) {
@ -105,8 +114,8 @@ abstract class AbstractRequestScheduler <T> {
logger.info('Making "%s" to friends.', this.description) logger.info('Making "%s" to friends.', this.description)
const goodPods = [] const goodPods: number[] = []
const badPods = [] const badPods: number[] = []
return Promise.map(Object.keys(requestsToMake), hashKey => { return Promise.map(Object.keys(requestsToMake), hashKey => {
const requestToMake = requestsToMake[hashKey] const requestToMake = requestsToMake[hashKey]
@ -149,5 +158,6 @@ abstract class AbstractRequestScheduler <T> {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
export { export {
AbstractRequestScheduler AbstractRequestScheduler,
RequestsObjects
} }

View File

@ -1,11 +1,11 @@
import * as Sequelize from 'sequelize' import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database' import { database as db } from '../../initializers/database'
import { AbstractRequestScheduler } from './abstract-request-scheduler' import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import { logger } from '../../helpers' import { logger } from '../../helpers'
import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers' import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers'
import { RequestsGrouped } from '../../models' import { RequestsGrouped } from '../../models'
import { RequestEndpoint } from '../../../shared' import { RequestEndpoint, RemoteVideoRequest } from '../../../shared'
export type RequestSchedulerOptions = { export type RequestSchedulerOptions = {
type: string type: string
@ -34,8 +34,8 @@ class RequestScheduler extends AbstractRequestScheduler<RequestsGrouped> {
return db.RequestToPod return db.RequestToPod
} }
buildRequestObjects (requestsGrouped: RequestsGrouped) { buildRequestsObjects (requestsGrouped: RequestsGrouped) {
const requestsToMakeGrouped = {} const requestsToMakeGrouped: RequestsObjects<RemoteVideoRequest> = {}
Object.keys(requestsGrouped).forEach(toPodId => { Object.keys(requestsGrouped).forEach(toPodId => {
requestsGrouped[toPodId].forEach(data => { requestsGrouped[toPodId].forEach(data => {

View File

@ -1,14 +1,14 @@
import * as Sequelize from 'sequelize' import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database' import { database as db } from '../../initializers/database'
import { AbstractRequestScheduler } from './abstract-request-scheduler' import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import { import {
REQUESTS_VIDEO_EVENT_LIMIT_PODS, REQUESTS_VIDEO_EVENT_LIMIT_PODS,
REQUESTS_VIDEO_EVENT_LIMIT_PER_POD, REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
REQUEST_VIDEO_EVENT_ENDPOINT REQUEST_VIDEO_EVENT_ENDPOINT
} from '../../initializers' } from '../../initializers'
import { RequestsVideoEventGrouped } from '../../models' import { RequestsVideoEventGrouped } from '../../models'
import { RequestVideoEventType } from '../../../shared' import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared'
export type RequestVideoEventSchedulerOptions = { export type RequestVideoEventSchedulerOptions = {
type: RequestVideoEventType type: RequestVideoEventType
@ -36,8 +36,8 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
return db.RequestVideoEvent return db.RequestVideoEvent
} }
buildRequestObjects (eventRequests: RequestsVideoEventGrouped) { buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) {
const requestsToMakeGrouped = {} const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {}
/* Example: /* Example:
{ {
@ -47,7 +47,15 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
} }
} }
*/ */
const eventsPerVideoPerPod = {} const eventsPerVideoPerPod: {
[ podId: string ]: {
[ videoRemoteId: string ]: {
views?: number
likes?: number
dislikes?: number
}
}
} = {}
// We group video events per video and per pod // We group video events per video and per pod
// We add the counts of the same event types // We add the counts of the same event types
@ -87,8 +95,8 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
requestsToMakeGrouped[toPodId].datas.push({ requestsToMakeGrouped[toPodId].datas.push({
data: { data: {
remoteId, remoteId,
eventType, eventType: eventType as RemoteVideoEventType,
count: eventsForVideo[eventType] count: +eventsForVideo[eventType]
} }
}) })
}) })

View File

@ -1,7 +1,7 @@
import * as Sequelize from 'sequelize' import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database' import { database as db } from '../../initializers/database'
import { AbstractRequestScheduler } from './abstract-request-scheduler' import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import { logger } from '../../helpers' import { logger } from '../../helpers'
import { import {
REQUESTS_VIDEO_QADU_LIMIT_PODS, REQUESTS_VIDEO_QADU_LIMIT_PODS,
@ -9,8 +9,27 @@ import {
REQUEST_VIDEO_QADU_ENDPOINT, REQUEST_VIDEO_QADU_ENDPOINT,
REQUEST_VIDEO_QADU_TYPES REQUEST_VIDEO_QADU_TYPES
} from '../../initializers' } from '../../initializers'
import { RequestsVideoQaduGrouped } from '../../models' import { RequestsVideoQaduGrouped, PodInstance } from '../../models'
import { RequestVideoQaduType } from '../../../shared' import { RemoteQaduVideoRequest, RequestVideoQaduType } from '../../../shared'
// We create a custom interface because we need "videos" attribute for our computations
interface RequestsObjectsCustom<U> extends RequestsObjects<U> {
[ id: string ]: {
toPod: PodInstance
endpoint: string
ids: number[] // ids
datas: U[]
videos: {
[ id: string ]: {
remoteId: string
likes?: number
dislikes?: number
views?: number
}
}
}
}
export type RequestVideoQaduSchedulerOptions = { export type RequestVideoQaduSchedulerOptions = {
type: RequestVideoQaduType type: RequestVideoQaduType
@ -37,8 +56,8 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
return db.RequestVideoQadu return db.RequestVideoQadu
} }
buildRequestObjects (requests: RequestsVideoQaduGrouped) { buildRequestsObjects (requests: RequestsVideoQaduGrouped) {
const requestsToMakeGrouped = {} const requestsToMakeGrouped: RequestsObjectsCustom<RemoteQaduVideoRequest> = {}
Object.keys(requests).forEach(toPodId => { Object.keys(requests).forEach(toPodId => {
requests[toPodId].forEach(data => { requests[toPodId].forEach(data => {
@ -59,7 +78,7 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
// Maybe another attribute was filled for this video // Maybe another attribute was filled for this video
let videoData = requestsToMakeGrouped[hashKey].videos[video.id] let videoData = requestsToMakeGrouped[hashKey].videos[video.id]
if (!videoData) videoData = {} if (!videoData) videoData = { remoteId: null }
switch (request.type) { switch (request.type) {
case REQUEST_VIDEO_QADU_TYPES.LIKES: case REQUEST_VIDEO_QADU_TYPES.LIKES:

View File

@ -6,9 +6,12 @@ import {
logger, logger,
checkSignature as peertubeCryptoCheckSignature checkSignature as peertubeCryptoCheckSignature
} from '../helpers' } from '../helpers'
import { PodSignature } from '../../shared'
function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) { function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) {
const host = req.body.signature.host const signatureObject: PodSignature = req.body.signature
const host = signatureObject.host
db.Pod.loadByHost(host) db.Pod.loadByHost(host)
.then(pod => { .then(pod => {
if (pod === null) { if (pod === null) {
@ -27,7 +30,7 @@ function checkSignature (req: express.Request, res: express.Response, next: expr
signatureShouldBe = host signatureShouldBe = host
} }
const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature) const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, signatureObject.signature)
if (signatureOk === true) { if (signatureOk === true) {
res.locals.secure = { res.locals.secure = {
@ -37,11 +40,11 @@ function checkSignature (req: express.Request, res: express.Response, next: expr
return next() return next()
} }
logger.error('Signature is not okay in body for %s.', req.body.signature.host) logger.error('Signature is not okay in body for %s.', signatureObject.host)
return res.sendStatus(403) return res.sendStatus(403)
}) })
.catch(err => { .catch(err => {
logger.error('Cannot get signed host in body.', { error: err.stack, signature: req.body.signature.signature }) logger.error('Cannot get signed host in body.', { error: err.stack, signature: signatureObject.signature })
return res.sendStatus(500) return res.sendStatus(500)
}) })
} }

View File

@ -2,7 +2,7 @@ import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird' import * as Promise from 'bluebird'
// Don't use barrel, import just what we need // Don't use barrel, import just what we need
import { Pod as FormatedPod } from '../../../shared/models/pod.model' import { Pod as FormatedPod } from '../../../shared/models/pods/pod.model'
export namespace PodMethods { export namespace PodMethods {
export type ToFormatedJSON = (this: PodInstance) => FormatedPod export type ToFormatedJSON = (this: PodInstance) => FormatedPod

View File

@ -2,7 +2,8 @@ import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird' import * as Promise from 'bluebird'
// Don't use barrel, import just what we need // Don't use barrel, import just what we need
import { UserRole, User as FormatedUser } from '../../../shared/models/user.model' import { User as FormatedUser } from '../../../shared/models/users/user.model'
import { UserRole } from '../../../shared/models/users/user-role.type'
import { ResultList } from '../../../shared/models/result-list.model' import { ResultList } from '../../../shared/models/result-list.model'
export namespace UserMethods { export namespace UserMethods {

View File

@ -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 { VideoRateType } from '../../../shared/models/user-video-rate.model' import { VideoRateType } from '../../../shared/models/videos/video-rate.type'
export namespace UserVideoRateMethods { export namespace UserVideoRateMethods {
export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance> export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance>

View File

@ -5,7 +5,7 @@ import { PodInstance } from '../pod'
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
import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/video-abuse.model' import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/videos/video-abuse.model'
export namespace VideoAbuseMethods { export namespace VideoAbuseMethods {
export type ToFormatedJSON = (this: VideoAbuseInstance) => FormatedVideoAbuse export type ToFormatedJSON = (this: VideoAbuseInstance) => FormatedVideoAbuse

View File

@ -4,7 +4,7 @@ import * as Promise from 'bluebird'
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
import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/video-blacklist.model' import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/videos/video-blacklist.model'
export namespace BlacklistedVideoMethods { export namespace BlacklistedVideoMethods {
export type ToFormatedJSON = (this: BlacklistedVideoInstance) => FormatedBlacklistedVideo export type ToFormatedJSON = (this: BlacklistedVideoInstance) => FormatedBlacklistedVideo

View File

@ -5,7 +5,7 @@ import { AuthorInstance } from './author-interface'
import { TagAttributes, TagInstance } from './tag-interface' import { TagAttributes, TagInstance } from './tag-interface'
// Don't use barrel, import just what we need // Don't use barrel, import just what we need
import { Video as FormatedVideo } from '../../../shared/models/video.model' import { Video as FormatedVideo } from '../../../shared/models/videos/video.model'
import { ResultList } from '../../../shared/models/result-list.model' import { ResultList } from '../../../shared/models/result-list.model'
export type FormatedAddRemoteVideo = { export type FormatedAddRemoteVideo = {

View File

@ -1,11 +1,8 @@
export * from './pods'
export * from './users'
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 './pod.model'
export * from './result-list.model' export * from './result-list.model'
export * from './request-scheduler.model' export * from './request-scheduler.model'
export * from './user-video-rate.model'
export * from './user.model'
export * from './video-abuse.model'
export * from './video-blacklist.model'
export * from './video.model'
export * from './server-config.model' export * from './server-config.model'

View File

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

View File

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

View File

@ -0,0 +1,7 @@
export * from './remote-qadu-video-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-report-abuse-request.model'

View File

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

View File

@ -0,0 +1,27 @@
import { RemoteVideoRequest } from './remote-video-request.model'
export interface RemoteVideoCreateData {
remoteId: string
author: string
tags: string[]
name: string
extname: string
infoHash: string
category: number
licence: number
language: number
nsfw: boolean
description: string
duration: number
createdAt: Date
updatedAt: Date
views: number
likes: number
dislikes: number
thumbnailData: string
}
export interface RemoteVideoCreateRequest extends RemoteVideoRequest {
type: 'add'
data: RemoteVideoCreateData
}

View File

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

View File

@ -0,0 +1,10 @@
import { RemoteVideoRequest } from './remote-video-request.model'
export interface RemoteVideoRemoveData {
remoteId: string
}
export interface RemoteVideoRemoveRequest extends RemoteVideoRequest {
type: 'remove'
data: RemoteVideoRemoveData
}

View File

@ -0,0 +1,12 @@
import { RemoteVideoRequest } from './remote-video-request.model'
export interface RemoteVideoReportAbuseData {
videoRemoteId: string
reporterUsername: string
reportReason: string
}
export interface RemoteVideoReportAbuseRequest extends RemoteVideoRequest {
type: 'report-abuse'
data: RemoteVideoReportAbuseData
}

View File

@ -0,0 +1,4 @@
export interface RemoteVideoRequest {
type: 'add' | 'update' | 'remove' | 'report-abuse'
data: any
}

View File

@ -0,0 +1,23 @@
export interface RemoteVideoUpdateData {
remoteId: string
tags: string[]
name: string
extname: string
infoHash: string
category: number
licence: number
language: number
nsfw: boolean
description: string
duration: number
createdAt: Date
updatedAt: Date
views: number
likes: number
dislikes: number
}
export interface RemoteVideoUpdateRequest {
type: 'update'
data: RemoteVideoUpdateData
}

View File

@ -1,7 +0,0 @@
export type VideoRateType = 'like' | 'dislike'
export type UserVideoRateType = 'like' | 'dislike' | 'none'
export interface UserVideoRate {
videoId: string
rating: UserVideoRateType
}

View File

@ -0,0 +1,4 @@
export * from './user.model'
export * from './user-create.model'
export * from './user-update.model'
export * from './user-role.type'

View File

@ -0,0 +1,5 @@
export interface UserCreate {
username: string
password: string
email: string
}

View File

@ -0,0 +1 @@
export type UserRole = 'admin' | 'user'

View File

@ -0,0 +1,4 @@
export interface UserUpdate {
displayNSFW?: boolean
password?: string
}

View File

@ -1,4 +1,4 @@
export type UserRole = 'admin' | 'user' import { UserRole } from './user-role.type'
export interface User { export interface User {
id: number id: number

View File

@ -0,0 +1,10 @@
export * from './user-video-rate-update.model'
export * from './user-video-rate.model'
export * from './user-video-rate.type'
export * from './video-abuse-create.model'
export * from './video-abuse.model'
export * from './video-blacklist.model'
export * from './video-create.model'
export * from './video-rate.type'
export * from './video-update.model'
export * from './video.model'

View File

@ -0,0 +1,5 @@
import { UserVideoRateType } from './user-video-rate.type'
export interface UserVideoRateUpdate {
rating: UserVideoRateType
}

View File

@ -0,0 +1,6 @@
import { UserVideoRateType } from './user-video-rate.type'
export interface UserVideoRate {
videoId: string
rating: UserVideoRateType
}

View File

@ -0,0 +1 @@
export type UserVideoRateType = 'like' | 'dislike' | 'none'

View File

@ -0,0 +1,3 @@
export interface VideoAbuseCreate {
reason: string
}

View File

@ -0,0 +1,9 @@
export interface VideoCreate {
category: number
licence: number
language: number
description: string
nsfw: boolean
name: string
tags: string[]
}

View File

@ -0,0 +1 @@
export type VideoRateType = 'like' | 'dislike'

View File

@ -0,0 +1,9 @@
export interface VideoUpdate {
name?: string
category?: number
licence?: number
language?: number
description?: string
tags?: string[]
nsfw?: boolean
}