index.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. removeCategory,
  7. removeChannel,
  8. removeVideoMedia,
  9. removeVideo,
  10. removeUserDefinedLicense,
  11. removeKnownLicense,
  12. removeHttpMediaLocation,
  13. removeJoystreamMediaLocation,
  14. removeLanguage,
  15. removeVideoMediaEncoding,
  16. removeLicense,
  17. removeMediaLocation,
  18. removeFeaturedVideo,
  19. } from './remove'
  20. import { createBlockOrGetFromDatabase } from './create'
  21. import {
  22. categoryPropertyNamesWithId,
  23. channelPropertyNamesWithId,
  24. httpMediaLocationPropertyNamesWithId,
  25. joystreamMediaLocationPropertyNamesWithId,
  26. knownLicensePropertyNamesWIthId,
  27. languagePropertyNamesWIthId,
  28. userDefinedLicensePropertyNamesWithId,
  29. videoMediaEncodingPropertyNamesWithId,
  30. videoPropertyNamesWithId,
  31. ContentDirectoryKnownClasses,
  32. featuredVideoPropertyNamesWithId,
  33. licensePropertyNamesWithId,
  34. mediaLocationPropertyNamesWithId,
  35. } from '../content-dir-consts'
  36. import {
  37. IChannel,
  38. ICategory,
  39. IKnownLicense,
  40. IUserDefinedLicense,
  41. IJoystreamMediaLocation,
  42. IHttpMediaLocation,
  43. IVideoMedia,
  44. IVideo,
  45. ILanguage,
  46. IVideoMediaEncoding,
  47. IWhereCond,
  48. ILicense,
  49. IMediaLocation,
  50. IFeaturedVideo,
  51. } from '../../types'
  52. import { getOrCreate, getKnownClass } from '../get-or-create'
  53. import { createDefaultSchema } from '../default-schemas'
  54. import {
  55. addSchemaToCategory,
  56. addSchemaToChannel,
  57. addSchemaToFeaturedVideo,
  58. addSchemaToHttpMediaLocation,
  59. addSchemaToJoystreamMediaLocation,
  60. addSchemaToKnownLicense,
  61. addSchemaToLanguage,
  62. addSchemaToLicense,
  63. addSchemaToMediaLocation,
  64. addSchemaToUserDefinedLicense,
  65. addSchemaToVideo,
  66. addSchemaToVideoMedia,
  67. addSchemaToVideoMediaEncoding,
  68. } from './addSchema'
  69. import { NextEntityId } from '../../../generated/graphql-server/src/modules/next-entity-id/next-entity-id.model'
  70. const debug = Debug('mappings:content-directory')
  71. async function addSchemSupportToEntity(
  72. event: SubstrateEvent,
  73. className: string,
  74. db: DB,
  75. entityId: number,
  76. nextEntityId = 0
  77. ) {
  78. switch (className) {
  79. case ContentDirectoryKnownClasses.CHANNEL:
  80. addSchemaToChannel({
  81. db,
  82. entityId,
  83. nextEntityId,
  84. props: decode.setProperties<IChannel>(event, channelPropertyNamesWithId),
  85. })
  86. break
  87. case ContentDirectoryKnownClasses.CATEGORY:
  88. await addSchemaToCategory({
  89. db,
  90. entityId,
  91. nextEntityId,
  92. props: decode.setProperties<ICategory>(event, categoryPropertyNamesWithId),
  93. })
  94. break
  95. case ContentDirectoryKnownClasses.KNOWNLICENSE:
  96. await addSchemaToKnownLicense({
  97. db,
  98. entityId,
  99. nextEntityId,
  100. props: decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId),
  101. })
  102. break
  103. case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
  104. await addSchemaToUserDefinedLicense({
  105. db,
  106. entityId,
  107. nextEntityId,
  108. props: decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId),
  109. })
  110. break
  111. case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
  112. await addSchemaToJoystreamMediaLocation({
  113. db,
  114. entityId,
  115. nextEntityId,
  116. props: decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId),
  117. })
  118. break
  119. case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
  120. await addSchemaToHttpMediaLocation({
  121. db,
  122. entityId,
  123. nextEntityId,
  124. props: decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId),
  125. })
  126. break
  127. case ContentDirectoryKnownClasses.VIDEOMEDIA:
  128. await addSchemaToVideoMedia({
  129. db,
  130. entityId,
  131. nextEntityId,
  132. props: decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
  133. })
  134. break
  135. case ContentDirectoryKnownClasses.VIDEO:
  136. await addSchemaToVideo({
  137. db,
  138. entityId,
  139. nextEntityId,
  140. props: decode.setProperties<IVideo>(event, videoPropertyNamesWithId),
  141. })
  142. break
  143. case ContentDirectoryKnownClasses.LANGUAGE:
  144. await addSchemaToLanguage({
  145. db,
  146. entityId,
  147. nextEntityId,
  148. props: decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId),
  149. })
  150. break
  151. case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
  152. await addSchemaToVideoMediaEncoding({
  153. db,
  154. entityId,
  155. nextEntityId,
  156. props: decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId),
  157. })
  158. break
  159. case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
  160. await addSchemaToFeaturedVideo({
  161. db,
  162. entityId,
  163. nextEntityId,
  164. props: decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
  165. })
  166. break
  167. case ContentDirectoryKnownClasses.LICENSE:
  168. await addSchemaToLicense({
  169. db,
  170. entityId,
  171. nextEntityId,
  172. props: decode.setProperties<ILicense>(event, licensePropertyNamesWithId),
  173. })
  174. break
  175. case ContentDirectoryKnownClasses.MEDIALOCATION:
  176. await addSchemaToMediaLocation({
  177. db,
  178. entityId,
  179. nextEntityId,
  180. props: decode.setProperties<IMediaLocation>(event, mediaLocationPropertyNamesWithId),
  181. })
  182. break
  183. default:
  184. debug(`Unknown class name: ${className}`)
  185. break
  186. }
  187. }
  188. // eslint-disable-next-line @typescript-eslint/naming-convention
  189. async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: SubstrateEvent): Promise<void> {
  190. if (event.extrinsic && event.extrinsic.method === 'transaction') return
  191. debug(`EntitySchemaSupportAdded event: ${JSON.stringify(event)}`)
  192. const { params } = event
  193. const entityId = params[1].value as number
  194. const [knownClass] = await getKnownClass(db, { where: { id: entityId.toString() } })
  195. if (!knownClass) return
  196. await addSchemSupportToEntity(event, knownClass.name, db, entityId)
  197. }
  198. // eslint-disable-next-line @typescript-eslint/naming-convention
  199. async function contentDirectory_EntityRemoved(db: DB, event: SubstrateEvent): Promise<void> {
  200. debug(`EntityRemoved event: ${JSON.stringify(event)}`)
  201. const entityId = decode.stringIfyEntityId(event)
  202. const where: IWhereCond = { where: { id: entityId } }
  203. const [knownClass, classEntity] = await getKnownClass(db, where)
  204. if (!knownClass) return
  205. switch (knownClass.name) {
  206. case ContentDirectoryKnownClasses.CHANNEL:
  207. await removeChannel(db, where)
  208. break
  209. case ContentDirectoryKnownClasses.CATEGORY:
  210. await removeCategory(db, where)
  211. break
  212. case ContentDirectoryKnownClasses.KNOWNLICENSE:
  213. await removeKnownLicense(db, where)
  214. break
  215. case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
  216. await removeUserDefinedLicense(db, where)
  217. break
  218. case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
  219. await removeJoystreamMediaLocation(db, where)
  220. break
  221. case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
  222. await removeHttpMediaLocation(db, where)
  223. break
  224. case ContentDirectoryKnownClasses.VIDEOMEDIA:
  225. await removeVideoMedia(db, where)
  226. break
  227. case ContentDirectoryKnownClasses.VIDEO:
  228. await removeVideo(db, where)
  229. break
  230. case ContentDirectoryKnownClasses.LANGUAGE:
  231. await removeLanguage(db, where)
  232. break
  233. case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
  234. await removeVideoMediaEncoding(db, where)
  235. break
  236. case ContentDirectoryKnownClasses.LICENSE:
  237. await removeLicense(db, where)
  238. break
  239. case ContentDirectoryKnownClasses.MEDIALOCATION:
  240. await removeMediaLocation(db, where)
  241. break
  242. case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
  243. await removeFeaturedVideo(db, where)
  244. break
  245. default:
  246. throw new Error(`Unknown class name: ${knownClass.name}`)
  247. }
  248. await db.remove<ClassEntity>(classEntity)
  249. }
  250. // eslint-disable-next-line @typescript-eslint/naming-convention
  251. async function contentDirectory_EntityCreated(db: DB, event: SubstrateEvent): Promise<void> {
  252. if (event.extrinsic && event.extrinsic.method === 'transaction') return
  253. debug(`EntityCreated event: ${JSON.stringify(event)}`)
  254. const c = decode.getClassEntity(event)
  255. const classEntity = new ClassEntity()
  256. classEntity.classId = c.classId
  257. classEntity.id = c.entityId.toString()
  258. classEntity.version = event.blockNumber
  259. classEntity.happenedIn = await createBlockOrGetFromDatabase(db, event.blockNumber)
  260. await db.save<ClassEntity>(classEntity)
  261. const nextEntityIdFromDb = await getOrCreate.nextEntityId(db)
  262. nextEntityIdFromDb.nextId = c.entityId + 1
  263. await db.save<NextEntityId>(nextEntityIdFromDb)
  264. await createDefaultSchema(db, classEntity)
  265. }
  266. // eslint-disable-next-line @typescript-eslint/naming-convention
  267. async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: SubstrateEvent): Promise<void> {
  268. const { extrinsic } = event
  269. if (extrinsic && extrinsic.method === 'transaction') return
  270. if (extrinsic === undefined) throw Error(`Extrinsic data not found for event: ${event.id}`)
  271. debug(`EntityPropertyValuesUpdated event: ${JSON.stringify(event)}`)
  272. const { 2: newPropertyValues } = extrinsic.args
  273. // const entityId = decode.stringIfyEntityId(event)
  274. // const where: IWhereCond = { where: { id: entityId } }
  275. const entityId = event.params[1].value as number
  276. const [knownClass] = await getKnownClass(db, { where: { id: entityId.toString() } })
  277. if (!knownClass) return
  278. // TODO: change setProperties method signature to accecpt SubstrateExtrinsic, then remove the following
  279. // line. The reason we push the same arg is beacuse of the setProperties method check the 3rd indices
  280. // to get properties values
  281. extrinsic.args.push(newPropertyValues)
  282. await addSchemSupportToEntity(event, knownClass.name, db, entityId)
  283. }
  284. export {
  285. contentDirectory_EntityCreated,
  286. contentDirectory_EntityRemoved,
  287. contentDirectory_EntitySchemaSupportAdded,
  288. contentDirectory_EntityPropertyValuesUpdated,
  289. }