Init commit

This commit is contained in:
ShreejitPanchal
2026-05-19 19:56:02 +08:00
commit 6601501eff
4047 changed files with 2185372 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
import { getNodeABIVersion } from '@server/helpers/version.js'
import { CONFIG } from '@server/initializers/config.js'
import memoizee from 'memoizee'
import { AllowNull, Column, DataType, Default, DefaultScope, HasOne, IsInt, Table } from 'sequelize-typescript'
import type { PickDeep } from 'type-fest'
import { AccountModel } from '../account/account.js'
import { ActorImageModel } from '../actor/actor-image.js'
import { SequelizeModel } from '../shared/index.js'
import { UploadImageModel } from './upload-image.js'
export const getServerActor = memoizee(async function () {
const application = await ApplicationModel.load()
if (!application) throw Error('Could not load Application from database.')
const actor = application.Account.Actor
actor.Account = application.Account
const { avatars, banners } = await ActorImageModel.listActorImages(actor)
actor.Avatars = avatars
actor.Banners = banners
const uploadImages = await UploadImageModel.listByActor(actor, undefined)
actor.UploadImages = uploadImages
return actor
}, { promise: true })
type ConfigPart = PickDeep<typeof CONFIG, 'OBJECT_STORAGE.STREAMING_PLAYLISTS'>
@DefaultScope(() => ({
include: [
{
model: AccountModel,
required: true
}
]
}))
@Table({
tableName: 'application',
timestamps: false
})
export class ApplicationModel extends SequelizeModel<ApplicationModel> {
@AllowNull(false)
@Default(0)
@IsInt
@Column
declare migrationVersion: number
@AllowNull(true)
@Column
declare latestPeerTubeVersion: string
@AllowNull(false)
@Column
declare nodeVersion: string
@AllowNull(false)
@Column
declare nodeABIVersion: string
@AllowNull(true)
@Column(DataType.JSONB)
declare configPart: ConfigPart
@HasOne(() => AccountModel, {
foreignKey: {
allowNull: true
},
onDelete: 'cascade'
})
declare Account: Awaited<AccountModel>
private static lastRunConfigPart: ConfigPart
private static lastRunNodeABIVersion: string
static countTotal () {
return ApplicationModel.count()
}
static load () {
return ApplicationModel.findOne()
}
static async nodeABIChanged () {
const application = await this.load()
const nodeABIVersion = this.lastRunNodeABIVersion || application.nodeABIVersion
return nodeABIVersion !== getNodeABIVersion()
}
static async streamingPlaylistBaseUrlChanged () {
const application = await this.load()
const configPart = this.lastRunConfigPart || application.configPart
return configPart?.OBJECT_STORAGE.STREAMING_PLAYLISTS.BASE_URL !== CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS.BASE_URL
}
static async updateNodeVersionsOrConfig () {
const application = await this.load()
this.lastRunNodeABIVersion = application.nodeABIVersion
this.lastRunConfigPart = application.configPart
application.nodeABIVersion = getNodeABIVersion()
application.nodeVersion = process.version
application.configPart = {
OBJECT_STORAGE: {
STREAMING_PLAYLISTS: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS
}
}
await application.save()
}
}

View File

@@ -0,0 +1,128 @@
import { type UploadImageType_Type } from '@peertube/peertube-models'
import { MActorId, MUploadImage } from '@server/types/models/index.js'
import { remove } from 'fs-extra/esm'
import { join } from 'path'
import { Transaction } from 'sequelize'
import { AfterDestroy, AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { logger } from '../../helpers/logger.js'
import { DIRECTORIES, STATIC_PATHS, WEBSERVER } from '../../initializers/constants.js'
import { ActorModel } from '../actor/actor.js'
import { SequelizeModel } from '../shared/index.js'
// Image uploads that are not suitable for other tables actor images (avatars/banners)
// Can be used to store instance images like logos, favicons, etc.
@Table({
tableName: 'uploadImage',
indexes: [
{
fields: [ 'filename' ],
unique: true
},
{
fields: [ 'actorId', 'type', 'width' ],
unique: true
}
]
})
export class UploadImageModel extends SequelizeModel<UploadImageModel> {
@AllowNull(false)
@Column
declare filename: string
@AllowNull(true)
@Default(null)
@Column
declare height: number
@AllowNull(true)
@Default(null)
@Column
declare width: number
@AllowNull(true)
@Column
declare fileUrl: string
@AllowNull(false)
@Column
declare type: UploadImageType_Type
@CreatedAt
declare createdAt: Date
@UpdatedAt
declare updatedAt: Date
@ForeignKey(() => ActorModel)
@Column
declare actorId: number
@BelongsTo(() => ActorModel, {
foreignKey: {
allowNull: false
},
onDelete: 'CASCADE'
})
declare Actor: Awaited<ActorModel>
@AfterDestroy
static removeFile (instance: UploadImageModel) {
logger.info('Removing upload image file %s.', instance.filename)
// Don't block the transaction
instance.removeImage()
.catch(err => logger.error('Cannot remove upload image file %s.', instance.filename, { err }))
}
static listByActor (actor: MActorId, transaction: Transaction) {
const query = {
where: {
actorId: actor.id
},
transaction
}
return UploadImageModel.findAll(query)
}
static listByActorAndType (actor: MActorId, type: UploadImageType_Type, transaction: Transaction) {
const query = {
where: {
actorId: actor.id,
type
},
transaction
}
return UploadImageModel.findAll(query)
}
static getImageUrl (image: MUploadImage) {
if (!image) return undefined
return WEBSERVER.URL + image.getStaticPath()
}
static getPathOf (filename: string) {
return join(DIRECTORIES.UPLOAD_IMAGES, filename)
}
// ---------------------------------------------------------------------------
getStaticPath (this: MUploadImage) {
return join(STATIC_PATHS.UPLOAD_IMAGES, this.filename)
}
getPath () {
return UploadImageModel.getPathOf(this.filename)
}
removeImage () {
return remove(this.getPath())
}
isLocal () {
return !this.fileUrl
}
}