From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 31 Jul 2023 14:34:36 +0200 Subject: Migrate server to ESM Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports) --- server/scripts/update-host.ts | 140 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100755 server/scripts/update-host.ts (limited to 'server/scripts/update-host.ts') diff --git a/server/scripts/update-host.ts b/server/scripts/update-host.ts new file mode 100755 index 000000000..52ac4947a --- /dev/null +++ b/server/scripts/update-host.ts @@ -0,0 +1,140 @@ +import { updateTorrentMetadata } from '@server/helpers/webtorrent.js' +import { getServerActor } from '@server/models/application/application.js' +import { WEBSERVER } from '@server/initializers/constants.js' +import { initDatabaseModels } from '@server/initializers/database.js' +import { + getLocalAccountActivityPubUrl, + getLocalVideoActivityPubUrl, + getLocalVideoAnnounceActivityPubUrl, + getLocalVideoChannelActivityPubUrl, + getLocalVideoCommentActivityPubUrl +} from '@server/lib/activitypub/url.js' +import { AccountModel } from '@server/models/account/account.js' +import { ActorFollowModel } from '@server/models/actor/actor-follow.js' +import { ActorModel } from '@server/models/actor/actor.js' +import { VideoChannelModel } from '@server/models/video/video-channel.js' +import { VideoCommentModel } from '@server/models/video/video-comment.js' +import { VideoShareModel } from '@server/models/video/video-share.js' +import { VideoModel } from '@server/models/video/video.js' + +run() + .then(() => process.exit(0)) + .catch(err => { + console.error(err) + process.exit(-1) + }) + +async function run () { + await initDatabaseModels(true) + + const serverAccount = await getServerActor() + + { + const res = await ActorFollowModel.listAcceptedFollowingUrlsForApi([ serverAccount.id ], undefined) + const hasFollowing = res.total > 0 + + if (hasFollowing === true) { + throw new Error('Cannot update host because you follow other servers!') + } + } + + console.log('Updating actors.') + + const actors: ActorModel[] = await ActorModel.unscoped().findAll({ + include: [ + { + model: VideoChannelModel.unscoped(), + required: false + }, + { + model: AccountModel.unscoped(), + required: false + } + ] + }) + for (const actor of actors) { + if (actor.isOwned() === false) continue + + console.log('Updating actor ' + actor.url) + + const newUrl = actor.Account + ? getLocalAccountActivityPubUrl(actor.preferredUsername) + : getLocalVideoChannelActivityPubUrl(actor.preferredUsername) + + actor.url = newUrl + actor.inboxUrl = newUrl + '/inbox' + actor.outboxUrl = newUrl + '/outbox' + actor.sharedInboxUrl = WEBSERVER.URL + '/inbox' + actor.followersUrl = newUrl + '/followers' + actor.followingUrl = newUrl + '/following' + + await actor.save() + } + + console.log('Updating video shares.') + + const videoShares: VideoShareModel[] = await VideoShareModel.findAll({ + include: [ VideoModel.unscoped(), ActorModel.unscoped() ] + }) + for (const videoShare of videoShares) { + if (videoShare.Video.isOwned() === false) continue + + console.log('Updating video share ' + videoShare.url) + + videoShare.url = getLocalVideoAnnounceActivityPubUrl(videoShare.Actor, videoShare.Video) + await videoShare.save() + } + + console.log('Updating video comments.') + const videoComments: VideoCommentModel[] = await VideoCommentModel.findAll({ + include: [ + { + model: VideoModel.unscoped() + }, + { + model: AccountModel.unscoped(), + include: [ + { + model: ActorModel.unscoped() + } + ] + } + ] + }) + for (const comment of videoComments) { + if (comment.isOwned() === false) continue + + console.log('Updating comment ' + comment.url) + + comment.url = getLocalVideoCommentActivityPubUrl(comment.Video, comment) + await comment.save() + } + + console.log('Updating video and torrent files.') + + const ids = await VideoModel.listLocalIds() + for (const id of ids) { + const video = await VideoModel.loadFull(id) + + console.log('Updating video ' + video.uuid) + + video.url = getLocalVideoActivityPubUrl(video) + await video.save() + + for (const file of video.VideoFiles) { + console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid) + await updateTorrentMetadata(video, file) + + await file.save() + } + + const playlist = video.getHLSPlaylist() + for (const file of (playlist?.VideoFiles || [])) { + console.log('Updating fragmented torrent file %s of video %s.', file.resolution, video.uuid) + + await updateTorrentMetadata(playlist, file) + + await file.save() + } + } +} -- cgit v1.2.3