index.ts 12 KB

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