]>
Commit | Line | Data |
---|---|---|
9de33c6b | 1 | import { logger, loggerTagsFactory } from '@server/helpers/logger' |
4ead40e7 | 2 | import { PromiseCache } from '@server/helpers/promise-cache' |
136d7efd | 3 | import { PeerTubeRequestError } from '@server/helpers/requests' |
868fce62 | 4 | import { ActorLoadByUrlType } from '@server/lib/model-loaders' |
136d7efd C |
5 | import { ActorModel } from '@server/models/actor/actor' |
6 | import { MActorAccountChannelId, MActorFull } from '@server/types/models' | |
c0e8b12e | 7 | import { HttpStatusCode } from '@shared/models' |
136d7efd C |
8 | import { fetchRemoteActor } from './shared' |
9 | import { APActorUpdater } from './updater' | |
10363c74 | 10 | import { getUrlFromWebfinger } from './webfinger' |
136d7efd | 11 | |
4ead40e7 C |
12 | type RefreshResult <T> = Promise<{ actor: T | MActorFull, refreshed: boolean }> |
13 | ||
14 | type RefreshOptions <T> = { | |
15 | actor: T | |
868fce62 | 16 | fetchedType: ActorLoadByUrlType |
4ead40e7 C |
17 | } |
18 | ||
19 | const promiseCache = new PromiseCache(doRefresh, (options: RefreshOptions<MActorFull | MActorAccountChannelId>) => options.actor.url) | |
20 | ||
21 | function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannelId> (options: RefreshOptions<T>): RefreshResult <T> { | |
22 | const actorArg = options.actor | |
23 | if (!actorArg.isOutdated()) return Promise.resolve({ actor: actorArg, refreshed: false }) | |
24 | ||
25 | return promiseCache.run(options) | |
26 | } | |
27 | ||
28 | export { | |
29 | refreshActorIfNeeded | |
30 | } | |
31 | ||
32 | // --------------------------------------------------------------------------- | |
33 | ||
34 | async function doRefresh <T extends MActorFull | MActorAccountChannelId> (options: RefreshOptions<T>): RefreshResult <MActorFull> { | |
35 | const { actor: actorArg, fetchedType } = options | |
136d7efd C |
36 | |
37 | // We need more attributes | |
38 | const actor = fetchedType === 'all' | |
39 | ? actorArg as MActorFull | |
40 | : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url) | |
41 | ||
9de33c6b C |
42 | const lTags = loggerTagsFactory('ap', 'actor', 'refresh', actor.url) |
43 | ||
44 | logger.info('Refreshing actor %s.', actor.url, lTags()) | |
45 | ||
136d7efd C |
46 | try { |
47 | const actorUrl = await getActorUrl(actor) | |
48 | const { actorObject } = await fetchRemoteActor(actorUrl) | |
49 | ||
50 | if (actorObject === undefined) { | |
b0f42042 | 51 | logger.info('Cannot fetch remote actor %s in refresh actor.', actorUrl) |
136d7efd C |
52 | return { actor, refreshed: false } |
53 | } | |
54 | ||
55 | const updater = new APActorUpdater(actorObject, actor) | |
56 | await updater.update() | |
57 | ||
58 | return { refreshed: true, actor } | |
59 | } catch (err) { | |
60 | if ((err as PeerTubeRequestError).statusCode === HttpStatusCode.NOT_FOUND_404) { | |
9de33c6b | 61 | logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url, lTags()) |
136d7efd C |
62 | |
63 | actor.Account | |
64 | ? await actor.Account.destroy() | |
65 | : await actor.VideoChannel.destroy() | |
66 | ||
67 | return { actor: undefined, refreshed: false } | |
68 | } | |
69 | ||
b0f42042 | 70 | logger.info('Cannot refresh actor %s.', actor.url, { err, ...lTags() }) |
136d7efd C |
71 | return { actor, refreshed: false } |
72 | } | |
73 | } | |
74 | ||
136d7efd C |
75 | function getActorUrl (actor: MActorFull) { |
76 | return getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost()) | |
77 | .catch(err => { | |
1cc97746 | 78 | logger.warn('Cannot get actor URL from webfinger, keeping the old one.', { err }) |
136d7efd C |
79 | return actor.url |
80 | }) | |
81 | } |