aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/send
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-03-24 13:36:47 +0100
committerChocobozzz <chocobozzz@cpy.re>2022-04-15 09:49:35 +0200
commitb211106695bb82f6c32e53306081b5262c3d109d (patch)
treefa187de1c33b0956665f5362e29af6b0f6d8bb57 /server/lib/activitypub/send
parent69d48ee30c9d47cddf0c3c047dc99a99dcb6e894 (diff)
downloadPeerTube-b211106695bb82f6c32e53306081b5262c3d109d.tar.gz
PeerTube-b211106695bb82f6c32e53306081b5262c3d109d.tar.zst
PeerTube-b211106695bb82f6c32e53306081b5262c3d109d.zip
Support video views/viewers stats in server
* Add "currentTime" and "event" body params to view endpoint * Merge watching and view endpoints * Introduce WatchAction AP activity * Add tables to store viewer information of local videos * Add endpoints to fetch video views/viewers stats of local videos * Refactor views/viewers handlers * Support "views" and "viewers" counters for both VOD and live videos
Diffstat (limited to 'server/lib/activitypub/send')
-rw-r--r--server/lib/activitypub/send/send-create.ts17
-rw-r--r--server/lib/activitypub/send/send-view.ts51
2 files changed, 51 insertions, 17 deletions
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts
index 5d8763495..7c3a6bdd0 100644
--- a/server/lib/activitypub/send/send-create.ts
+++ b/server/lib/activitypub/send/send-create.ts
@@ -6,6 +6,7 @@ import { VideoCommentModel } from '../../../models/video/video-comment'
6import { 6import {
7 MActorLight, 7 MActorLight,
8 MCommentOwnerVideo, 8 MCommentOwnerVideo,
9 MLocalVideoViewerWithWatchSections,
9 MVideoAccountLight, 10 MVideoAccountLight,
10 MVideoAP, 11 MVideoAP,
11 MVideoPlaylistFull, 12 MVideoPlaylistFull,
@@ -19,6 +20,7 @@ import {
19 getActorsInvolvedInVideo, 20 getActorsInvolvedInVideo,
20 getAudienceFromFollowersOf, 21 getAudienceFromFollowersOf,
21 getVideoCommentAudience, 22 getVideoCommentAudience,
23 sendVideoActivityToOrigin,
22 sendVideoRelatedActivity, 24 sendVideoRelatedActivity,
23 unicastTo 25 unicastTo
24} from './shared' 26} from './shared'
@@ -61,6 +63,18 @@ async function sendCreateCacheFile (
61 }) 63 })
62} 64}
63 65
66async function sendCreateWatchAction (stats: MLocalVideoViewerWithWatchSections, transaction: Transaction) {
67 logger.info('Creating job to send create watch action %s.', stats.url, lTags(stats.uuid))
68
69 const byActor = await getServerActor()
70
71 const activityBuilder = (audience: ActivityAudience) => {
72 return buildCreateActivity(stats.url, byActor, stats.toActivityPubObject(), audience)
73 }
74
75 return sendVideoActivityToOrigin(activityBuilder, { byActor, video: stats.Video, transaction, contextType: 'WatchAction' })
76}
77
64async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transaction: Transaction) { 78async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transaction: Transaction) {
65 if (playlist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined 79 if (playlist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
66 80
@@ -175,7 +189,8 @@ export {
175 buildCreateActivity, 189 buildCreateActivity,
176 sendCreateVideoComment, 190 sendCreateVideoComment,
177 sendCreateVideoPlaylist, 191 sendCreateVideoPlaylist,
178 sendCreateCacheFile 192 sendCreateCacheFile,
193 sendCreateWatchAction
179} 194}
180 195
181// --------------------------------------------------------------------------- 196// ---------------------------------------------------------------------------
diff --git a/server/lib/activitypub/send/send-view.ts b/server/lib/activitypub/send/send-view.ts
index 1f97307b9..1088bf258 100644
--- a/server/lib/activitypub/send/send-view.ts
+++ b/server/lib/activitypub/send/send-view.ts
@@ -1,27 +1,49 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { VideoViews } from '@server/lib/video-views' 2import { VideoViewsManager } from '@server/lib/views/video-views-manager'
3import { MActorAudience, MVideoImmutable, MVideoUrl } from '@server/types/models' 3import { MActorAudience, MActorLight, MVideoImmutable, MVideoUrl } from '@server/types/models'
4import { ActivityAudience, ActivityView } from '@shared/models' 4import { ActivityAudience, ActivityView } from '@shared/models'
5import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
6import { ActorModel } from '../../../models/actor/actor'
7import { audiencify, getAudience } from '../audience' 6import { audiencify, getAudience } from '../audience'
8import { getLocalVideoViewActivityPubUrl } from '../url' 7import { getLocalVideoViewActivityPubUrl } from '../url'
9import { sendVideoRelatedActivity } from './shared/send-utils' 8import { sendVideoRelatedActivity } from './shared/send-utils'
10 9
11async function sendView (byActor: ActorModel, video: MVideoImmutable, t: Transaction) { 10type ViewType = 'view' | 'viewer'
12 logger.info('Creating job to send view of %s.', video.url) 11
12async function sendView (options: {
13 byActor: MActorLight
14 type: ViewType
15 video: MVideoImmutable
16 transaction?: Transaction
17}) {
18 const { byActor, type, video, transaction } = options
19
20 logger.info('Creating job to send %s of %s.', type, video.url)
13 21
14 const activityBuilder = (audience: ActivityAudience) => { 22 const activityBuilder = (audience: ActivityAudience) => {
15 const url = getLocalVideoViewActivityPubUrl(byActor, video) 23 const url = getLocalVideoViewActivityPubUrl(byActor, video)
16 24
17 return buildViewActivity(url, byActor, video, audience) 25 return buildViewActivity({ url, byActor, video, audience, type })
18 } 26 }
19 27
20 return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t, contextType: 'View' }) 28 return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction, contextType: 'View' })
21} 29}
22 30
23function buildViewActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityView { 31// ---------------------------------------------------------------------------
24 if (!audience) audience = getAudience(byActor) 32
33export {
34 sendView
35}
36
37// ---------------------------------------------------------------------------
38
39function buildViewActivity (options: {
40 url: string
41 byActor: MActorAudience
42 video: MVideoUrl
43 type: ViewType
44 audience?: ActivityAudience
45}): ActivityView {
46 const { url, byActor, type, video, audience = getAudience(byActor) } = options
25 47
26 return audiencify( 48 return audiencify(
27 { 49 {
@@ -29,14 +51,11 @@ function buildViewActivity (url: string, byActor: MActorAudience, video: MVideoU
29 type: 'View' as 'View', 51 type: 'View' as 'View',
30 actor: byActor.url, 52 actor: byActor.url,
31 object: video.url, 53 object: video.url,
32 expires: new Date(VideoViews.Instance.buildViewerExpireTime()).toISOString() 54
55 expires: type === 'viewer'
56 ? new Date(VideoViewsManager.Instance.buildViewerExpireTime()).toISOString()
57 : undefined
33 }, 58 },
34 audience 59 audience
35 ) 60 )
36} 61}
37
38// ---------------------------------------------------------------------------
39
40export {
41 sendView
42}