channel.ts 7.8 KB

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