index.ts 10 KB

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