aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/controllers/api/videos/index.ts5
-rw-r--r--server/helpers/activitypub.ts275
-rw-r--r--server/helpers/webfinger.ts4
-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
-rw-r--r--server/lib/cache/videos-preview-cache.ts3
-rw-r--r--server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts6
-rw-r--r--server/lib/user.ts2
-rw-r--r--server/lib/video-channel.ts2
-rw-r--r--server/middlewares/activitypub.ts2
26 files changed, 341 insertions, 305 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 8c9b0aa50..0d114dcd2 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -3,7 +3,6 @@ import * as multer from 'multer'
3import { extname, join } from 'path' 3import { extname, join } from 'path'
4import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared' 4import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared'
5import { 5import {
6 fetchRemoteVideoDescription,
7 generateRandomString, 6 generateRandomString,
8 getFormattedObjects, 7 getFormattedObjects,
9 getVideoFileHeight, 8 getVideoFileHeight,
@@ -12,7 +11,6 @@ import {
12 resetSequelizeInstance, 11 resetSequelizeInstance,
13 retryTransactionWrapper 12 retryTransactionWrapper
14} from '../../../helpers' 13} from '../../../helpers'
15import { getVideoActivityPubUrl, shareVideoByServer } from '../../../helpers/activitypub'
16import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' 14import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers'
17import { database as db } from '../../../initializers/database' 15import { database as db } from '../../../initializers/database'
18import { sendAddVideo } from '../../../lib/activitypub/send/send-add' 16import { sendAddVideo } from '../../../lib/activitypub/send/send-add'
@@ -37,6 +35,9 @@ import { abuseVideoRouter } from './abuse'
37import { blacklistRouter } from './blacklist' 35import { blacklistRouter } from './blacklist'
38import { videoChannelRouter } from './channel' 36import { videoChannelRouter } from './channel'
39import { rateVideoRouter } from './rate' 37import { rateVideoRouter } from './rate'
38import { getVideoActivityPubUrl } from '../../../lib/activitypub/url'
39import { shareVideoByServer } from '../../../lib/activitypub/share'
40import { fetchRemoteVideoDescription } from '../../../lib/activitypub/videos'
40 41
41const videosRouter = express.Router() 42const videosRouter = express.Router()
42 43
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index 9622a1801..5c577bb61 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -1,244 +1,7 @@
1import { join } from 'path'
2import * as request from 'request'
3import * as Sequelize from 'sequelize'
4import * as url from 'url'
5import { ActivityIconObject } from '../../shared/index'
6import { Activity } from '../../shared/models/activitypub/activity' 1import { Activity } from '../../shared/models/activitypub/activity'
7import { ActivityPubActor } from '../../shared/models/activitypub/activitypub-actor'
8import { VideoChannelObject } from '../../shared/models/activitypub/objects/video-channel-object'
9import { ResultList } from '../../shared/models/result-list.model' 2import { ResultList } from '../../shared/models/result-list.model'
10import { database as db, REMOTE_SCHEME } from '../initializers'
11import { ACTIVITY_PUB, CONFIG, STATIC_PATHS } from '../initializers/constants'
12import { videoChannelActivityObjectToDBAttributes } from '../lib/activitypub/process/misc'
13import { sendVideoAnnounce } from '../lib/activitypub/send/send-announce'
14import { sendVideoChannelAnnounce } from '../lib/index'
15import { AccountFollowInstance } from '../models/account/account-follow-interface'
16import { AccountInstance } from '../models/account/account-interface' 3import { AccountInstance } from '../models/account/account-interface'
17import { VideoAbuseInstance } from '../models/video/video-abuse-interface'
18import { VideoChannelInstance } from '../models/video/video-channel-interface'
19import { VideoInstance } from '../models/video/video-interface'
20import { isRemoteAccountValid } from './custom-validators'
21import { logger } from './logger'
22import { signObject } from './peertube-crypto' 4import { signObject } from './peertube-crypto'
23import { doRequest, doRequestAndSaveToFile } from './requests'
24import { getServerAccount } from './utils'
25import { isVideoChannelObjectValid } from './custom-validators/activitypub/video-channels'
26
27function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObject) {
28 const thumbnailName = video.getThumbnailName()
29 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName)
30
31 const options = {
32 method: 'GET',
33 uri: icon.url
34 }
35 return doRequestAndSaveToFile(options, thumbnailPath)
36}
37
38async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) {
39 const serverAccount = await getServerAccount()
40
41 await db.VideoChannelShare.create({
42 accountId: serverAccount.id,
43 videoChannelId: videoChannel.id
44 }, { transaction: t })
45
46 return sendVideoChannelAnnounce(serverAccount, videoChannel, t)
47}
48
49async function shareVideoByServer (video: VideoInstance, t: Sequelize.Transaction) {
50 const serverAccount = await getServerAccount()
51
52 await db.VideoShare.create({
53 accountId: serverAccount.id,
54 videoId: video.id
55 }, { transaction: t })
56
57 return sendVideoAnnounce(serverAccount, video, t)
58}
59
60function getVideoActivityPubUrl (video: VideoInstance) {
61 return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid
62}
63
64function getVideoChannelActivityPubUrl (videoChannel: VideoChannelInstance) {
65 return CONFIG.WEBSERVER.URL + '/video-channels/' + videoChannel.uuid
66}
67
68function getAccountActivityPubUrl (accountName: string) {
69 return CONFIG.WEBSERVER.URL + '/account/' + accountName
70}
71
72function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseInstance) {
73 return CONFIG.WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
74}
75
76function getAccountFollowActivityPubUrl (accountFollow: AccountFollowInstance) {
77 const me = accountFollow.AccountFollower
78 const following = accountFollow.AccountFollowing
79
80 return me.url + '#follows/' + following.id
81}
82
83function getAccountFollowAcceptActivityPubUrl (accountFollow: AccountFollowInstance) {
84 const follower = accountFollow.AccountFollower
85 const me = accountFollow.AccountFollowing
86
87 return follower.url + '#accepts/follows/' + me.id
88}
89
90function getAnnounceActivityPubUrl (originalUrl: string, byAccount: AccountInstance) {
91 return originalUrl + '#announces/' + byAccount.id
92}
93
94function getUpdateActivityPubUrl (originalUrl: string, updatedAt: string) {
95 return originalUrl + '#updates/' + updatedAt
96}
97
98function getUndoActivityPubUrl (originalUrl: string) {
99 return originalUrl + '/undo'
100}
101
102async function getOrCreateAccount (accountUrl: string) {
103 let account = await db.Account.loadByUrl(accountUrl)
104
105 // We don't have this account in our database, fetch it on remote
106 if (!account) {
107 const res = await fetchRemoteAccountAndCreateServer(accountUrl)
108 if (res === undefined) throw new Error('Cannot fetch remote account.')
109
110 // Save our new account in database
111 account = await res.account.save()
112 }
113
114 return account
115}
116
117async function getOrCreateVideoChannel (ownerAccount: AccountInstance, videoChannelUrl: string) {
118 let videoChannel = await db.VideoChannel.loadByUrl(videoChannelUrl)
119
120 // We don't have this account in our database, fetch it on remote
121 if (!videoChannel) {
122 videoChannel = await fetchRemoteVideoChannel(ownerAccount, videoChannelUrl)
123 if (videoChannel === undefined) throw new Error('Cannot fetch remote video channel.')
124
125 // Save our new video channel in database
126 await videoChannel.save()
127 }
128
129 return videoChannel
130}
131
132async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
133 const options = {
134 uri: accountUrl,
135 method: 'GET',
136 headers: {
137 'Accept': ACTIVITY_PUB.ACCEPT_HEADER
138 }
139 }
140
141 logger.info('Fetching remote account %s.', accountUrl)
142
143 let requestResult
144 try {
145 requestResult = await doRequest(options)
146 } catch (err) {
147 logger.warn('Cannot fetch remote account %s.', accountUrl, err)
148 return undefined
149 }
150
151 const accountJSON: ActivityPubActor = JSON.parse(requestResult.body)
152 if (isRemoteAccountValid(accountJSON) === false) {
153 logger.debug('Remote account JSON is not valid.', { accountJSON })
154 return undefined
155 }
156
157 const followersCount = await fetchAccountCount(accountJSON.followers)
158 const followingCount = await fetchAccountCount(accountJSON.following)
159
160 const account = db.Account.build({
161 uuid: accountJSON.uuid,
162 name: accountJSON.preferredUsername,
163 url: accountJSON.url,
164 publicKey: accountJSON.publicKey.publicKeyPem,
165 privateKey: null,
166 followersCount: followersCount,
167 followingCount: followingCount,
168 inboxUrl: accountJSON.inbox,
169 outboxUrl: accountJSON.outbox,
170 sharedInboxUrl: accountJSON.endpoints.sharedInbox,
171 followersUrl: accountJSON.followers,
172 followingUrl: accountJSON.following
173 })
174
175 const accountHost = url.parse(account.url).host
176 const serverOptions = {
177 where: {
178 host: accountHost
179 },
180 defaults: {
181 host: accountHost
182 }
183 }
184 const [ server ] = await db.Server.findOrCreate(serverOptions)
185 account.set('serverId', server.id)
186
187 return { account, server }
188}
189
190async function fetchRemoteVideoChannel (ownerAccount: AccountInstance, videoChannelUrl: string) {
191 const options = {
192 uri: videoChannelUrl,
193 method: 'GET',
194 headers: {
195 'Accept': ACTIVITY_PUB.ACCEPT_HEADER
196 }
197 }
198
199 logger.info('Fetching remote video channel %s.', videoChannelUrl)
200
201 let requestResult
202 try {
203 requestResult = await doRequest(options)
204 } catch (err) {
205 logger.warn('Cannot fetch remote video channel %s.', videoChannelUrl, err)
206 return undefined
207 }
208
209 const videoChannelJSON: VideoChannelObject = JSON.parse(requestResult.body)
210 if (isVideoChannelObjectValid(videoChannelJSON) === false) {
211 logger.debug('Remote video channel JSON is not valid.', { videoChannelJSON })
212 return undefined
213 }
214
215 const videoChannelAttributes = videoChannelActivityObjectToDBAttributes(videoChannelJSON, ownerAccount)
216 const videoChannel = db.VideoChannel.build(videoChannelAttributes)
217 videoChannel.Account = ownerAccount
218
219 return videoChannel
220}
221
222function fetchRemoteVideoPreview (video: VideoInstance) {
223 // FIXME: use url
224 const host = video.VideoChannel.Account.Server.host
225 const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName())
226
227 return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
228}
229
230async function fetchRemoteVideoDescription (video: VideoInstance) {
231 // FIXME: use url
232 const host = video.VideoChannel.Account.Server.host
233 const path = video.getDescriptionPath()
234 const options = {
235 uri: REMOTE_SCHEME.HTTP + '://' + host + path,
236 json: true
237 }
238
239 const { body } = await doRequest(options)
240 return body.description ? body.description : ''
241}
242 5
243function activityPubContextify <T> (data: T) { 6function activityPubContextify <T> (data: T) {
244 return Object.assign(data,{ 7 return Object.assign(data,{
@@ -289,43 +52,7 @@ function buildSignedActivity (byAccount: AccountInstance, data: Object) {
289// --------------------------------------------------------------------------- 52// ---------------------------------------------------------------------------
290 53
291export { 54export {
292 fetchRemoteAccountAndCreateServer,
293 activityPubContextify, 55 activityPubContextify,
294 activityPubCollectionPagination, 56 activityPubCollectionPagination,
295 generateThumbnailFromUrl, 57 buildSignedActivity
296 getOrCreateAccount,
297 fetchRemoteVideoPreview,
298 fetchRemoteVideoDescription,
299 shareVideoChannelByServer,
300 shareVideoByServer,
301 getOrCreateVideoChannel,
302 buildSignedActivity,
303 getVideoActivityPubUrl,
304 getVideoChannelActivityPubUrl,
305 getAccountActivityPubUrl,
306 getVideoAbuseActivityPubUrl,
307 getAccountFollowActivityPubUrl,
308 getAccountFollowAcceptActivityPubUrl,
309 getAnnounceActivityPubUrl,
310 getUpdateActivityPubUrl,
311 getUndoActivityPubUrl
312}
313
314// ---------------------------------------------------------------------------
315
316async function fetchAccountCount (url: string) {
317 const options = {
318 uri: url,
319 method: 'GET'
320 }
321
322 let requestResult
323 try {
324 requestResult = await doRequest(options)
325 } catch (err) {
326 logger.warn('Cannot fetch remote account count %s.', url, err)
327 return undefined
328 }
329
330 return requestResult.totalItems ? requestResult.totalItems : 0
331} 58}
diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts
index 31417e728..b7408c845 100644
--- a/server/helpers/webfinger.ts
+++ b/server/helpers/webfinger.ts
@@ -1,9 +1,9 @@
1import * as WebFinger from 'webfinger.js' 1import * as WebFinger from 'webfinger.js'
2import { WebFingerData } from '../../shared'
2 3
3import { isTestInstance } from './core-utils' 4import { isTestInstance } from './core-utils'
4import { isActivityPubUrlValid } from './custom-validators' 5import { isActivityPubUrlValid } from './custom-validators'
5import { WebFingerData } from '../../shared' 6import { fetchRemoteAccountAndCreateServer } from '../lib/activitypub/account'
6import { fetchRemoteAccountAndCreateServer } from './activitypub'
7 7
8const webfinger = new WebFinger({ 8const webfinger = new WebFinger({
9 webfist_fallback: false, 9 webfist_fallback: false,
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}
diff --git a/server/lib/cache/videos-preview-cache.ts b/server/lib/cache/videos-preview-cache.ts
index 0570f51e8..7f352f361 100644
--- a/server/lib/cache/videos-preview-cache.ts
+++ b/server/lib/cache/videos-preview-cache.ts
@@ -3,8 +3,9 @@ import { join } from 'path'
3import { createWriteStream } from 'fs' 3import { createWriteStream } from 'fs'
4 4
5import { database as db, CONFIG, CACHE } from '../../initializers' 5import { database as db, CONFIG, CACHE } from '../../initializers'
6import { logger, unlinkPromise, fetchRemoteVideoPreview } from '../../helpers' 6import { logger, unlinkPromise } from '../../helpers'
7import { VideoInstance } from '../../models' 7import { VideoInstance } from '../../models'
8import { fetchRemoteVideoPreview } from '../activitypub/videos'
8 9
9class VideosPreviewCache { 10class VideosPreviewCache {
10 11
diff --git a/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts
index f26110973..e65ab3ee1 100644
--- a/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts
+++ b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts
@@ -1,13 +1,11 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { computeResolutionsToTranscode, logger } from '../../../helpers' 2import { computeResolutionsToTranscode, logger } from '../../../helpers'
3
4import { database as db } from '../../../initializers/database' 3import { database as db } from '../../../initializers/database'
5import { VideoInstance } from '../../../models' 4import { VideoInstance } from '../../../models'
6 5import { sendAddVideo } from '../../activitypub/send/send-add'
7import { JobScheduler } from '../job-scheduler' 6import { JobScheduler } from '../job-scheduler'
8import { TranscodingJobPayload } from './transcoding-job-scheduler' 7import { TranscodingJobPayload } from './transcoding-job-scheduler'
9import { shareVideoByServer } from '../../../helpers/activitypub' 8import { shareVideoByServer } from '../../activitypub/share'
10import { sendAddVideo } from '../../activitypub/send/send-add'
11 9
12async function process (data: TranscodingJobPayload, jobId: number) { 10async function process (data: TranscodingJobPayload, jobId: number) {
13 const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID) 11 const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID)
diff --git a/server/lib/user.ts b/server/lib/user.ts
index d54ffc916..5653d8e65 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -5,7 +5,7 @@ import { CONFIG } from '../initializers/constants'
5import { UserInstance } from '../models' 5import { UserInstance } from '../models'
6import { createVideoChannel } from './video-channel' 6import { createVideoChannel } from './video-channel'
7import { logger } from '../helpers/logger' 7import { logger } from '../helpers/logger'
8import { getAccountActivityPubUrl } from '../helpers/activitypub' 8import { getAccountActivityPubUrl } from './activitypub/url'
9 9
10async function createUserAccountAndChannel (user: UserInstance, validateUser = true) { 10async function createUserAccountAndChannel (user: UserInstance, validateUser = true) {
11 const { account, videoChannel } = await db.sequelize.transaction(async t => { 11 const { account, videoChannel } = await db.sequelize.transaction(async t => {
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts
index 5235d9cb5..a939a23d5 100644
--- a/server/lib/video-channel.ts
+++ b/server/lib/video-channel.ts
@@ -3,7 +3,7 @@ import { VideoChannelCreate } from '../../shared/models'
3import { logger } from '../helpers' 3import { logger } from '../helpers'
4import { database as db } from '../initializers' 4import { database as db } from '../initializers'
5import { AccountInstance } from '../models' 5import { AccountInstance } from '../models'
6import { getVideoChannelActivityPubUrl } from '../helpers/activitypub' 6import { getVideoChannelActivityPubUrl } from './activitypub/url'
7 7
8async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountInstance, t: Sequelize.Transaction) { 8async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountInstance, t: Sequelize.Transaction) {
9 const videoChannelData = { 9 const videoChannelData = {
diff --git a/server/middlewares/activitypub.ts b/server/middlewares/activitypub.ts
index 8e8a3961b..29bec0c97 100644
--- a/server/middlewares/activitypub.ts
+++ b/server/middlewares/activitypub.ts
@@ -2,9 +2,9 @@ import { eachSeries } from 'async'
2import { NextFunction, Request, RequestHandler, Response } from 'express' 2import { NextFunction, Request, RequestHandler, Response } from 'express'
3import { ActivityPubSignature } from '../../shared' 3import { ActivityPubSignature } from '../../shared'
4import { isSignatureVerified, logger } from '../helpers' 4import { isSignatureVerified, logger } from '../helpers'
5import { fetchRemoteAccountAndCreateServer } from '../helpers/activitypub'
6import { database as db } from '../initializers' 5import { database as db } from '../initializers'
7import { ACTIVITY_PUB } from '../initializers/constants' 6import { ACTIVITY_PUB } from '../initializers/constants'
7import { fetchRemoteAccountAndCreateServer } from '../lib/activitypub/account'
8 8
9async function checkSignature (req: Request, res: Response, next: NextFunction) { 9async function checkSignature (req: Request, res: Response, next: NextFunction) {
10 const signatureObject: ActivityPubSignature = req.body.signature 10 const signatureObject: ActivityPubSignature = req.body.signature