123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /*
- eslint-disable @typescript-eslint/naming-convention
- */
- import { EventContext, StoreContext } from '@joystream/hydra-common'
- import { In } from 'typeorm'
- import { Content } from '../generated/types'
- import { deserializeMetadata, inconsistentState, logger } from '../common'
- import { processVideoMetadata } from './utils'
- import { Channel, Video, VideoCategory } from 'query-node/dist/model'
- import { VideoMetadata, VideoCategoryMetadata } from '@joystream/metadata-protobuf'
- import { integrateMeta } from '@joystream/metadata-protobuf/utils'
- import _ from 'lodash'
- export async function content_VideoCategoryCreated({ store, event }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoCategoryId, videoCategoryCreationParameters] = new Content.VideoCategoryCreatedEvent(event).params
- // read metadata
- const metadata = (await deserializeMetadata(VideoCategoryMetadata, videoCategoryCreationParameters.meta)) || {}
- // create new video category
- const videoCategory = new VideoCategory({
- // main data
- id: videoCategoryId.toString(),
- videos: [],
- createdInBlock: event.blockNumber,
- // fill in auto-generated fields
- createdAt: new Date(event.blockTimestamp),
- updatedAt: new Date(event.blockTimestamp),
- })
- integrateMeta(videoCategory, metadata, ['name'])
- // save video category
- await store.save<VideoCategory>(videoCategory)
- // emit log event
- logger.info('Video category has been created', { id: videoCategoryId })
- }
- export async function content_VideoCategoryUpdated({ store, event }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoCategoryId, videoCategoryUpdateParameters] = new Content.VideoCategoryUpdatedEvent(event).params
- // load video category
- const videoCategory = await store.get(VideoCategory, {
- where: { id: videoCategoryId.toString() },
- })
- // ensure video category exists
- if (!videoCategory) {
- return inconsistentState('Non-existing video category update requested', videoCategoryId)
- }
- // read metadata
- const newMeta = deserializeMetadata(VideoCategoryMetadata, videoCategoryUpdateParameters.new_meta) || {}
- integrateMeta(videoCategory, newMeta, ['name'])
- // set last update time
- videoCategory.updatedAt = new Date(event.blockTimestamp)
- // save video category
- await store.save<VideoCategory>(videoCategory)
- // emit log event
- logger.info('Video category has been updated', { id: videoCategoryId })
- }
- export async function content_VideoCategoryDeleted({ store, event }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoCategoryId] = new Content.VideoCategoryDeletedEvent(event).params
- // load video category
- const videoCategory = await store.get(VideoCategory, {
- where: { id: videoCategoryId.toString() },
- })
- // ensure video category exists
- if (!videoCategory) {
- return inconsistentState('Non-existing video category deletion requested', videoCategoryId)
- }
- // remove video category
- await store.remove<VideoCategory>(videoCategory)
- // emit log event
- logger.info('Video category has been deleted', { id: videoCategoryId })
- }
- /// //////////////// Video //////////////////////////////////////////////////////
- export async function content_VideoCreated(ctx: EventContext & StoreContext): Promise<void> {
- const { store, event } = ctx
- // read event data
- const [, channelId, videoId, videoCreationParameters] = new Content.VideoCreatedEvent(event).params
- // load channel
- const channel = await store.get(Channel, { where: { id: channelId.toString() } })
- // ensure channel exists
- if (!channel) {
- return inconsistentState('Trying to add video to non-existing channel', channelId)
- }
- const video = new Video({
- id: videoId.toString(),
- channel,
- isCensored: false,
- isFeatured: false,
- createdInBlock: event.blockNumber,
- createdAt: new Date(event.blockTimestamp),
- updatedAt: new Date(event.blockTimestamp),
- })
- // deserialize & process metadata
- if (videoCreationParameters.meta.isSome) {
- const metadata = deserializeMetadata(VideoMetadata, videoCreationParameters.meta.unwrap()) || {}
- await processVideoMetadata(ctx, video, metadata, videoCreationParameters.assets.unwrapOr(undefined))
- }
- // save video
- await store.save<Video>(video)
- // emit log event
- logger.info('Video has been created', { id: videoId })
- }
- export async function content_VideoUpdated(ctx: EventContext & StoreContext): Promise<void> {
- const { event, store } = ctx
- // read event data
- const [, videoId, videoUpdateParameters] = new Content.VideoUpdatedEvent(event).params
- // load video
- const video = await store.get(Video, {
- where: { id: videoId.toString() },
- relations: ['channel', 'license'],
- })
- // ensure video exists
- if (!video) {
- return inconsistentState('Non-existing video update requested', videoId)
- }
- // prepare changed metadata
- const newMetadataBytes = videoUpdateParameters.new_meta.unwrapOr(null)
- // update metadata if it was changed
- if (newMetadataBytes) {
- const newMetadata = deserializeMetadata(VideoMetadata, newMetadataBytes) || {}
- await processVideoMetadata(ctx, video, newMetadata, videoUpdateParameters.assets_to_upload.unwrapOr(undefined))
- }
- // set last update time
- video.updatedAt = new Date(event.blockTimestamp)
- // save video
- await store.save<Video>(video)
- // emit log event
- logger.info('Video has been updated', { id: videoId })
- }
- export async function content_VideoDeleted({ store, event }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoId] = new Content.VideoDeletedEvent(event).params
- // load video
- const video = await store.get(Video, { where: { id: videoId.toString() } })
- // ensure video exists
- if (!video) {
- return inconsistentState('Non-existing video deletion requested', videoId)
- }
- // remove video
- await store.remove<Video>(video)
- // emit log event
- logger.info('Video has been deleted', { id: videoId })
- }
- export async function content_VideoCensorshipStatusUpdated({
- store,
- event,
- }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoId, isCensored] = new Content.VideoCensorshipStatusUpdatedEvent(event).params
- // load video
- const video = await store.get(Video, { where: { id: videoId.toString() } })
- // ensure video exists
- if (!video) {
- return inconsistentState('Non-existing video censoring requested', videoId)
- }
- // update video
- video.isCensored = isCensored.isTrue
- // set last update time
- video.updatedAt = new Date(event.blockTimestamp)
- // save video
- await store.save<Video>(video)
- // emit log event
- logger.info('Video censorship status has been updated', { id: videoId, isCensored: isCensored.isTrue })
- }
- export async function content_FeaturedVideosSet({ store, event }: EventContext & StoreContext): Promise<void> {
- // read event data
- const [, videoIds] = new Content.FeaturedVideosSetEvent(event).params
- // load old featured videos
- const existingFeaturedVideos = await store.getMany(Video, { where: { isFeatured: true } })
- // comparsion utility
- const isSame = (videoIdA: string) => (videoIdB: string) => videoIdA === videoIdB
- // calculate diff sets
- const videosToRemove = existingFeaturedVideos.filter(
- (existingFV) => !videoIds.map((videoId) => videoId.toString()).some(isSame(existingFV.id))
- )
- const videoIdsToAdd = videoIds.filter(
- (videoId) => !existingFeaturedVideos.map((existingFV) => existingFV.id).some(isSame(videoId.toString()))
- )
- // mark previously featured videos as not-featured
- await Promise.all(
- videosToRemove.map(async (video) => {
- video.isFeatured = false
- // set last update time
- video.updatedAt = new Date(event.blockTimestamp)
- await store.save<Video>(video)
- })
- )
- // read previously not-featured videos that are meant to be featured
- const videosToAdd = await store.getMany(Video, {
- where: {
- id: In(videoIdsToAdd.map((item) => item.toString())),
- },
- })
- if (videosToAdd.length !== videoIdsToAdd.length) {
- // Do not throw, as this is not validated by the runtime
- console.warn(
- 'Non-existing video(s) in featuredVideos set:',
- _.difference(
- videoIdsToAdd.map((v) => v.toString()),
- videosToAdd.map((v) => v.id)
- )
- )
- }
- // mark previously not-featured videos as featured
- await Promise.all(
- videosToAdd.map(async (video) => {
- video.isFeatured = true
- // set last update time
- video.updatedAt = new Date(event.blockTimestamp)
- await store.save<Video>(video)
- })
- )
- // emit log event
- const addedVideoIds = videosToAdd.map((v) => v.id)
- const removedVideoIds = videosToRemove.map((v) => v.id)
- logger.info('Featured videos have been updated', { addedVideoIds, removedVideoIds })
- }
|