aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r--server/lib/activitypub/account.ts104
-rw-r--r--server/lib/activitypub/index.ts5
-rw-r--r--server/lib/activitypub/process/process-add.ts17
-rw-r--r--server/lib/activitypub/process/process-announce.ts2
-rw-r--r--server/lib/activitypub/process/process-create.ts3
-rw-r--r--server/lib/activitypub/process/process-delete.ts2
-rw-r--r--server/lib/activitypub/process/process-follow.ts3
-rw-r--r--server/lib/activitypub/process/process-update.ts2
-rw-r--r--server/lib/activitypub/send/send-accept.ts2
-rw-r--r--server/lib/activitypub/send/send-announce.ts2
-rw-r--r--server/lib/activitypub/send/send-create.ts2
-rw-r--r--server/lib/activitypub/send/send-follow.ts2
-rw-r--r--server/lib/activitypub/send/send-undo.ts2
-rw-r--r--server/lib/activitypub/send/send-update.ts2
-rw-r--r--server/lib/activitypub/share.ts33
-rw-r--r--server/lib/activitypub/url.ts60
-rw-r--r--server/lib/activitypub/video-channels.ts60
-rw-r--r--server/lib/activitypub/videos.ts44
18 files changed, 328 insertions, 19 deletions
diff --git a/server/lib/activitypub/account.ts b/server/lib/activitypub/account.ts
new file mode 100644
index 000000000..704a92e13
--- /dev/null
+++ b/server/lib/activitypub/account.ts
@@ -0,0 +1,104 @@
1import * as url from 'url'
2import { ActivityPubActor } from '../../../shared/models/activitypub/activitypub-actor'
3import { isRemoteAccountValid } from '../../helpers/custom-validators/activitypub/account'
4import { logger } from '../../helpers/logger'
5import { doRequest } from '../../helpers/requests'
6import { ACTIVITY_PUB } from '../../initializers/constants'
7import { database as db } from '../../initializers/database'
8
9async function getOrCreateAccount (accountUrl: string) {
10 let account = await db.Account.loadByUrl(accountUrl)
11
12 // We don't have this account in our database, fetch it on remote
13 if (!account) {
14 const res = await fetchRemoteAccountAndCreateServer(accountUrl)
15 if (res === undefined) throw new Error('Cannot fetch remote account.')
16
17 // Save our new account in database
18 account = await res.account.save()
19 }
20
21 return account
22}
23
24async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
25 const options = {
26 uri: accountUrl,
27 method: 'GET',
28 headers: {
29 'Accept': ACTIVITY_PUB.ACCEPT_HEADER
30 }
31 }
32
33 logger.info('Fetching remote account %s.', accountUrl)
34
35 let requestResult
36 try {
37 requestResult = await doRequest(options)
38 } catch (err) {
39 logger.warn('Cannot fetch remote account %s.', accountUrl, err)
40 return undefined
41 }
42
43 const accountJSON: ActivityPubActor = JSON.parse(requestResult.body)
44 if (isRemoteAccountValid(accountJSON) === false) {
45 logger.debug('Remote account JSON is not valid.', { accountJSON })
46 return undefined
47 }
48
49 const followersCount = await fetchAccountCount(accountJSON.followers)
50 const followingCount = await fetchAccountCount(accountJSON.following)
51
52 const account = db.Account.build({
53 uuid: accountJSON.uuid,
54 name: accountJSON.preferredUsername,
55 url: accountJSON.url,
56 publicKey: accountJSON.publicKey.publicKeyPem,
57 privateKey: null,
58 followersCount: followersCount,
59 followingCount: followingCount,
60 inboxUrl: accountJSON.inbox,
61 outboxUrl: accountJSON.outbox,
62 sharedInboxUrl: accountJSON.endpoints.sharedInbox,
63 followersUrl: accountJSON.followers,
64 followingUrl: accountJSON.following
65 })
66
67 const accountHost = url.parse(account.url).host
68 const serverOptions = {
69 where: {
70 host: accountHost
71 },
72 defaults: {
73 host: accountHost
74 }
75 }
76 const [ server ] = await db.Server.findOrCreate(serverOptions)
77 account.set('serverId', server.id)
78
79 return { account, server }
80}
81
82export {
83 getOrCreateAccount,
84 fetchRemoteAccountAndCreateServer
85}
86
87// ---------------------------------------------------------------------------
88
89async function fetchAccountCount (url: string) {
90 const options = {
91 uri: url,
92 method: 'GET'
93 }
94
95 let requestResult
96 try {
97 requestResult = await doRequest(options)
98 } catch (err) {
99 logger.warn('Cannot fetch remote account count %s.', url, err)
100 return undefined
101 }
102
103 return requestResult.totalItems ? requestResult.totalItems : 0
104}
diff --git a/server/lib/activitypub/index.ts b/server/lib/activitypub/index.ts
index 1bea0a412..b1daa70bb 100644
--- a/server/lib/activitypub/index.ts
+++ b/server/lib/activitypub/index.ts
@@ -1,2 +1,7 @@
1export * from './process' 1export * from './process'
2export * from './send' 2export * from './send'
3export * from './account'
4export * from './share'
5export * from './video-channels'
6export * from './videos'
7export * from './url'
diff --git a/server/lib/activitypub/process/process-add.ts b/server/lib/activitypub/process/process-add.ts
index f064c1ab6..281036228 100644
--- a/server/lib/activitypub/process/process-add.ts
+++ b/server/lib/activitypub/process/process-add.ts
@@ -1,11 +1,14 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { VideoTorrentObject } from '../../../../shared' 2import { VideoTorrentObject } from '../../../../shared'
3import { ActivityAdd } from '../../../../shared/models/activitypub/activity' 3import { ActivityAdd } from '../../../../shared/models/activitypub/activity'
4import { generateThumbnailFromUrl, getOrCreateAccount, logger, retryTransactionWrapper } from '../../../helpers' 4import { retryTransactionWrapper } from '../../../helpers/database-utils'
5import { getOrCreateVideoChannel } from '../../../helpers/activitypub' 5import { logger } from '../../../helpers/logger'
6import { database as db } from '../../../initializers' 6import { database as db } from '../../../initializers'
7import { AccountInstance } from '../../../models/account/account-interface' 7import { AccountInstance } from '../../../models/account/account-interface'
8import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 8import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
9import { getOrCreateAccount } from '../account'
10import { getOrCreateVideoChannel } from '../video-channels'
11import { generateThumbnailFromUrl } from '../videos'
9import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' 12import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
10 13
11async function processAddActivity (activity: ActivityAdd) { 14async function processAddActivity (activity: ActivityAdd) {
@@ -41,12 +44,10 @@ function processAddVideo (account: AccountInstance, activity: ActivityAdd, video
41 return retryTransactionWrapper(addRemoteVideo, options) 44 return retryTransactionWrapper(addRemoteVideo, options)
42} 45}
43 46
44function addRemoteVideo ( 47function addRemoteVideo (account: AccountInstance,
45 account: AccountInstance, 48 activity: ActivityAdd,
46 activity: ActivityAdd, 49 videoChannel: VideoChannelInstance,
47 videoChannel: VideoChannelInstance, 50 videoToCreateData: VideoTorrentObject) {
48 videoToCreateData: VideoTorrentObject
49) {
50 logger.debug('Adding remote video %s.', videoToCreateData.url) 51 logger.debug('Adding remote video %s.', videoToCreateData.url)
51 52
52 return db.sequelize.transaction(async t => { 53 return db.sequelize.transaction(async t => {
diff --git a/server/lib/activitypub/process/process-announce.ts b/server/lib/activitypub/process/process-announce.ts
index 656db08a9..40712ef03 100644
--- a/server/lib/activitypub/process/process-announce.ts
+++ b/server/lib/activitypub/process/process-announce.ts
@@ -1,11 +1,11 @@
1import { ActivityAnnounce } from '../../../../shared/models/activitypub/activity' 1import { ActivityAnnounce } from '../../../../shared/models/activitypub/activity'
2import { getOrCreateAccount } from '../../../helpers/activitypub'
3import { logger } from '../../../helpers/logger' 2import { logger } from '../../../helpers/logger'
4import { database as db } from '../../../initializers/index' 3import { database as db } from '../../../initializers/index'
5import { VideoInstance } from '../../../models/index' 4import { VideoInstance } from '../../../models/index'
6import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 5import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
7import { processAddActivity } from './process-add' 6import { processAddActivity } from './process-add'
8import { processCreateActivity } from './process-create' 7import { processCreateActivity } from './process-create'
8import { getOrCreateAccount } from '../account'
9 9
10async function processAnnounceActivity (activity: ActivityAnnounce) { 10async function processAnnounceActivity (activity: ActivityAnnounce) {
11 const announcedActivity = activity.object 11 const announcedActivity = activity.object
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index aac941a6c..fc635eb1f 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -1,9 +1,10 @@
1import { ActivityCreate, VideoChannelObject } from '../../../../shared' 1import { ActivityCreate, VideoChannelObject } from '../../../../shared'
2import { VideoAbuseObject } from '../../../../shared/models/activitypub/objects/video-abuse-object' 2import { VideoAbuseObject } from '../../../../shared/models/activitypub/objects/video-abuse-object'
3import { logger, retryTransactionWrapper } from '../../../helpers' 3import { logger, retryTransactionWrapper } from '../../../helpers'
4import { getOrCreateAccount, getVideoChannelActivityPubUrl } from '../../../helpers/activitypub'
5import { database as db } from '../../../initializers' 4import { database as db } from '../../../initializers'
6import { AccountInstance } from '../../../models/account/account-interface' 5import { AccountInstance } from '../../../models/account/account-interface'
6import { getOrCreateAccount } from '../account'
7import { getVideoChannelActivityPubUrl } from '../url'
7import { videoChannelActivityObjectToDBAttributes } from './misc' 8import { videoChannelActivityObjectToDBAttributes } from './misc'
8 9
9async function processCreateActivity (activity: ActivityCreate) { 10async function processCreateActivity (activity: ActivityCreate) {
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts
index af5d964d4..0328d1a7d 100644
--- a/server/lib/activitypub/process/process-delete.ts
+++ b/server/lib/activitypub/process/process-delete.ts
@@ -1,11 +1,11 @@
1import { ActivityDelete } from '../../../../shared/models/activitypub/activity' 1import { ActivityDelete } from '../../../../shared/models/activitypub/activity'
2import { getOrCreateAccount } from '../../../helpers/activitypub'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
5import { database as db } from '../../../initializers' 4import { database as db } from '../../../initializers'
6import { AccountInstance } from '../../../models/account/account-interface' 5import { AccountInstance } from '../../../models/account/account-interface'
7import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 6import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
8import { VideoInstance } from '../../../models/video/video-interface' 7import { VideoInstance } from '../../../models/video/video-interface'
8import { getOrCreateAccount } from '../account'
9 9
10async function processDeleteActivity (activity: ActivityDelete) { 10async function processDeleteActivity (activity: ActivityDelete) {
11 const account = await getOrCreateAccount(activity.actor) 11 const account = await getOrCreateAccount(activity.actor)
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts
index 553639580..41b38828c 100644
--- a/server/lib/activitypub/process/process-follow.ts
+++ b/server/lib/activitypub/process/process-follow.ts
@@ -1,9 +1,10 @@
1import { ActivityFollow } from '../../../../shared/models/activitypub/activity' 1import { ActivityFollow } from '../../../../shared/models/activitypub/activity'
2import { getOrCreateAccount, retryTransactionWrapper } from '../../../helpers' 2import { retryTransactionWrapper } from '../../../helpers'
3import { database as db } from '../../../initializers' 3import { database as db } from '../../../initializers'
4import { AccountInstance } from '../../../models/account/account-interface' 4import { AccountInstance } from '../../../models/account/account-interface'
5import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
6import { sendAccept } from '../send/send-accept' 6import { sendAccept } from '../send/send-accept'
7import { getOrCreateAccount } from '../account'
7 8
8async function processFollowActivity (activity: ActivityFollow) { 9async function processFollowActivity (activity: ActivityFollow) {
9 const activityObject = activity.object 10 const activityObject = activity.object
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts
index a3bfb1baf..4876735b8 100644
--- a/server/lib/activitypub/process/process-update.ts
+++ b/server/lib/activitypub/process/process-update.ts
@@ -1,6 +1,5 @@
1import { VideoChannelObject, VideoTorrentObject } from '../../../../shared' 1import { VideoChannelObject, VideoTorrentObject } from '../../../../shared'
2import { ActivityUpdate } from '../../../../shared/models/activitypub/activity' 2import { ActivityUpdate } from '../../../../shared/models/activitypub/activity'
3import { getOrCreateAccount } from '../../../helpers/activitypub'
4import { retryTransactionWrapper } from '../../../helpers/database-utils' 3import { retryTransactionWrapper } from '../../../helpers/database-utils'
5import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
6import { resetSequelizeInstance } from '../../../helpers/utils' 5import { resetSequelizeInstance } from '../../../helpers/utils'
@@ -9,6 +8,7 @@ import { AccountInstance } from '../../../models/account/account-interface'
9import { VideoInstance } from '../../../models/video/video-interface' 8import { VideoInstance } from '../../../models/video/video-interface'
10import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' 9import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
11import Bluebird = require('bluebird') 10import Bluebird = require('bluebird')
11import { getOrCreateAccount } from '../account'
12 12
13async function processUpdateActivity (activity: ActivityUpdate) { 13async function processUpdateActivity (activity: ActivityUpdate) {
14 const account = await getOrCreateAccount(activity.actor) 14 const account = await getOrCreateAccount(activity.actor)
diff --git a/server/lib/activitypub/send/send-accept.ts b/server/lib/activitypub/send/send-accept.ts
index 0324a30fa..eeab19ed0 100644
--- a/server/lib/activitypub/send/send-accept.ts
+++ b/server/lib/activitypub/send/send-accept.ts
@@ -3,7 +3,7 @@ import { ActivityAccept } from '../../../../shared/models/activitypub/activity'
3import { AccountInstance } from '../../../models' 3import { AccountInstance } from '../../../models'
4import { AccountFollowInstance } from '../../../models/account/account-follow-interface' 4import { AccountFollowInstance } from '../../../models/account/account-follow-interface'
5import { unicastTo } from './misc' 5import { unicastTo } from './misc'
6import { getAccountFollowAcceptActivityPubUrl } from '../../../helpers/activitypub' 6import { getAccountFollowAcceptActivityPubUrl } from '../url'
7 7
8async function sendAccept (accountFollow: AccountFollowInstance, t: Transaction) { 8async function sendAccept (accountFollow: AccountFollowInstance, t: Transaction) {
9 const follower = accountFollow.AccountFollower 9 const follower = accountFollow.AccountFollower
diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts
index b9217e4f6..4b3a4ef75 100644
--- a/server/lib/activitypub/send/send-announce.ts
+++ b/server/lib/activitypub/send/send-announce.ts
@@ -4,7 +4,7 @@ import { VideoChannelInstance } from '../../../models/video/video-channel-interf
4import { broadcastToFollowers } from './misc' 4import { broadcastToFollowers } from './misc'
5import { addActivityData } from './send-add' 5import { addActivityData } from './send-add'
6import { createActivityData } from './send-create' 6import { createActivityData } from './send-create'
7import { getAnnounceActivityPubUrl } from '../../../helpers/activitypub' 7import { getAnnounceActivityPubUrl } from '../url'
8 8
9async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstance, t: Transaction) { 9async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
10 const url = getAnnounceActivityPubUrl(video.url, byAccount) 10 const url = getAnnounceActivityPubUrl(video.url, byAccount)
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts
index 66bfeee89..14b666fc9 100644
--- a/server/lib/activitypub/send/send-create.ts
+++ b/server/lib/activitypub/send/send-create.ts
@@ -3,7 +3,7 @@ import { ActivityCreate } from '../../../../shared/models/activitypub/activity'
3import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models' 3import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models'
4import { VideoAbuseInstance } from '../../../models/video/video-abuse-interface' 4import { VideoAbuseInstance } from '../../../models/video/video-abuse-interface'
5import { broadcastToFollowers, getAudience, unicastTo } from './misc' 5import { broadcastToFollowers, getAudience, unicastTo } from './misc'
6import { getVideoAbuseActivityPubUrl } from '../../../helpers/activitypub' 6import { getVideoAbuseActivityPubUrl } from '../url'
7 7
8async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { 8async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) {
9 const byAccount = videoChannel.Account 9 const byAccount = videoChannel.Account
diff --git a/server/lib/activitypub/send/send-follow.ts b/server/lib/activitypub/send/send-follow.ts
index 48d641c22..3c01fb77c 100644
--- a/server/lib/activitypub/send/send-follow.ts
+++ b/server/lib/activitypub/send/send-follow.ts
@@ -2,8 +2,8 @@ import { Transaction } from 'sequelize'
2import { ActivityFollow } from '../../../../shared/models/activitypub/activity' 2import { ActivityFollow } from '../../../../shared/models/activitypub/activity'
3import { AccountInstance } from '../../../models' 3import { AccountInstance } from '../../../models'
4import { AccountFollowInstance } from '../../../models/account/account-follow-interface' 4import { AccountFollowInstance } from '../../../models/account/account-follow-interface'
5import { getAccountFollowActivityPubUrl } from '../url'
5import { unicastTo } from './misc' 6import { unicastTo } from './misc'
6import { getAccountFollowActivityPubUrl } from '../../../helpers/activitypub'
7 7
8async function sendFollow (accountFollow: AccountFollowInstance, t: Transaction) { 8async function sendFollow (accountFollow: AccountFollowInstance, t: Transaction) {
9 const me = accountFollow.AccountFollower 9 const me = accountFollow.AccountFollower
diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts
index 39da824f3..77bee6639 100644
--- a/server/lib/activitypub/send/send-undo.ts
+++ b/server/lib/activitypub/send/send-undo.ts
@@ -3,8 +3,8 @@ import { ActivityFollow, ActivityUndo } from '../../../../shared/models/activity
3import { AccountInstance } from '../../../models' 3import { AccountInstance } from '../../../models'
4import { AccountFollowInstance } from '../../../models/account/account-follow-interface' 4import { AccountFollowInstance } from '../../../models/account/account-follow-interface'
5import { unicastTo } from './misc' 5import { unicastTo } from './misc'
6import { getAccountFollowActivityPubUrl, getUndoActivityPubUrl } from '../../../helpers/activitypub'
7import { followActivityData } from './send-follow' 6import { followActivityData } from './send-follow'
7import { getAccountFollowActivityPubUrl, getUndoActivityPubUrl } from '../url'
8 8
9async function sendUndoFollow (accountFollow: AccountFollowInstance, t: Transaction) { 9async function sendUndoFollow (accountFollow: AccountFollowInstance, t: Transaction) {
10 const me = accountFollow.AccountFollower 10 const me = accountFollow.AccountFollower
diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts
index 42738f973..32cada06e 100644
--- a/server/lib/activitypub/send/send-update.ts
+++ b/server/lib/activitypub/send/send-update.ts
@@ -1,8 +1,8 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { ActivityUpdate } from '../../../../shared/models/activitypub/activity' 2import { ActivityUpdate } from '../../../../shared/models/activitypub/activity'
3import { getUpdateActivityPubUrl } from '../../../helpers/activitypub'
4import { database as db } from '../../../initializers' 3import { database as db } from '../../../initializers'
5import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models' 4import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models'
5import { getUpdateActivityPubUrl } from '../url'
6import { broadcastToFollowers, getAudience } from './misc' 6import { broadcastToFollowers, getAudience } from './misc'
7 7
8async function sendUpdateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { 8async function sendUpdateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) {
diff --git a/server/lib/activitypub/share.ts b/server/lib/activitypub/share.ts
new file mode 100644
index 000000000..689e200a6
--- /dev/null
+++ b/server/lib/activitypub/share.ts
@@ -0,0 +1,33 @@
1import { Transaction } from 'sequelize'
2import { getServerAccount } from '../../helpers/utils'
3import { database as db } from '../../initializers'
4import { VideoChannelInstance } from '../../models/index'
5import { VideoInstance } from '../../models/video/video-interface'
6import { sendVideoAnnounce, sendVideoChannelAnnounce } from './send/send-announce'
7
8async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t: Transaction) {
9 const serverAccount = await getServerAccount()
10
11 await db.VideoChannelShare.create({
12 accountId: serverAccount.id,
13 videoChannelId: videoChannel.id
14 }, { transaction: t })
15
16 return sendVideoChannelAnnounce(serverAccount, videoChannel, t)
17}
18
19async function shareVideoByServer (video: VideoInstance, t: Transaction) {
20 const serverAccount = await getServerAccount()
21
22 await db.VideoShare.create({
23 accountId: serverAccount.id,
24 videoId: video.id
25 }, { transaction: t })
26
27 return sendVideoAnnounce(serverAccount, video, t)
28}
29
30export {
31 shareVideoChannelByServer,
32 shareVideoByServer
33}
diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts
new file mode 100644
index 000000000..41ac0f9a8
--- /dev/null
+++ b/server/lib/activitypub/url.ts
@@ -0,0 +1,60 @@
1import { CONFIG } from '../../initializers/constants'
2import { VideoInstance } from '../../models/video/video-interface'
3import { VideoChannelInstance } from '../../models/video/video-channel-interface'
4import { VideoAbuseInstance } from '../../models/video/video-abuse-interface'
5import { AccountFollowInstance } from '../../models/account/account-follow-interface'
6import { AccountInstance } from '../../models/account/account-interface'
7
8function getVideoActivityPubUrl (video: VideoInstance) {
9 return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid
10}
11
12function getVideoChannelActivityPubUrl (videoChannel: VideoChannelInstance) {
13 return CONFIG.WEBSERVER.URL + '/video-channels/' + videoChannel.uuid
14}
15
16function getAccountActivityPubUrl (accountName: string) {
17 return CONFIG.WEBSERVER.URL + '/account/' + accountName
18}
19
20function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseInstance) {
21 return CONFIG.WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
22}
23
24function getAccountFollowActivityPubUrl (accountFollow: AccountFollowInstance) {
25 const me = accountFollow.AccountFollower
26 const following = accountFollow.AccountFollowing
27
28 return me.url + '#follows/' + following.id
29}
30
31function getAccountFollowAcceptActivityPubUrl (accountFollow: AccountFollowInstance) {
32 const follower = accountFollow.AccountFollower
33 const me = accountFollow.AccountFollowing
34
35 return follower.url + '#accepts/follows/' + me.id
36}
37
38function getAnnounceActivityPubUrl (originalUrl: string, byAccount: AccountInstance) {
39 return originalUrl + '#announces/' + byAccount.id
40}
41
42function getUpdateActivityPubUrl (originalUrl: string, updatedAt: string) {
43 return originalUrl + '#updates/' + updatedAt
44}
45
46function getUndoActivityPubUrl (originalUrl: string) {
47 return originalUrl + '/undo'
48}
49
50export {
51 getVideoActivityPubUrl,
52 getVideoChannelActivityPubUrl,
53 getAccountActivityPubUrl,
54 getVideoAbuseActivityPubUrl,
55 getAccountFollowActivityPubUrl,
56 getAccountFollowAcceptActivityPubUrl,
57 getAnnounceActivityPubUrl,
58 getUpdateActivityPubUrl,
59 getUndoActivityPubUrl
60}
diff --git a/server/lib/activitypub/video-channels.ts b/server/lib/activitypub/video-channels.ts
new file mode 100644
index 000000000..7339d79f9
--- /dev/null
+++ b/server/lib/activitypub/video-channels.ts
@@ -0,0 +1,60 @@
1import { VideoChannelObject } from '../../../shared/models/activitypub/objects/video-channel-object'
2import { isVideoChannelObjectValid } from '../../helpers/custom-validators/activitypub/video-channels'
3import { logger } from '../../helpers/logger'
4import { doRequest } from '../../helpers/requests'
5import { database as db } from '../../initializers'
6import { ACTIVITY_PUB } from '../../initializers/constants'
7import { AccountInstance } from '../../models/account/account-interface'
8import { videoChannelActivityObjectToDBAttributes } from './process/misc'
9
10async function getOrCreateVideoChannel (ownerAccount: AccountInstance, videoChannelUrl: string) {
11 let videoChannel = await db.VideoChannel.loadByUrl(videoChannelUrl)
12
13 // We don't have this account in our database, fetch it on remote
14 if (!videoChannel) {
15 videoChannel = await fetchRemoteVideoChannel(ownerAccount, videoChannelUrl)
16 if (videoChannel === undefined) throw new Error('Cannot fetch remote video channel.')
17
18 // Save our new video channel in database
19 await videoChannel.save()
20 }
21
22 return videoChannel
23}
24
25async function fetchRemoteVideoChannel (ownerAccount: AccountInstance, videoChannelUrl: string) {
26 const options = {
27 uri: videoChannelUrl,
28 method: 'GET',
29 headers: {
30 'Accept': ACTIVITY_PUB.ACCEPT_HEADER
31 }
32 }
33
34 logger.info('Fetching remote video channel %s.', videoChannelUrl)
35
36 let requestResult
37 try {
38 requestResult = await doRequest(options)
39 } catch (err) {
40 logger.warn('Cannot fetch remote video channel %s.', videoChannelUrl, err)
41 return undefined
42 }
43
44 const videoChannelJSON: VideoChannelObject = JSON.parse(requestResult.body)
45 if (isVideoChannelObjectValid(videoChannelJSON) === false) {
46 logger.debug('Remote video channel JSON is not valid.', { videoChannelJSON })
47 return undefined
48 }
49
50 const videoChannelAttributes = videoChannelActivityObjectToDBAttributes(videoChannelJSON, ownerAccount)
51 const videoChannel = db.VideoChannel.build(videoChannelAttributes)
52 videoChannel.Account = ownerAccount
53
54 return videoChannel
55}
56
57export {
58 getOrCreateVideoChannel,
59 fetchRemoteVideoChannel
60}
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
new file mode 100644
index 000000000..944244893
--- /dev/null
+++ b/server/lib/activitypub/videos.ts
@@ -0,0 +1,44 @@
1import { join } from 'path'
2import * as request from 'request'
3import { ActivityIconObject } from '../../../shared/index'
4import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
5import { CONFIG, REMOTE_SCHEME, STATIC_PATHS } from '../../initializers/constants'
6import { VideoInstance } from '../../models/video/video-interface'
7
8function fetchRemoteVideoPreview (video: VideoInstance) {
9 // FIXME: use url
10 const host = video.VideoChannel.Account.Server.host
11 const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName())
12
13 return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
14}
15
16async function fetchRemoteVideoDescription (video: VideoInstance) {
17 // FIXME: use url
18 const host = video.VideoChannel.Account.Server.host
19 const path = video.getDescriptionPath()
20 const options = {
21 uri: REMOTE_SCHEME.HTTP + '://' + host + path,
22 json: true
23 }
24
25 const { body } = await doRequest(options)
26 return body.description ? body.description : ''
27}
28
29function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObject) {
30 const thumbnailName = video.getThumbnailName()
31 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName)
32
33 const options = {
34 method: 'GET',
35 uri: icon.url
36 }
37 return doRequestAndSaveToFile(options, thumbnailPath)
38}
39
40export {
41 fetchRemoteVideoPreview,
42 fetchRemoteVideoDescription,
43 generateThumbnailFromUrl
44}