index.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. import Debug from 'debug'
  2. import { DB, SubstrateEvent } from '../../../generated/indexer'
  3. import { ClassEntity } from '../../../generated/graphql-server/src/modules/class-entity/class-entity.model'
  4. import { decode } from '../decode'
  5. import {
  6. updateCategoryEntityPropertyValues,
  7. updateChannelEntityPropertyValues,
  8. updateVideoMediaEntityPropertyValues,
  9. updateVideoEntityPropertyValues,
  10. updateUserDefinedLicenseEntityPropertyValues,
  11. updateHttpMediaLocationEntityPropertyValues,
  12. updateJoystreamMediaLocationEntityPropertyValues,
  13. updateKnownLicenseEntityPropertyValues,
  14. updateLanguageEntityPropertyValues,
  15. updateVideoMediaEncodingEntityPropertyValues,
  16. updateLicenseEntityPropertyValues,
  17. updateMediaLocationEntityPropertyValues,
  18. updateFeaturedVideoEntityPropertyValues,
  19. } from './update'
  20. import {
  21. removeCategory,
  22. removeChannel,
  23. removeVideoMedia,
  24. removeVideo,
  25. removeUserDefinedLicense,
  26. removeKnownLicense,
  27. removeHttpMediaLocation,
  28. removeJoystreamMediaLocation,
  29. removeLanguage,
  30. removeVideoMediaEncoding,
  31. removeLicense,
  32. removeMediaLocation,
  33. removeFeaturedVideo,
  34. } from './remove'
  35. import {
  36. createCategory,
  37. createChannel,
  38. createVideoMedia,
  39. createVideo,
  40. createUserDefinedLicense,
  41. createKnownLicense,
  42. createHttpMediaLocation,
  43. createJoystreamMediaLocation,
  44. createLanguage,
  45. createVideoMediaEncoding,
  46. createBlockOrGetFromDatabase,
  47. createFeaturedVideo,
  48. } from './create'
  49. import {
  50. categoryPropertyNamesWithId,
  51. channelPropertyNamesWithId,
  52. httpMediaLocationPropertyNamesWithId,
  53. joystreamMediaLocationPropertyNamesWithId,
  54. knownLicensePropertyNamesWIthId,
  55. languagePropertyNamesWIthId,
  56. userDefinedLicensePropertyNamesWithId,
  57. videoMediaEncodingPropertyNamesWithId,
  58. videoPropertyNamesWithId,
  59. contentDirectoryClassNamesWithId,
  60. ContentDirectoryKnownClasses,
  61. featuredVideoPropertyNamesWithId,
  62. } from '../content-dir-consts'
  63. import {
  64. IChannel,
  65. ICategory,
  66. IKnownLicense,
  67. IUserDefinedLicense,
  68. IJoystreamMediaLocation,
  69. IHttpMediaLocation,
  70. IVideoMedia,
  71. IVideo,
  72. ILanguage,
  73. IVideoMediaEncoding,
  74. IDBBlockId,
  75. IWhereCond,
  76. IEntity,
  77. ILicense,
  78. IMediaLocation,
  79. IFeaturedVideo,
  80. } from '../../types'
  81. import { getOrCreate } from '../get-or-create'
  82. const debug = Debug('mappings:content-directory')
  83. // eslint-disable-next-line @typescript-eslint/naming-convention
  84. async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: SubstrateEvent): Promise<void> {
  85. if (event.extrinsic && event.extrinsic.method === 'transaction') return
  86. debug(`EntitySchemaSupportAdded event: ${JSON.stringify(event)}`)
  87. const { blockNumber: block } = event
  88. const entityId = decode.stringIfyEntityId(event)
  89. const classEntity = await db.get(ClassEntity, { where: { id: entityId } })
  90. if (classEntity === undefined) {
  91. console.log(`Class not found for the EntityId: ${entityId}`)
  92. return
  93. }
  94. const cls = contentDirectoryClassNamesWithId.find((c) => c.classId === classEntity.classId)
  95. if (cls === undefined) {
  96. console.log('Not recognized class')
  97. return
  98. }
  99. const arg: IDBBlockId = { db, block, id: entityId }
  100. switch (cls.name) {
  101. case ContentDirectoryKnownClasses.CHANNEL:
  102. await createChannel(
  103. arg,
  104. new Map<string, IEntity[]>(),
  105. decode.setProperties<IChannel>(event, channelPropertyNamesWithId),
  106. 0 // ignored
  107. )
  108. break
  109. case ContentDirectoryKnownClasses.CATEGORY:
  110. await createCategory(arg, decode.setProperties<ICategory>(event, categoryPropertyNamesWithId))
  111. break
  112. case ContentDirectoryKnownClasses.KNOWNLICENSE:
  113. await createKnownLicense(arg, decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId))
  114. break
  115. case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
  116. await createUserDefinedLicense(
  117. arg,
  118. decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId)
  119. )
  120. break
  121. case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
  122. await createJoystreamMediaLocation(
  123. arg,
  124. decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId)
  125. )
  126. break
  127. case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
  128. await createHttpMediaLocation(
  129. arg,
  130. decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId)
  131. )
  132. break
  133. case ContentDirectoryKnownClasses.VIDEOMEDIA:
  134. await createVideoMedia(
  135. arg,
  136. new Map<string, IEntity[]>(),
  137. decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
  138. 0 // ignored
  139. )
  140. break
  141. case ContentDirectoryKnownClasses.VIDEO:
  142. await createVideo(
  143. arg,
  144. new Map<string, IEntity[]>(),
  145. decode.setProperties<IVideo>(event, videoPropertyNamesWithId),
  146. 0 // ignored
  147. )
  148. break
  149. case ContentDirectoryKnownClasses.LANGUAGE:
  150. await createLanguage(arg, decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId))
  151. break
  152. case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
  153. await createVideoMediaEncoding(
  154. arg,
  155. decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
  156. )
  157. break
  158. case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
  159. await createFeaturedVideo(
  160. arg,
  161. new Map<string, IEntity[]>(),
  162. decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
  163. 0
  164. )
  165. break
  166. default:
  167. throw new Error(`Unknown class name: ${cls.name}`)
  168. }
  169. }
  170. // eslint-disable-next-line @typescript-eslint/naming-convention
  171. async function contentDirectory_EntityRemoved(db: DB, event: SubstrateEvent): Promise<void> {
  172. debug(`EntityRemoved event: ${JSON.stringify(event)}`)
  173. const entityId = decode.stringIfyEntityId(event)
  174. const where: IWhereCond = { where: { id: entityId } }
  175. const classEntity = await db.get(ClassEntity, where)
  176. if (classEntity === undefined) {
  177. console.log(`Class not found for the EntityId: ${entityId}`)
  178. return
  179. }
  180. const cls = contentDirectoryClassNamesWithId.find((c) => c.classId === classEntity.classId)
  181. if (cls === undefined) {
  182. console.log('Unknown class')
  183. return
  184. }
  185. switch (cls.name) {
  186. case ContentDirectoryKnownClasses.CHANNEL:
  187. await removeChannel(db, where)
  188. break
  189. case ContentDirectoryKnownClasses.CATEGORY:
  190. await removeCategory(db, where)
  191. break
  192. case ContentDirectoryKnownClasses.KNOWNLICENSE:
  193. await removeKnownLicense(db, where)
  194. break
  195. case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
  196. await removeUserDefinedLicense(db, where)
  197. break
  198. case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
  199. await removeJoystreamMediaLocation(db, where)
  200. break
  201. case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
  202. await removeHttpMediaLocation(db, where)
  203. break
  204. case ContentDirectoryKnownClasses.VIDEOMEDIA:
  205. await removeVideoMedia(db, where)
  206. break
  207. case ContentDirectoryKnownClasses.VIDEO:
  208. await removeVideo(db, where)
  209. break
  210. case ContentDirectoryKnownClasses.LANGUAGE:
  211. await removeLanguage(db, where)
  212. break
  213. case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
  214. await removeVideoMediaEncoding(db, where)
  215. break
  216. case ContentDirectoryKnownClasses.LICENSE:
  217. await removeLicense(db, where)
  218. break
  219. case ContentDirectoryKnownClasses.MEDIALOCATION:
  220. await removeMediaLocation(db, where)
  221. break
  222. case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
  223. await removeFeaturedVideo(db, where)
  224. break
  225. default:
  226. throw new Error(`Unknown class name: ${cls.name}`)
  227. }
  228. }
  229. // eslint-disable-next-line @typescript-eslint/naming-convention
  230. async function contentDirectory_EntityCreated(db: DB, event: SubstrateEvent): Promise<void> {
  231. if (event.extrinsic && event.extrinsic.method === 'transaction') return
  232. debug(`EntityCreated event: ${JSON.stringify(event)}`)
  233. const c = decode.getClassEntity(event)
  234. const classEntity = new ClassEntity()
  235. classEntity.classId = c.classId
  236. classEntity.id = c.entityId.toString()
  237. classEntity.version = event.blockNumber
  238. classEntity.happenedIn = await createBlockOrGetFromDatabase(db, event.blockNumber)
  239. await db.save<ClassEntity>(classEntity)
  240. await getOrCreate.nextEntityId(db, c.entityId + 1)
  241. }
  242. // eslint-disable-next-line @typescript-eslint/naming-convention
  243. async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: SubstrateEvent): Promise<void> {
  244. const { extrinsic } = event
  245. if (extrinsic && extrinsic.method === 'transaction') return
  246. if (extrinsic === undefined) throw Error(`Extrinsic data not found for event: ${event.id}`)
  247. debug(`EntityPropertyValuesUpdated event: ${JSON.stringify(event)}`)
  248. const { 2: newPropertyValues } = extrinsic.args
  249. const entityId = decode.stringIfyEntityId(event)
  250. const ce = await db.get(ClassEntity, { where: { id: entityId } })
  251. if (ce === undefined) throw Error(`Class not found for the entity id: ${entityId}`)
  252. const cls = contentDirectoryClassNamesWithId.find((c) => c.classId === ce.classId)
  253. if (cls === undefined) throw Error(`Not known class id: ${ce.classId}`)
  254. const where: IWhereCond = { where: { id: entityId } }
  255. // TODO: change setProperties method signature to accecpt SubstrateExtrinsic, then remove the following
  256. // line. The reason we push the same arg is beacuse of the setProperties method check the 3rd indices
  257. // to get properties values
  258. extrinsic.args.push(newPropertyValues)
  259. switch (cls.name) {
  260. case ContentDirectoryKnownClasses.CHANNEL:
  261. updateChannelEntityPropertyValues(db, where, decode.setProperties<IChannel>(event, channelPropertyNamesWithId), 0)
  262. break
  263. case ContentDirectoryKnownClasses.CATEGORY:
  264. await updateCategoryEntityPropertyValues(
  265. db,
  266. where,
  267. decode.setProperties<ICategory>(event, categoryPropertyNamesWithId)
  268. )
  269. break
  270. case ContentDirectoryKnownClasses.KNOWNLICENSE:
  271. await updateKnownLicenseEntityPropertyValues(
  272. db,
  273. where,
  274. decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId)
  275. )
  276. break
  277. case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
  278. await updateUserDefinedLicenseEntityPropertyValues(
  279. db,
  280. where,
  281. decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId)
  282. )
  283. break
  284. case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
  285. await updateJoystreamMediaLocationEntityPropertyValues(
  286. db,
  287. where,
  288. decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId)
  289. )
  290. break
  291. case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
  292. await updateHttpMediaLocationEntityPropertyValues(
  293. db,
  294. where,
  295. decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId)
  296. )
  297. break
  298. case ContentDirectoryKnownClasses.VIDEOMEDIA:
  299. await updateVideoMediaEntityPropertyValues(
  300. db,
  301. where,
  302. decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
  303. 0
  304. )
  305. break
  306. case ContentDirectoryKnownClasses.VIDEO:
  307. await updateVideoEntityPropertyValues(db, where, decode.setProperties<IVideo>(event, videoPropertyNamesWithId), 0)
  308. break
  309. case ContentDirectoryKnownClasses.LANGUAGE:
  310. await updateLanguageEntityPropertyValues(
  311. db,
  312. where,
  313. decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId)
  314. )
  315. break
  316. case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
  317. await updateVideoMediaEncodingEntityPropertyValues(
  318. db,
  319. where,
  320. decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
  321. )
  322. break
  323. case ContentDirectoryKnownClasses.LICENSE:
  324. await updateLicenseEntityPropertyValues(
  325. db,
  326. where,
  327. decode.setProperties<ILicense>(event, videoMediaEncodingPropertyNamesWithId),
  328. 0
  329. )
  330. break
  331. case ContentDirectoryKnownClasses.MEDIALOCATION:
  332. await updateMediaLocationEntityPropertyValues(
  333. db,
  334. where,
  335. decode.setProperties<IMediaLocation>(event, videoMediaEncodingPropertyNamesWithId),
  336. 0
  337. )
  338. break
  339. case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
  340. await updateFeaturedVideoEntityPropertyValues(
  341. db,
  342. where,
  343. decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
  344. 0
  345. )
  346. break
  347. default:
  348. throw new Error(`Unknown class name: ${cls.name}`)
  349. }
  350. }
  351. export {
  352. contentDirectory_EntityCreated,
  353. contentDirectory_EntityRemoved,
  354. contentDirectory_EntitySchemaSupportAdded,
  355. contentDirectory_EntityPropertyValuesUpdated,
  356. }