import { fetchRemoteVideoDescription, getVideoActivityPubUrl, shareVideoByServerAndChannel } from '../../../lib/activitypub'
import { sendCreateVideo, sendCreateViewToOrigin, sendCreateViewToVideoFollowers, sendUpdateVideo } from '../../../lib/activitypub/send'
import { JobQueue } from '../../../lib/job-queue'
+import { Redis } from '../../../lib/redis'
import {
asyncMiddleware,
authenticate,
async function viewVideo (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video
+ const ip = req.ip
+ const exists = await Redis.Instance.isViewExists(ip, videoInstance.uuid)
+ if (exists) {
+ logger.debug('View for ip %s and video %s already exists.', ip, videoInstance.uuid)
+ return res.status(204).end()
+ }
+
await videoInstance.increment('views')
+ await Redis.Instance.setView(ip, videoInstance.uuid)
+
const serverAccount = await getServerActor()
if (videoInstance.isOwned()) {
}
}
+let VIDEO_VIEW_LIFETIME = 60000 * 60 // 1 hour
+
const VIDEO_RATE_TYPES: { [ id: string ]: VideoRateType } = {
LIKE: 'like',
DISLIKE: 'dislike'
ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL = 10 * 1000 // 10 seconds
CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max = 100 * 1024 // 100KB
SCHEDULER_INTERVAL = 10000
+ VIDEO_VIEW_LIFETIME = 1000 // 1 second
}
updateWebserverConfig()
USER_PASSWORD_RESET_LIFETIME,
IMAGE_MIMETYPE_EXT,
SCHEDULER_INTERVAL,
- JOB_COMPLETED_LIFETIME
+ JOB_COMPLETED_LIFETIME,
+ VIDEO_VIEW_LIFETIME
}
// ---------------------------------------------------------------------------
import { createClient, RedisClient } from 'redis'
import { logger } from '../helpers/logger'
import { generateRandomString } from '../helpers/utils'
-import { CONFIG, USER_PASSWORD_RESET_LIFETIME } from '../initializers'
+import { CONFIG, USER_PASSWORD_RESET_LIFETIME, VIDEO_VIEW_LIFETIME } from '../initializers'
class Redis {
return this.getValue(this.generateResetPasswordKey(userId))
}
+ setView (ip: string, videoUUID: string) {
+ return this.setValue(this.buildViewKey(ip, videoUUID), '1', VIDEO_VIEW_LIFETIME)
+ }
+
+ async isViewExists (ip: string, videoUUID: string) {
+ return this.exists(this.buildViewKey(ip, videoUUID))
+ }
+
private getValue (key: string) {
return new Promise<string>((res, rej) => {
this.client.get(this.prefix + key, (err, value) => {
})
}
+ private exists (key: string) {
+ return new Promise<boolean>((res, rej) => {
+ this.client.exists(this.prefix + key, (err, existsNumber) => {
+ if (err) return rej(err)
+
+ return res(existsNumber === 1)
+ })
+ })
+ }
+
private generateResetPasswordKey (userId: number) {
return 'reset-password-' + userId
}
+ private buildViewKey (ip: string, videoUUID: string) {
+ return videoUUID + '-' + ip
+ }
+
static get Instance () {
return this.instance || (this.instance = new this())
}
})
it('Should view multiple videos on owned servers', async function () {
- this.timeout(10000)
+ this.timeout(15000)
const tasks: Promise<any>[] = []
- tasks.push(viewVideo(servers[2].url, localVideosServer3[0]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[0]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[0]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[1]))
+ await viewVideo(servers[2].url, localVideosServer3[0])
+ await viewVideo(servers[2].url, localVideosServer3[0])
+ await viewVideo(servers[2].url, localVideosServer3[0])
+ await viewVideo(servers[2].url, localVideosServer3[1])
await Promise.all(tasks)
+ await wait(1500)
+
+ await viewVideo(servers[2].url, localVideosServer3[0])
+
+ await wait(1500)
+
+ await viewVideo(servers[2].url, localVideosServer3[0])
await wait(5000)
checkVideoFilesWereRemoved, completeVideoCheck, flushTests, getVideo, getVideoCategories, getVideoLanguages, getVideoLicences,
getVideoPrivacies, getVideosList, getVideosListPagination, getVideosListSort, killallServers, rateVideo, removeVideo, runServer,
searchVideo, searchVideoWithPagination, searchVideoWithSort, ServerInfo, setAccessTokensToServers, testImage, updateVideo, uploadVideo,
- viewVideo
+ viewVideo, wait
} from '../../utils'
const expect = chai.expect
})
it('Should get and seed the uploaded video', async function () {
- // Yes, this could be long
- this.timeout(60000)
+ this.timeout(5000)
const res = await getVideosList(server.url)
})
it('Should get the video by UUID', async function () {
- // Yes, this could be long
- this.timeout(60000)
+ this.timeout(5000)
const res = await getVideo(server.url, videoUUID)
})
it('Should have the views updated', async function () {
+ this.timeout(10000)
+
await viewVideo(server.url, videoId)
await viewVideo(server.url, videoId)
await viewVideo(server.url, videoId)
+ await wait(1500)
+
+ await viewVideo(server.url, videoId)
+ await viewVideo(server.url, videoId)
+
+ await wait(1500)
+
+ await viewVideo(server.url, videoId)
+ await viewVideo(server.url, videoId)
+
const res = await getVideo(server.url, videoId)
const video = res.body