channel.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. eslint-disable @typescript-eslint/naming-convention
  3. */
  4. import { EventContext, StoreContext } from '@joystream/hydra-common'
  5. import { Content } from '../generated/types'
  6. import { convertContentActorToChannelOwner, processChannelMetadata } from './utils'
  7. import { Channel, ChannelCategory, StorageDataObject, Membership } from 'query-node/dist/model'
  8. import { deserializeMetadata, inconsistentState, logger } from '../common'
  9. import { ChannelCategoryMetadata, ChannelMetadata } from '@joystream/metadata-protobuf'
  10. import { integrateMeta } from '@joystream/metadata-protobuf/utils'
  11. import { In } from 'typeorm'
  12. import { removeDataObject } from '../storage/utils'
  13. export async function content_ChannelCreated(ctx: EventContext & StoreContext): Promise<void> {
  14. const { store, event } = ctx
  15. // read event data
  16. const [contentActor, channelId, , channelCreationParameters] = new Content.ChannelCreatedEvent(event).params
  17. // create entity
  18. const channel = new Channel({
  19. // main data
  20. id: channelId.toString(),
  21. isCensored: false,
  22. videos: [],
  23. createdInBlock: event.blockNumber,
  24. rewardAccount: channelCreationParameters.reward_account.unwrapOr(undefined)?.toString(),
  25. // fill in auto-generated fields
  26. createdAt: new Date(event.blockTimestamp),
  27. updatedAt: new Date(event.blockTimestamp),
  28. // prepare channel owner (handles fields `ownerMember` and `ownerCuratorGroup`)
  29. ...(await convertContentActorToChannelOwner(store, contentActor)),
  30. collaborators: Array.from(channelCreationParameters.collaborators).map(
  31. (id) => new Membership({ id: id.toString() })
  32. ),
  33. })
  34. // deserialize & process metadata
  35. if (channelCreationParameters.meta.isSome) {
  36. const metadata = deserializeMetadata(ChannelMetadata, channelCreationParameters.meta.unwrap()) || {}
  37. await processChannelMetadata(ctx, channel, metadata, channelCreationParameters.assets.unwrapOr(undefined))
  38. }
  39. // save entity
  40. await store.save<Channel>(channel)
  41. // emit log event
  42. logger.info('Channel has been created', { id: channel.id })
  43. }
  44. export async function content_ChannelUpdated(ctx: EventContext & StoreContext): Promise<void> {
  45. const { store, event } = ctx
  46. // read event data
  47. const [, channelId, , channelUpdateParameters] = new Content.ChannelUpdatedEvent(event).params
  48. // load channel
  49. const channel = await store.get(Channel, { where: { id: channelId.toString() } })
  50. // ensure channel exists
  51. if (!channel) {
  52. return inconsistentState('Non-existing channel update requested', channelId)
  53. }
  54. // prepare changed metadata
  55. const newMetadataBytes = channelUpdateParameters.new_meta.unwrapOr(null)
  56. // update metadata if it was changed
  57. if (newMetadataBytes) {
  58. const newMetadata = deserializeMetadata(ChannelMetadata, newMetadataBytes) || {}
  59. await processChannelMetadata(
  60. ctx,
  61. channel,
  62. newMetadata,
  63. channelUpdateParameters.assets_to_upload.unwrapOr(undefined)
  64. )
  65. }
  66. // prepare changed reward account
  67. const newRewardAccount = channelUpdateParameters.reward_account.unwrapOr(null)
  68. // reward account change happened?
  69. if (newRewardAccount) {
  70. // this will change the `channel`!
  71. channel.rewardAccount = newRewardAccount.unwrapOr(undefined)?.toString()
  72. }
  73. const newCollaborators = channelUpdateParameters.collaborators.unwrapOr(undefined)
  74. if (newCollaborators) {
  75. channel.collaborators = Array.from(newCollaborators).map((id) => new Membership({ id: id.toString() }))
  76. }
  77. // set last update time
  78. channel.updatedAt = new Date(event.blockTimestamp)
  79. // save channel
  80. await store.save<Channel>(channel)
  81. // emit log event
  82. logger.info('Channel has been updated', { id: channel.id })
  83. }
  84. export async function content_ChannelAssetsRemoved({ store, event }: EventContext & StoreContext): Promise<void> {
  85. const [, , dataObjectIds] = new Content.ChannelAssetsRemovedEvent(event).params
  86. const assets = await store.getMany(StorageDataObject, {
  87. where: {
  88. id: In(Array.from(dataObjectIds).map((item) => item.toString())),
  89. },
  90. })
  91. await Promise.all(assets.map((a) => removeDataObject(store, a)))
  92. logger.info('Channel assets have been removed', { ids: dataObjectIds.toJSON() })
  93. }
  94. export async function content_ChannelCensorshipStatusUpdated({
  95. store,
  96. event,
  97. }: EventContext & StoreContext): Promise<void> {
  98. // read event data
  99. const [, channelId, isCensored] = new Content.ChannelCensorshipStatusUpdatedEvent(event).params
  100. // load event
  101. const channel = await store.get(Channel, { where: { id: channelId.toString() } })
  102. // ensure channel exists
  103. if (!channel) {
  104. return inconsistentState('Non-existing channel censoring requested', channelId)
  105. }
  106. // update channel
  107. channel.isCensored = isCensored.isTrue
  108. // set last update time
  109. channel.updatedAt = new Date(event.blockTimestamp)
  110. // save channel
  111. await store.save<Channel>(channel)
  112. // emit log event
  113. logger.info('Channel censorship status has been updated', { id: channelId, isCensored: isCensored.isTrue })
  114. }
  115. /// //////////////// ChannelCategory ////////////////////////////////////////////
  116. export async function content_ChannelCategoryCreated({ store, event }: EventContext & StoreContext): Promise<void> {
  117. // read event data
  118. const [channelCategoryId, , channelCategoryCreationParameters] = new Content.ChannelCategoryCreatedEvent(event).params
  119. // read metadata
  120. const metadata = deserializeMetadata(ChannelCategoryMetadata, channelCategoryCreationParameters.meta) || {}
  121. // create new channel category
  122. const channelCategory = new ChannelCategory({
  123. // main data
  124. id: channelCategoryId.toString(),
  125. channels: [],
  126. createdInBlock: event.blockNumber,
  127. // fill in auto-generated fields
  128. createdAt: new Date(event.blockTimestamp),
  129. updatedAt: new Date(event.blockTimestamp),
  130. })
  131. integrateMeta(channelCategory, metadata, ['name'])
  132. // save channel
  133. await store.save<ChannelCategory>(channelCategory)
  134. // emit log event
  135. logger.info('Channel category has been created', { id: channelCategory.id })
  136. }
  137. export async function content_ChannelCategoryUpdated({ store, event }: EventContext & StoreContext): Promise<void> {
  138. // read event data
  139. const [, channelCategoryId, channelCategoryUpdateParameters] = new Content.ChannelCategoryUpdatedEvent(event).params
  140. // load channel category
  141. const channelCategory = await store.get(ChannelCategory, {
  142. where: {
  143. id: channelCategoryId.toString(),
  144. },
  145. })
  146. // ensure channel exists
  147. if (!channelCategory) {
  148. return inconsistentState('Non-existing channel category update requested', channelCategoryId)
  149. }
  150. // read metadata
  151. const newMeta = deserializeMetadata(ChannelCategoryMetadata, channelCategoryUpdateParameters.new_meta) || {}
  152. integrateMeta(channelCategory, newMeta, ['name'])
  153. // set last update time
  154. channelCategory.updatedAt = new Date(event.blockTimestamp)
  155. // save channel category
  156. await store.save<ChannelCategory>(channelCategory)
  157. // emit log event
  158. logger.info('Channel category has been updated', { id: channelCategory.id })
  159. }
  160. export async function content_ChannelCategoryDeleted({ store, event }: EventContext & StoreContext): Promise<void> {
  161. // read event data
  162. const [, channelCategoryId] = new Content.ChannelCategoryDeletedEvent(event).params
  163. // load channel category
  164. const channelCategory = await store.get(ChannelCategory, {
  165. where: {
  166. id: channelCategoryId.toString(),
  167. },
  168. })
  169. // ensure channel category exists
  170. if (!channelCategory) {
  171. return inconsistentState('Non-existing channel category deletion requested', channelCategoryId)
  172. }
  173. // delete channel category
  174. await store.remove<ChannelCategory>(channelCategory)
  175. // emit log event
  176. logger.info('Channel category has been deleted', { id: channelCategory.id })
  177. }
  178. export async function content_ChannelDeleted({ store, event }: EventContext & StoreContext): Promise<void> {
  179. const [, channelId] = new Content.ChannelDeletedEvent(event).params
  180. await store.remove<Channel>(new Channel({ id: channelId.toString() }))
  181. }