plugin-helpers-builder.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import express from 'express'
  2. import { Server } from 'http'
  3. import { join } from 'path'
  4. import { buildLogger } from '@server/helpers/logger.js'
  5. import { CONFIG } from '@server/initializers/config.js'
  6. import { WEBSERVER } from '@server/initializers/constants.js'
  7. import { sequelizeTypescript } from '@server/initializers/database.js'
  8. import { AccountModel } from '@server/models/account/account.js'
  9. import { AccountBlocklistModel } from '@server/models/account/account-blocklist.js'
  10. import { getServerActor } from '@server/models/application/application.js'
  11. import { ServerModel } from '@server/models/server/server.js'
  12. import { ServerBlocklistModel } from '@server/models/server/server-blocklist.js'
  13. import { UserModel } from '@server/models/user/user.js'
  14. import { VideoModel } from '@server/models/video/video.js'
  15. import { VideoBlacklistModel } from '@server/models/video/video-blacklist.js'
  16. import { MPlugin, MVideo, UserNotificationModelForApi } from '@server/types/models/index.js'
  17. import { PeerTubeHelpers } from '@server/types/plugins/index.js'
  18. import { ffprobePromise } from '@peertube/peertube-ffmpeg'
  19. import { VideoBlacklistCreate, FileStorage } from '@peertube/peertube-models'
  20. import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist.js'
  21. import { PeerTubeSocket } from '../peertube-socket.js'
  22. import { ServerConfigManager } from '../server-config-manager.js'
  23. import { blacklistVideo, unblacklistVideo } from '../video-blacklist.js'
  24. import { VideoPathManager } from '../video-path-manager.js'
  25. function buildPluginHelpers (httpServer: Server, pluginModel: MPlugin, npmName: string): PeerTubeHelpers {
  26. const logger = buildPluginLogger(npmName)
  27. const database = buildDatabaseHelpers()
  28. const videos = buildVideosHelpers()
  29. const config = buildConfigHelpers()
  30. const server = buildServerHelpers(httpServer)
  31. const moderation = buildModerationHelpers()
  32. const plugin = buildPluginRelatedHelpers(pluginModel, npmName)
  33. const socket = buildSocketHelpers()
  34. const user = buildUserHelpers()
  35. return {
  36. logger,
  37. database,
  38. videos,
  39. config,
  40. moderation,
  41. plugin,
  42. server,
  43. socket,
  44. user
  45. }
  46. }
  47. export {
  48. buildPluginHelpers
  49. }
  50. // ---------------------------------------------------------------------------
  51. function buildPluginLogger (npmName: string) {
  52. return buildLogger(npmName)
  53. }
  54. function buildDatabaseHelpers () {
  55. return {
  56. query: sequelizeTypescript.query.bind(sequelizeTypescript)
  57. }
  58. }
  59. function buildServerHelpers (httpServer: Server) {
  60. return {
  61. getHTTPServer: () => httpServer,
  62. getServerActor: () => getServerActor()
  63. }
  64. }
  65. function buildVideosHelpers () {
  66. return {
  67. loadByUrl: (url: string) => {
  68. return VideoModel.loadByUrl(url)
  69. },
  70. loadByIdOrUUID: (id: number | string) => {
  71. return VideoModel.load(id)
  72. },
  73. loadByIdOrUUIDWithFiles: (id: number | string) => {
  74. return VideoModel.loadWithFiles(id)
  75. },
  76. removeVideo: (id: number) => {
  77. return sequelizeTypescript.transaction(async t => {
  78. const video = await VideoModel.loadFull(id, t)
  79. await video.destroy({ transaction: t })
  80. })
  81. },
  82. ffprobe: (path: string) => {
  83. return ffprobePromise(path)
  84. },
  85. getFiles: async (id: number | string) => {
  86. const video = await VideoModel.loadFull(id)
  87. if (!video) return undefined
  88. const webVideoFiles = (video.VideoFiles || []).map(f => ({
  89. path: f.storage === FileStorage.FILE_SYSTEM
  90. ? VideoPathManager.Instance.getFSVideoFileOutputPath(video, f)
  91. : null,
  92. url: f.getFileUrl(video),
  93. resolution: f.resolution,
  94. size: f.size,
  95. fps: f.fps
  96. }))
  97. const hls = video.getHLSPlaylist()
  98. const hlsVideoFiles = hls
  99. ? (video.getHLSPlaylist().VideoFiles || []).map(f => {
  100. return {
  101. path: f.storage === FileStorage.FILE_SYSTEM
  102. ? VideoPathManager.Instance.getFSVideoFileOutputPath(hls, f)
  103. : null,
  104. url: f.getFileUrl(video),
  105. resolution: f.resolution,
  106. size: f.size,
  107. fps: f.fps
  108. }
  109. })
  110. : []
  111. const thumbnails = video.Thumbnails.map(t => ({
  112. type: t.type,
  113. url: t.getOriginFileUrl(video),
  114. path: t.getPath()
  115. }))
  116. return {
  117. webtorrent: { // TODO: remove in v7
  118. videoFiles: webVideoFiles
  119. },
  120. webVideo: {
  121. videoFiles: webVideoFiles
  122. },
  123. hls: {
  124. videoFiles: hlsVideoFiles
  125. },
  126. thumbnails
  127. }
  128. }
  129. }
  130. }
  131. function buildModerationHelpers () {
  132. return {
  133. blockServer: async (options: { byAccountId: number, hostToBlock: string }) => {
  134. const serverToBlock = await ServerModel.loadOrCreateByHost(options.hostToBlock)
  135. const user = await UserModel.loadByAccountId(options.byAccountId)
  136. await addServerInBlocklist({
  137. byAccountId: options.byAccountId,
  138. targetServerId: serverToBlock.id,
  139. removeNotificationOfUserId: user?.id
  140. })
  141. },
  142. unblockServer: async (options: { byAccountId: number, hostToUnblock: string }) => {
  143. const serverBlock = await ServerBlocklistModel.loadByAccountAndHost(options.byAccountId, options.hostToUnblock)
  144. if (!serverBlock) return
  145. await removeServerFromBlocklist(serverBlock)
  146. },
  147. blockAccount: async (options: { byAccountId: number, handleToBlock: string }) => {
  148. const accountToBlock = await AccountModel.loadByNameWithHost(options.handleToBlock)
  149. if (!accountToBlock) return
  150. const user = await UserModel.loadByAccountId(options.byAccountId)
  151. await addAccountInBlocklist({
  152. byAccountId: options.byAccountId,
  153. targetAccountId: accountToBlock.id,
  154. removeNotificationOfUserId: user?.id
  155. })
  156. },
  157. unblockAccount: async (options: { byAccountId: number, handleToUnblock: string }) => {
  158. const targetAccount = await AccountModel.loadByNameWithHost(options.handleToUnblock)
  159. if (!targetAccount) return
  160. const accountBlock = await AccountBlocklistModel.loadByAccountAndTarget(options.byAccountId, targetAccount.id)
  161. if (!accountBlock) return
  162. await removeAccountFromBlocklist(accountBlock)
  163. },
  164. blacklistVideo: async (options: { videoIdOrUUID: number | string, createOptions: VideoBlacklistCreate }) => {
  165. const video = await VideoModel.loadFull(options.videoIdOrUUID)
  166. if (!video) return
  167. await blacklistVideo(video, options.createOptions)
  168. },
  169. unblacklistVideo: async (options: { videoIdOrUUID: number | string }) => {
  170. const video = await VideoModel.loadFull(options.videoIdOrUUID)
  171. if (!video) return
  172. const videoBlacklist = await VideoBlacklistModel.loadByVideoId(video.id)
  173. if (!videoBlacklist) return
  174. await unblacklistVideo(videoBlacklist, video)
  175. }
  176. }
  177. }
  178. function buildConfigHelpers () {
  179. return {
  180. getWebserverUrl () {
  181. return WEBSERVER.URL
  182. },
  183. getServerListeningConfig () {
  184. return { hostname: CONFIG.LISTEN.HOSTNAME, port: CONFIG.LISTEN.PORT }
  185. },
  186. getServerConfig () {
  187. return ServerConfigManager.Instance.getServerConfig()
  188. }
  189. }
  190. }
  191. function buildPluginRelatedHelpers (plugin: MPlugin, npmName: string) {
  192. return {
  193. getBaseStaticRoute: () => `/plugins/${plugin.name}/${plugin.version}/static/`,
  194. getBaseRouterRoute: () => `/plugins/${plugin.name}/${plugin.version}/router/`,
  195. getBaseWebSocketRoute: () => `/plugins/${plugin.name}/${plugin.version}/ws/`,
  196. getDataDirectoryPath: () => join(CONFIG.STORAGE.PLUGINS_DIR, 'data', npmName)
  197. }
  198. }
  199. function buildSocketHelpers () {
  200. return {
  201. sendNotification: (userId: number, notification: UserNotificationModelForApi) => {
  202. PeerTubeSocket.Instance.sendNotification(userId, notification)
  203. },
  204. sendVideoLiveNewState: (video: MVideo) => {
  205. PeerTubeSocket.Instance.sendVideoLiveNewState(video)
  206. }
  207. }
  208. }
  209. function buildUserHelpers () {
  210. return {
  211. loadById: (id: number) => {
  212. return UserModel.loadByIdFull(id)
  213. },
  214. getAuthUser: (res: express.Response) => {
  215. const user = res.locals.oauth?.token?.User || res.locals.videoFileToken?.user
  216. if (!user) return undefined
  217. return UserModel.loadByIdFull(user.id)
  218. }
  219. }
  220. }