From 744d0eca195bce7dafeb4a958d0eb3c0046be32d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 14 Jan 2019 11:30:15 +0100 Subject: Refresh remote actors on GET enpoints --- server/lib/activitypub/actor.ts | 111 +++++++++++---------- server/lib/activitypub/videos.ts | 2 +- .../job-queue/handlers/activitypub-refresher.ts | 25 +++-- 3 files changed, 77 insertions(+), 61 deletions(-) (limited to 'server/lib') diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index f80296725..d728c81d1 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts @@ -201,6 +201,62 @@ async function addFetchOutboxJob (actor: ActorModel) { return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) } +async function refreshActorIfNeeded ( + actorArg: ActorModel, + fetchedType: ActorFetchByUrlType +): Promise<{ actor: ActorModel, refreshed: boolean }> { + if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false } + + // We need more attributes + const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url) + + try { + const actorUrl = await getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost()) + const { result, statusCode } = await fetchRemoteActor(actorUrl) + + if (statusCode === 404) { + logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url) + actor.Account ? actor.Account.destroy() : actor.VideoChannel.destroy() + return { actor: undefined, refreshed: false } + } + + if (result === undefined) { + logger.warn('Cannot fetch remote actor in refresh actor.') + return { actor, refreshed: false } + } + + return sequelizeTypescript.transaction(async t => { + updateInstanceWithAnother(actor, result.actor) + + if (result.avatarName !== undefined) { + await updateActorAvatarInstance(actor, result.avatarName, t) + } + + // Force update + actor.setDataValue('updatedAt', new Date()) + await actor.save({ transaction: t }) + + if (actor.Account) { + actor.Account.set('name', result.name) + actor.Account.set('description', result.summary) + + await actor.Account.save({ transaction: t }) + } else if (actor.VideoChannel) { + actor.VideoChannel.set('name', result.name) + actor.VideoChannel.set('description', result.summary) + actor.VideoChannel.set('support', result.support) + + await actor.VideoChannel.save({ transaction: t }) + } + + return { refreshed: true, actor } + }) + } catch (err) { + logger.warn('Cannot refresh actor.', { err }) + return { actor, refreshed: false } + } +} + export { getOrCreateActorAndServerAndModel, buildActorInstance, @@ -208,6 +264,7 @@ export { fetchActorTotalItems, fetchAvatarIfExists, updateActorInstance, + refreshActorIfNeeded, updateActorAvatarInstance, addFetchOutboxJob } @@ -373,58 +430,4 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu return videoChannelCreated } -async function refreshActorIfNeeded ( - actorArg: ActorModel, - fetchedType: ActorFetchByUrlType -): Promise<{ actor: ActorModel, refreshed: boolean }> { - if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false } - - // We need more attributes - const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url) - - try { - const actorUrl = await getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost()) - const { result, statusCode } = await fetchRemoteActor(actorUrl) - - if (statusCode === 404) { - logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url) - actor.Account ? actor.Account.destroy() : actor.VideoChannel.destroy() - return { actor: undefined, refreshed: false } - } - - if (result === undefined) { - logger.warn('Cannot fetch remote actor in refresh actor.') - return { actor, refreshed: false } - } - return sequelizeTypescript.transaction(async t => { - updateInstanceWithAnother(actor, result.actor) - - if (result.avatarName !== undefined) { - await updateActorAvatarInstance(actor, result.avatarName, t) - } - - // Force update - actor.setDataValue('updatedAt', new Date()) - await actor.save({ transaction: t }) - - if (actor.Account) { - actor.Account.set('name', result.name) - actor.Account.set('description', result.summary) - - await actor.Account.save({ transaction: t }) - } else if (actor.VideoChannel) { - actor.VideoChannel.set('name', result.name) - actor.VideoChannel.set('description', result.summary) - actor.VideoChannel.set('support', result.support) - - await actor.VideoChannel.save({ transaction: t }) - } - - return { refreshed: true, actor } - }) - } catch (err) { - logger.warn('Cannot refresh actor.', { err }) - return { actor, refreshed: false } - } -} diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 893768769..cbdd981c5 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts @@ -179,7 +179,7 @@ async function getOrCreateVideoAndAccountAndChannel (options: { } if (syncParam.refreshVideo === true) videoFromDatabase = await refreshVideoIfNeeded(refreshOptions) - else await JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', videoUrl: videoFromDatabase.url } }) + else await JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: videoFromDatabase.url } }) } return { video: videoFromDatabase, created: false } diff --git a/server/lib/job-queue/handlers/activitypub-refresher.ts b/server/lib/job-queue/handlers/activitypub-refresher.ts index 671b0f487..454b975fe 100644 --- a/server/lib/job-queue/handlers/activitypub-refresher.ts +++ b/server/lib/job-queue/handlers/activitypub-refresher.ts @@ -1,30 +1,33 @@ import * as Bull from 'bull' import { logger } from '../../../helpers/logger' import { fetchVideoByUrl } from '../../../helpers/video' -import { refreshVideoIfNeeded } from '../../activitypub' +import { refreshVideoIfNeeded, refreshActorIfNeeded } from '../../activitypub' +import { ActorModel } from '../../../models/activitypub/actor' export type RefreshPayload = { - videoUrl: string - type: 'video' + type: 'video' | 'actor' + url: string } async function refreshAPObject (job: Bull.Job) { const payload = job.data as RefreshPayload - logger.info('Processing AP refresher in job %d for video %s.', job.id, payload.videoUrl) + logger.info('Processing AP refresher in job %d for %s.', job.id, payload.url) - if (payload.type === 'video') return refreshAPVideo(payload.videoUrl) + if (payload.type === 'video') return refreshVideo(payload.url) + if (payload.type === 'actor') return refreshActor(payload.url) } // --------------------------------------------------------------------------- export { + refreshActor, refreshAPObject } // --------------------------------------------------------------------------- -async function refreshAPVideo (videoUrl: string) { +async function refreshVideo (videoUrl: string) { const fetchType = 'all' as 'all' const syncParam = { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true } @@ -39,3 +42,13 @@ async function refreshAPVideo (videoUrl: string) { await refreshVideoIfNeeded(refreshOptions) } } + +async function refreshActor (actorUrl: string) { + const fetchType = 'all' as 'all' + const actor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorUrl) + + if (actor) { + await refreshActorIfNeeded(actor, fetchType) + } + +} -- cgit v1.2.3