123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542 |
- // Ensure we're `no_std` when compiling for Wasm.
- #![cfg_attr(not(feature = "std"), no_std)]
- #![recursion_limit = "256"]
- // Internal Substrate warning (decl_event).
- #![allow(clippy::unused_unit, clippy::all)]
- #[cfg(test)]
- mod tests;
- mod errors;
- mod permissions;
- pub use errors::*;
- pub use permissions::*;
- use core::hash::Hash;
- use codec::Codec;
- use codec::{Decode, Encode};
- pub use storage::{
- BagIdType, DataObjectCreationParameters, DataObjectStorage, DynamicBagIdType, UploadParameters,
- UploadParametersRecord,
- };
- use frame_support::{
- decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, Parameter,
- };
- use frame_system::ensure_signed;
- #[cfg(feature = "std")]
- pub use serde::{Deserialize, Serialize};
- use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
- use sp_runtime::traits::{MaybeSerializeDeserialize, Member};
- use sp_std::collections::btree_set::BTreeSet;
- use sp_std::vec::Vec;
- pub use common::{
- currency::{BalanceOf, GovernanceCurrency},
- working_group::WorkingGroup,
- AssetUrls, MembershipTypes, StorageOwnership,
- };
- type Storage<T> = storage::Module<T>;
- /// Type, used in diffrent numeric constraints representations
- pub type MaxNumber = u32;
- /// A numeric identifier trait
- pub trait NumericIdentifier:
- Parameter
- + Member
- + BaseArithmetic
- + Codec
- + Default
- + Copy
- + Clone
- + Hash
- + MaybeSerializeDeserialize
- + Eq
- + PartialEq
- + Ord
- + Zero
- {
- }
- impl NumericIdentifier for u64 {}
- /// Module configuration trait for Content Directory Module
- pub trait Trait:
- frame_system::Trait + ContentActorAuthenticator + Clone + GovernanceCurrency + storage::Trait
- {
- /// The overarching event type.
- type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
- /// Channel Transfer Payments Escrow Account seed for ModuleId to compute deterministic AccountId
- type ChannelOwnershipPaymentEscrowId: Get<[u8; 8]>;
- /// Type of identifier for Videos
- type VideoId: NumericIdentifier;
- /// Type of identifier for Video Categories
- type VideoCategoryId: NumericIdentifier;
- /// Type of identifier for Channel Categories
- type ChannelCategoryId: NumericIdentifier;
- /// Type of identifier for Playlists
- type PlaylistId: NumericIdentifier;
- /// Type of identifier for Persons
- type PersonId: NumericIdentifier;
- /// Type of identifier for Channels
- type SeriesId: NumericIdentifier;
- /// Type of identifier for Channel transfer requests
- type ChannelOwnershipTransferRequestId: NumericIdentifier;
- /// The maximum number of curators per group constraint
- type MaxNumberOfCuratorsPerGroup: Get<MaxNumber>;
- /// The storage type used
- type DataObjectStorage: storage::DataObjectStorage<Self>;
- }
- /// The owner of a channel, is the authorized "actor" that can update
- /// or delete or transfer a channel and its contents.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub enum ChannelOwner<MemberId, CuratorGroupId> {
- /// A Member owns the channel
- Member(MemberId),
- /// A specific curation group owns the channel
- CuratorGroup(CuratorGroupId),
- }
- // simplification type
- pub(crate) type ActorToChannelOwnerResult<T> = Result<
- ChannelOwner<
- <T as common::MembershipTypes>::MemberId,
- <T as ContentActorAuthenticator>::CuratorGroupId,
- >,
- Error<T>,
- >;
- // Default trait implemented only because its used in a Channel which needs to implement a Default trait
- // since it is a StorageValue.
- impl<MemberId: Default, CuratorGroupId> Default for ChannelOwner<MemberId, CuratorGroupId> {
- fn default() -> Self {
- ChannelOwner::Member(MemberId::default())
- }
- }
- /// A category which channels can belong to.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelCategory {
- // No runtime information is currently stored for a Category.
- }
- /// Information on the category being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelCategoryCreationParameters {
- /// Metadata for the category.
- meta: Vec<u8>,
- }
- /// Information on the category being updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelCategoryUpdateParameters {
- // as this is the only field it is not an Option
- /// Metadata update for the category.
- new_meta: Vec<u8>,
- }
- /// Type representing an owned channel which videos, playlists, and series can belong to.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelRecord<MemberId, CuratorGroupId, AccountId> {
- /// The owner of a channel
- owner: ChannelOwner<MemberId, CuratorGroupId>,
- /// The videos under this channel
- num_videos: u64,
- /// If curators have censored this channel or not
- is_censored: bool,
- /// Reward account where revenue is sent if set.
- reward_account: Option<AccountId>,
- /// Account for withdrawing deletion prize funds
- deletion_prize_source_account_id: AccountId,
- }
- // Channel alias type for simplification.
- pub type Channel<T> = ChannelRecord<
- <T as common::MembershipTypes>::MemberId,
- <T as ContentActorAuthenticator>::CuratorGroupId,
- <T as frame_system::Trait>::AccountId,
- >;
- /// A request to buy a channel by a new ChannelOwner.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelOwnershipTransferRequestRecord<
- ChannelId,
- MemberId,
- CuratorGroupId,
- Balance,
- AccountId,
- > {
- channel_id: ChannelId,
- new_owner: ChannelOwner<MemberId, CuratorGroupId>,
- payment: Balance,
- new_reward_account: Option<AccountId>,
- }
- // ChannelOwnershipTransferRequest type alias for simplification.
- pub type ChannelOwnershipTransferRequest<T> = ChannelOwnershipTransferRequestRecord<
- <T as storage::Trait>::ChannelId,
- <T as common::MembershipTypes>::MemberId,
- <T as ContentActorAuthenticator>::CuratorGroupId,
- BalanceOf<T>,
- <T as frame_system::Trait>::AccountId,
- >;
- /// Information about channel being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelCreationParametersRecord<StorageAssets, AccountId> {
- /// Asset collection for the channel, referenced by metadata
- assets: Option<StorageAssets>,
- /// Metadata about the channel.
- meta: Option<Vec<u8>>,
- /// optional reward account
- reward_account: Option<AccountId>,
- }
- type ChannelCreationParameters<T> =
- ChannelCreationParametersRecord<StorageAssets<T>, <T as frame_system::Trait>::AccountId>;
- /// Information about channel being updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct ChannelUpdateParametersRecord<StorageAssets, AccountId, DataObjectId: Ord> {
- /// Asset collection for the channel, referenced by metadata
- assets_to_upload: Option<StorageAssets>,
- /// If set, metadata update for the channel.
- new_meta: Option<Vec<u8>>,
- /// If set, updates the reward account of the channel
- reward_account: Option<Option<AccountId>>,
- /// assets to be removed from channel
- assets_to_remove: BTreeSet<DataObjectId>,
- }
- type ChannelUpdateParameters<T> = ChannelUpdateParametersRecord<
- StorageAssets<T>,
- <T as frame_system::Trait>::AccountId,
- DataObjectId<T>,
- >;
- /// A category that videos can belong to.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct VideoCategory {
- // No runtime information is currently stored for a Category.
- }
- /// Information about the video category being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct VideoCategoryCreationParameters {
- /// Metadata about the video category.
- meta: Vec<u8>,
- }
- /// Information about the video category being updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct VideoCategoryUpdateParameters {
- // Because it is the only field it is not an Option
- /// Metadata update for the video category.
- new_meta: Vec<u8>,
- }
- /// Information regarding the content being uploaded
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub struct StorageAssetsRecord<Balance> {
- /// Data object parameters.
- pub object_creation_list: Vec<DataObjectCreationParameters>,
- /// Expected data size fee value for this extrinsic call.
- pub expected_data_size_fee: Balance,
- }
- type StorageAssets<T> = StorageAssetsRecord<<T as balances::Trait>::Balance>;
- /// Information about the video being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub struct VideoCreationParametersRecord<StorageAssets> {
- /// Asset collection for the video
- assets: Option<StorageAssets>,
- /// Metadata for the video.
- meta: Option<Vec<u8>>,
- }
- type VideoCreationParameters<T> = VideoCreationParametersRecord<StorageAssets<T>>;
- /// Information about the video being updated
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct VideoUpdateParametersRecord<StorageAssets, DataObjectId: Ord> {
- /// Assets referenced by metadata
- assets_to_upload: Option<StorageAssets>,
- /// If set, metadata update for the video.
- new_meta: Option<Vec<u8>>,
- /// video assets to be removed from channel
- assets_to_remove: BTreeSet<DataObjectId>,
- }
- type VideoUpdateParameters<T> = VideoUpdateParametersRecord<StorageAssets<T>, DataObjectId<T>>;
- /// A video which belongs to a channel. A video may be part of a series or playlist.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct VideoRecord<ChannelId, SeriesId> {
- pub in_channel: ChannelId,
- // keep track of which season the video is in if it is an 'episode'
- // - prevent removing a video if it is in a season (because order is important)
- pub in_series: Option<SeriesId>,
- /// Whether the curators have censored the video or not.
- pub is_censored: bool,
- }
- type Video<T> = VideoRecord<<T as storage::Trait>::ChannelId, <T as Trait>::SeriesId>;
- /// Information about the plyalist being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct PlaylistCreationParameters {
- /// Metadata about the playlist.
- meta: Vec<u8>,
- }
- /// Information about the playlist being updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct PlaylistUpdateParameters {
- // It is the only field so its not an Option
- /// Metadata update for the playlist.
- new_meta: Vec<u8>,
- }
- /// A playlist is an ordered collection of videos.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct Playlist<ChannelId> {
- /// The channel the playlist belongs to.
- in_channel: ChannelId,
- }
- /// Information about the episode being created or updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub enum EpisodeParameters<VideoId, StorageAssets> {
- /// A new video is being added as the episode.
- NewVideo(VideoCreationParametersRecord<StorageAssets>),
- /// An existing video is being made into an episode.
- ExistingVideo(VideoId),
- }
- /// Information about the season being created or updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct SeasonParameters<VideoId, StorageAssets> {
- /// Season assets referenced by metadata
- assets: Option<StorageAssets>,
- // ?? It might just be more straighforward to always provide full list of episodes at cost of larger tx.
- /// If set, updates the episodes of a season. Extends the number of episodes in a season
- /// when length of new_episodes is greater than previously set. Last elements must all be
- /// 'Some' in that case.
- /// Will truncate existing season when length of new_episodes is less than previously set.
- episodes: Option<Vec<Option<EpisodeParameters<VideoId, StorageAssets>>>>,
- meta: Option<Vec<u8>>,
- }
- /// Information about the series being created or updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct SeriesParameters<VideoId, StorageAssets> {
- /// Series assets referenced by metadata
- assets: Option<StorageAssets>,
- // ?? It might just be more straighforward to always provide full list of seasons at cost of larger tx.
- /// If set, updates the seasons of a series. Extend a series when length of seasons is
- /// greater than previoulsy set. Last elements must all be 'Some' in that case.
- /// Will truncate existing series when length of seasons is less than previously set.
- seasons: Option<Vec<Option<SeasonParameters<VideoId, StorageAssets>>>>,
- meta: Option<Vec<u8>>,
- }
- /// A season is an ordered list of videos (episodes).
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct Season<VideoId> {
- episodes: Vec<VideoId>,
- }
- /// A series is an ordered list of seasons that belongs to a channel.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct Series<ChannelId, VideoId> {
- in_channel: ChannelId,
- seasons: Vec<Season<VideoId>>,
- }
- /// The actor the caller/origin is trying to act as for Person creation and update and delete calls.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub enum PersonActor<MemberId, CuratorId> {
- Member(MemberId),
- Curator(CuratorId),
- }
- /// The authorized actor that may update or delete a Person.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub enum PersonController<MemberId> {
- /// Member controls the person
- Member(MemberId),
- /// Any curator controls the person
- Curators,
- }
- /// Default trait implemented only because its used in Person which needs to implement a Default trait
- /// since it is a StorageValue.
- impl<MemberId: Default> Default for PersonController<MemberId> {
- fn default() -> Self {
- PersonController::Member(MemberId::default())
- }
- }
- /// Information for Person being created.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
- pub struct PersonCreationParameters<StorageAssets> {
- /// Assets referenced by metadata
- assets: StorageAssets,
- /// Metadata for person.
- meta: Vec<u8>,
- }
- /// Information for Persion being updated.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct PersonUpdateParameters<StorageAssets> {
- /// Assets referenced by metadata
- assets: Option<StorageAssets>,
- /// Metadata to update person.
- new_meta: Option<Vec<u8>>,
- }
- /// A Person represents a real person that may be associated with a video.
- #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
- #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
- pub struct Person<MemberId> {
- /// Who can update or delete this person.
- controlled_by: PersonController<MemberId>,
- }
- type DataObjectId<T> = <T as storage::Trait>::DataObjectId;
- decl_storage! {
- trait Store for Module<T: Trait> as Content {
- pub ChannelById get(fn channel_by_id): map hasher(blake2_128_concat) T::ChannelId => Channel<T>;
- pub ChannelCategoryById get(fn channel_category_by_id): map hasher(blake2_128_concat) T::ChannelCategoryId => ChannelCategory;
- pub VideoById get(fn video_by_id): map hasher(blake2_128_concat) T::VideoId => Video<T>;
- pub VideoCategoryById get(fn video_category_by_id): map hasher(blake2_128_concat) T::VideoCategoryId => VideoCategory;
- pub PlaylistById get(fn playlist_by_id): map hasher(blake2_128_concat) T::PlaylistId => Playlist<T::ChannelId>;
- pub SeriesById get(fn series_by_id): map hasher(blake2_128_concat) T::SeriesId => Series<T::ChannelId, T::VideoId>;
- pub PersonById get(fn person_by_id): map hasher(blake2_128_concat) T::PersonId => Person<T::MemberId>;
- pub ChannelOwnershipTransferRequestById get(fn channel_ownership_transfer_request_by_id):
- map hasher(blake2_128_concat) T::ChannelOwnershipTransferRequestId => ChannelOwnershipTransferRequest<T>;
- pub NextChannelCategoryId get(fn next_channel_category_id) config(): T::ChannelCategoryId;
- pub NextChannelId get(fn next_channel_id) config(): T::ChannelId;
- pub NextVideoCategoryId get(fn next_video_category_id) config(): T::VideoCategoryId;
- pub NextVideoId get(fn next_video_id) config(): T::VideoId;
- pub NextPlaylistId get(fn next_playlist_id) config(): T::PlaylistId;
- pub NextPersonId get(fn next_person_id) config(): T::PersonId;
- pub NextSeriesId get(fn next_series_id) config(): T::SeriesId;
- pub NextChannelOwnershipTransferRequestId get(fn next_channel_transfer_request_id) config(): T::ChannelOwnershipTransferRequestId;
- pub NextCuratorGroupId get(fn next_curator_group_id) config(): T::CuratorGroupId;
- /// Map, representing CuratorGroupId -> CuratorGroup relation
- pub CuratorGroupById get(fn curator_group_by_id): map hasher(blake2_128_concat) T::CuratorGroupId => CuratorGroup<T>;
- }
- }
- decl_module! {
- pub struct Module<T: Trait> for enum Call where origin: T::Origin {
- /// Predefined errors
- type Error = Error<T>;
- /// Initializing events
- fn deposit_event() = default;
- /// Exports const - max number of curators per group
- const MaxNumberOfCuratorsPerGroup: MaxNumber = T::MaxNumberOfCuratorsPerGroup::get();
- // ======
- // Next set of extrinsics can only be invoked by lead.
- // ======
- /// Add new curator group to runtime storage
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_curator_group(
- origin,
- ) {
- // Ensure given origin is lead
- ensure_is_lead::<T>(origin)?;
- //
- // == MUTATION SAFE ==
- //
- let curator_group_id = Self::next_curator_group_id();
- // Insert empty curator group with `active` parameter set to false
- <CuratorGroupById<T>>::insert(curator_group_id, CuratorGroup::<T>::default());
- // Increment the next curator curator_group_id:
- <NextCuratorGroupId<T>>::mutate(|n| *n += T::CuratorGroupId::one());
- // Trigger event
- Self::deposit_event(RawEvent::CuratorGroupCreated(curator_group_id));
- }
- /// Set `is_active` status for curator group under given `curator_group_id`
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn set_curator_group_status(
- origin,
- curator_group_id: T::CuratorGroupId,
- is_active: bool,
- ) {
- // Ensure given origin is lead
- ensure_is_lead::<T>(origin)?;
- // Ensure curator group under provided curator_group_id already exist
- Self::ensure_curator_group_under_given_id_exists(&curator_group_id)?;
- //
- // == MUTATION SAFE ==
- //
- // Set `is_active` status for curator group under given `curator_group_id`
- <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
- curator_group.set_status(is_active)
- });
- // Trigger event
- Self::deposit_event(RawEvent::CuratorGroupStatusSet(curator_group_id, is_active));
- }
- /// Add curator to curator group under given `curator_group_id`
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn add_curator_to_group(
- origin,
- curator_group_id: T::CuratorGroupId,
- curator_id: T::CuratorId,
- ) {
- // Ensure given origin is lead
- ensure_is_lead::<T>(origin)?;
- // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
- let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
- // Ensure that curator_id is infact a worker in content working group
- ensure_is_valid_curator_id::<T>(&curator_id)?;
- // Ensure max number of curators per group limit not reached yet
- curator_group.ensure_max_number_of_curators_limit_not_reached()?;
- // Ensure curator under provided curator_id isn`t a CuratorGroup member yet
- curator_group.ensure_curator_in_group_does_not_exist(&curator_id)?;
- //
- // == MUTATION SAFE ==
- //
- // Insert curator_id into curator_group under given curator_group_id
- <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
- curator_group.get_curators_mut().insert(curator_id);
- });
- // Trigger event
- Self::deposit_event(RawEvent::CuratorAdded(curator_group_id, curator_id));
- }
- /// Remove curator from a given curator group
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn remove_curator_from_group(
- origin,
- curator_group_id: T::CuratorGroupId,
- curator_id: T::CuratorId,
- ) {
- // Ensure given origin is lead
- ensure_is_lead::<T>(origin)?;
- // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
- let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
- // Ensure curator under provided curator_id is CuratorGroup member
- curator_group.ensure_curator_in_group_exists(&curator_id)?;
- //
- // == MUTATION SAFE ==
- //
- // Remove curator_id from curator_group under given curator_group_id
- <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
- curator_group.get_curators_mut().remove(&curator_id);
- });
- // Trigger event
- Self::deposit_event(RawEvent::CuratorRemoved(curator_group_id, curator_id));
- }
- // TODO: Add Option<reward_account> to ChannelCreationParameters ?
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_channel(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- params: ChannelCreationParameters<T>,
- ) {
- ensure_actor_authorized_to_create_channel::<T>(
- origin.clone(),
- &actor,
- )?;
- // channel creator account
- let sender = ensure_signed(origin)?;
- // The channel owner will be..
- let channel_owner = Self::actor_to_channel_owner(&actor)?;
- // next channel id
- let channel_id = NextChannelId::<T>::get();
- // atomically upload to storage and return the # of uploaded assets
- if let Some(upload_assets) = params.assets.as_ref() {
- Self::upload_assets_to_storage(
- upload_assets,
- &channel_id,
- &sender,
- )?;
- }
- //
- // == MUTATION SAFE ==
- //
- // Only increment next channel id if adding content was successful
- NextChannelId::<T>::mutate(|id| *id += T::ChannelId::one());
- // channel creation
- let channel: Channel<T> = ChannelRecord {
- owner: channel_owner,
- // a newly create channel has zero videos ??
- num_videos: 0u64,
- is_censored: false,
- reward_account: params.reward_account.clone(),
- // setting the channel owner account as the prize funds account
- deletion_prize_source_account_id: sender,
- };
- // add channel to onchain state
- ChannelById::<T>::insert(channel_id, channel.clone());
- Self::deposit_event(RawEvent::ChannelCreated(actor, channel_id, channel, params));
- }
- // Include Option<AccountId> in ChannelUpdateParameters to update reward_account
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_channel(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- channel_id: T::ChannelId,
- params: ChannelUpdateParameters<T>,
- ) {
- // check that channel exists
- let channel = Self::ensure_channel_exists(&channel_id)?;
- ensure_actor_authorized_to_update_channel::<T>(
- origin,
- &actor,
- &channel.owner,
- )?;
- Self::remove_assets_from_storage(¶ms.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
- // atomically upload to storage and return the # of uploaded assets
- if let Some(upload_assets) = params.assets_to_upload.as_ref() {
- Self::upload_assets_to_storage(
- upload_assets,
- &channel_id,
- &channel.deletion_prize_source_account_id
- )?;
- }
- //
- // == MUTATION SAFE ==
- //
- let mut channel = channel;
- // Maybe update the reward account
- if let Some(reward_account) = ¶ms.reward_account {
- channel.reward_account = reward_account.clone();
- }
- // Update the channel
- ChannelById::<T>::insert(channel_id, channel.clone());
- Self::deposit_event(RawEvent::ChannelUpdated(actor, channel_id, channel, params));
- }
- // extrinsics for channel deletion
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_channel(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- channel_id: T::ChannelId,
- num_objects_to_delete: u64,
- ) -> DispatchResult {
- // check that channel exists
- let channel = Self::ensure_channel_exists(&channel_id)?;
- // ensure permissions
- ensure_actor_authorized_to_update_channel::<T>(
- origin,
- &actor,
- &channel.owner,
- )?;
- // check that channel videos are 0
- ensure!(channel.num_videos == 0, Error::<T>::ChannelContainsVideos);
- // get bag id for the channel
- let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(channel_id);
- let bag_id = storage::BagIdType::from(dyn_bag.clone());
- // channel has a dynamic bag associated to it -> remove assets from storage
- if let Ok(bag) = T::DataObjectStorage::ensure_bag_exists(&bag_id) {
- // ensure that bag size provided is valid
- ensure!(
- bag.objects_number == num_objects_to_delete,
- Error::<T>::InvalidBagSizeSpecified
- );
- // construct collection of assets to be removed
- let assets_to_remove = T::DataObjectStorage::get_data_objects_id(&bag_id);
- // remove specified assets from storage
- Self::remove_assets_from_storage(
- &assets_to_remove,
- &channel_id,
- &channel.deletion_prize_source_account_id
- )?;
- // delete channel dynamic bag
- Storage::<T>::delete_dynamic_bag(
- channel.deletion_prize_source_account_id,
- dyn_bag
- )?;
- }
- //
- // == MUTATION SAFE ==
- //
- // remove channel from on chain state
- ChannelById::<T>::remove(channel_id);
- // deposit event
- Self::deposit_event(RawEvent::ChannelDeleted(actor, channel_id));
- Ok(())
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_channel_censorship_status(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- channel_id: T::ChannelId,
- is_censored: bool,
- rationale: Vec<u8>,
- ) {
- // check that channel exists
- let channel = Self::ensure_channel_exists(&channel_id)?;
- if channel.is_censored == is_censored {
- return Ok(())
- }
- ensure_actor_authorized_to_censor::<T>(
- origin,
- &actor,
- &channel.owner,
- )?;
- //
- // == MUTATION SAFE ==
- //
- ChannelById::<T>::mutate(channel_id, |channel| {
- channel.is_censored = is_censored
- });
- // TODO: unset the reward account ? so no revenue can be earned for censored channels?
- Self::deposit_event(RawEvent::ChannelCensorshipStatusUpdated(actor, channel_id, is_censored, rationale));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_channel_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- params: ChannelCategoryCreationParameters,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- //
- // == MUTATION SAFE ==
- //
- let category_id = Self::next_channel_category_id();
- NextChannelCategoryId::<T>::mutate(|id| *id += T::ChannelCategoryId::one());
- let category = ChannelCategory {};
- ChannelCategoryById::<T>::insert(category_id, category.clone());
- Self::deposit_event(RawEvent::ChannelCategoryCreated(category_id, category, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_channel_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- category_id: T::ChannelCategoryId,
- params: ChannelCategoryUpdateParameters,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- Self::ensure_channel_category_exists(&category_id)?;
- Self::deposit_event(RawEvent::ChannelCategoryUpdated(actor, category_id, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_channel_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- category_id: T::ChannelCategoryId,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- Self::ensure_channel_category_exists(&category_id)?;
- ChannelCategoryById::<T>::remove(&category_id);
- Self::deposit_event(RawEvent::ChannelCategoryDeleted(actor, category_id));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn request_channel_transfer(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _request: ChannelOwnershipTransferRequest<T>,
- ) {
- // requester must be new_owner
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn cancel_channel_transfer_request(
- _origin,
- _request_id: T::ChannelOwnershipTransferRequestId,
- ) {
- // origin must be original requester (ie. proposed new channel owner)
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn accept_channel_transfer(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _request_id: T::ChannelOwnershipTransferRequestId,
- ) {
- // only current owner of channel can approve
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_video(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- channel_id: T::ChannelId,
- params: VideoCreationParameters<T>,
- ) {
- // check that channel exists
- let channel = Self::ensure_channel_exists(&channel_id)?;
- ensure_actor_authorized_to_update_channel::<T>(
- origin,
- &actor,
- &channel.owner,
- )?;
- // next video id
- let video_id = NextVideoId::<T>::get();
- // atomically upload to storage and return the # of uploaded assets
- if let Some(upload_assets) = params.assets.as_ref() {
- Self::upload_assets_to_storage(
- upload_assets,
- &channel_id,
- &channel.deletion_prize_source_account_id
- )?;
- }
- //
- // == MUTATION SAFE ==
- //
- // create the video struct
- let video: Video<T> = VideoRecord {
- in_channel: channel_id,
- // keep track of which season the video is in if it is an 'episode'
- // - prevent removing a video if it is in a season (because order is important)
- in_series: None,
- /// Whether the curators have censored the video or not.
- is_censored: false,
- };
- // add it to the onchain state
- VideoById::<T>::insert(video_id, video);
- // Only increment next video id if adding content was successful
- NextVideoId::<T>::mutate(|id| *id += T::VideoId::one());
- // Add recently added video id to the channel
- ChannelById::<T>::mutate(channel_id, |channel| {
- channel.num_videos = channel.num_videos.saturating_add(1);
- });
- Self::deposit_event(RawEvent::VideoCreated(actor, channel_id, video_id, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_video(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- video_id: T::VideoId,
- params: VideoUpdateParameters<T>,
- ) {
- // check that video exists, retrieve corresponding channel id.
- let video = Self::ensure_video_exists(&video_id)?;
- let channel_id = video.in_channel;
- let channel = ChannelById::<T>::get(&channel_id);
- ensure_actor_authorized_to_update_channel::<T>(
- origin,
- &actor,
- &channel.owner,
- )?;
- // remove specified assets from channel bag in storage
- Self::remove_assets_from_storage(¶ms.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
- // atomically upload to storage and return the # of uploaded assets
- if let Some(upload_assets) = params.assets_to_upload.as_ref() {
- Self::upload_assets_to_storage(
- upload_assets,
- &channel_id,
- &channel.deletion_prize_source_account_id
- )?;
- }
- //
- // == MUTATION SAFE ==
- //
- Self::deposit_event(RawEvent::VideoUpdated(actor, video_id, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_video(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- video_id: T::VideoId,
- assets_to_remove: BTreeSet<DataObjectId<T>>,
- ) {
- // check that video exists
- let video = Self::ensure_video_exists(&video_id)?;
- // get information regarding channel
- let channel_id = video.in_channel;
- let channel = ChannelById::<T>::get(channel_id);
- ensure_actor_authorized_to_update_channel::<T>(
- origin,
- &actor,
- // The channel owner will be..
- &channel.owner,
- )?;
- // ensure video can be removed
- Self::ensure_video_can_be_removed(&video)?;
- // remove specified assets from channel bag in storage
- Self::remove_assets_from_storage(&assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
- //
- // == MUTATION SAFE ==
- //
- // Remove video
- VideoById::<T>::remove(video_id);
- // Decrease video count for the channel
- ChannelById::<T>::mutate(channel_id, |channel| {
- channel.num_videos = channel.num_videos.saturating_sub(1)
- });
- Self::deposit_event(RawEvent::VideoDeleted(actor, video_id));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_playlist(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _channel_id: T::ChannelId,
- _params: PlaylistCreationParameters,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_playlist(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _playlist: T::PlaylistId,
- _params: PlaylistUpdateParameters,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_playlist(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _channel_id: T::ChannelId,
- _playlist: T::PlaylistId,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn set_featured_videos(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- list: Vec<T::VideoId>
- ) {
- // can only be set by lead
- ensure_actor_authorized_to_set_featured_videos::<T>(
- origin,
- &actor,
- )?;
- //
- // == MUTATION SAFE ==
- //
- Self::deposit_event(RawEvent::FeaturedVideosSet(actor, list));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_video_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- params: VideoCategoryCreationParameters,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- //
- // == MUTATION SAFE ==
- //
- let category_id = Self::next_video_category_id();
- NextVideoCategoryId::<T>::mutate(|id| *id += T::VideoCategoryId::one());
- let category = VideoCategory {};
- VideoCategoryById::<T>::insert(category_id, category);
- Self::deposit_event(RawEvent::VideoCategoryCreated(actor, category_id, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_video_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- category_id: T::VideoCategoryId,
- params: VideoCategoryUpdateParameters,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- Self::ensure_video_category_exists(&category_id)?;
- Self::deposit_event(RawEvent::VideoCategoryUpdated(actor, category_id, params));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_video_category(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- category_id: T::VideoCategoryId,
- ) {
- ensure_actor_authorized_to_manage_categories::<T>(
- origin,
- &actor
- )?;
- Self::ensure_video_category_exists(&category_id)?;
- VideoCategoryById::<T>::remove(&category_id);
- Self::deposit_event(RawEvent::VideoCategoryDeleted(actor, category_id));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_person(
- _origin,
- _actor: PersonActor<T::MemberId, T::CuratorId>,
- _params: PersonCreationParameters<StorageAssets<T>>,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_person(
- _origin,
- _actor: PersonActor<T::MemberId, T::CuratorId>,
- _person: T::PersonId,
- _params: PersonUpdateParameters<StorageAssets<T>>,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_person(
- _origin,
- _actor: PersonActor<T::MemberId, T::CuratorId>,
- _person: T::PersonId,
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn add_person_to_video(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _video_id: T::VideoId,
- _person: T::PersonId
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn remove_person_from_video(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _video_id: T::VideoId
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_video_censorship_status(
- origin,
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- video_id: T::VideoId,
- is_censored: bool,
- rationale: Vec<u8>,
- ) {
- // check that video exists
- let video = Self::ensure_video_exists(&video_id)?;
- if video.is_censored == is_censored {
- return Ok(())
- }
- ensure_actor_authorized_to_censor::<T>(
- origin,
- &actor,
- // The channel owner will be..
- &Self::channel_by_id(video.in_channel).owner,
- )?;
- //
- // == MUTATION SAFE ==
- //
- // update
- VideoById::<T>::mutate(video_id, |video| {
- video.is_censored = is_censored;
- });
- Self::deposit_event(RawEvent::VideoCensorshipStatusUpdated(actor, video_id, is_censored, rationale));
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn create_series(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _channel_id: T::ChannelId,
- _params: SeriesParameters<T::VideoId, StorageAssets<T>>
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn update_series(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _channel_id: T::ChannelId,
- _params: SeriesParameters<T::VideoId, StorageAssets<T>>
- ) {
- Self::not_implemented()?;
- }
- #[weight = 10_000_000] // TODO: adjust weight
- pub fn delete_series(
- _origin,
- _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- _series: T::SeriesId,
- ) {
- Self::not_implemented()?;
- }
- }
- }
- impl<T: Trait> Module<T> {
- /// Ensure `CuratorGroup` under given id exists
- fn ensure_curator_group_under_given_id_exists(
- curator_group_id: &T::CuratorGroupId,
- ) -> Result<(), Error<T>> {
- ensure!(
- <CuratorGroupById<T>>::contains_key(curator_group_id),
- Error::<T>::CuratorGroupDoesNotExist
- );
- Ok(())
- }
- /// Ensure `CuratorGroup` under given id exists, return corresponding one
- fn ensure_curator_group_exists(
- curator_group_id: &T::CuratorGroupId,
- ) -> Result<CuratorGroup<T>, Error<T>> {
- Self::ensure_curator_group_under_given_id_exists(curator_group_id)?;
- Ok(Self::curator_group_by_id(curator_group_id))
- }
- fn ensure_channel_exists(channel_id: &T::ChannelId) -> Result<Channel<T>, Error<T>> {
- ensure!(
- ChannelById::<T>::contains_key(channel_id),
- Error::<T>::ChannelDoesNotExist
- );
- Ok(ChannelById::<T>::get(channel_id))
- }
- fn ensure_video_exists(video_id: &T::VideoId) -> Result<Video<T>, Error<T>> {
- ensure!(
- VideoById::<T>::contains_key(video_id),
- Error::<T>::VideoDoesNotExist
- );
- Ok(VideoById::<T>::get(video_id))
- }
- // Ensure given video is not in season
- fn ensure_video_can_be_removed(video: &Video<T>) -> DispatchResult {
- ensure!(video.in_series.is_none(), Error::<T>::VideoInSeason);
- Ok(())
- }
- fn ensure_channel_category_exists(
- channel_category_id: &T::ChannelCategoryId,
- ) -> Result<ChannelCategory, Error<T>> {
- ensure!(
- ChannelCategoryById::<T>::contains_key(channel_category_id),
- Error::<T>::CategoryDoesNotExist
- );
- Ok(ChannelCategoryById::<T>::get(channel_category_id))
- }
- fn ensure_video_category_exists(
- video_category_id: &T::VideoCategoryId,
- ) -> Result<VideoCategory, Error<T>> {
- ensure!(
- VideoCategoryById::<T>::contains_key(video_category_id),
- Error::<T>::CategoryDoesNotExist
- );
- Ok(VideoCategoryById::<T>::get(video_category_id))
- }
- fn pick_upload_parameters_from_assets(
- assets: &StorageAssets<T>,
- channel_id: &T::ChannelId,
- prize_source_account: &T::AccountId,
- ) -> UploadParameters<T> {
- // dynamic bag for a media object
- let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(*channel_id);
- let bag_id = BagIdType::from(dyn_bag.clone());
- if T::DataObjectStorage::ensure_bag_exists(&bag_id).is_err() {
- // create_dynamic_bag checks automatically satifsfied with None as second parameter
- Storage::<T>::create_dynamic_bag(dyn_bag, None).unwrap();
- }
- UploadParametersRecord {
- bag_id,
- object_creation_list: assets.object_creation_list.clone(),
- deletion_prize_source_account_id: prize_source_account.clone(),
- expected_data_size_fee: assets.expected_data_size_fee,
- }
- }
- fn actor_to_channel_owner(
- actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
- ) -> ActorToChannelOwnerResult<T> {
- match actor {
- // Lead should use their member or curator role to create channels
- ContentActor::Lead => Err(Error::<T>::ActorCannotOwnChannel),
- ContentActor::Curator(curator_group_id, _curator_id) => {
- Ok(ChannelOwner::CuratorGroup(*curator_group_id))
- }
- ContentActor::Member(member_id) => Ok(ChannelOwner::Member(*member_id)),
- }
- }
- fn bag_id_for_channel(channel_id: &T::ChannelId) -> storage::BagId<T> {
- // retrieve bag id from channel id
- let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(*channel_id);
- BagIdType::from(dyn_bag)
- }
- fn not_implemented() -> DispatchResult {
- Err(Error::<T>::FeatureNotImplemented.into())
- }
- fn upload_assets_to_storage(
- assets: &StorageAssets<T>,
- channel_id: &T::ChannelId,
- prize_source_account: &T::AccountId,
- ) -> DispatchResult {
- // construct upload params
- let upload_params =
- Self::pick_upload_parameters_from_assets(assets, channel_id, prize_source_account);
- // attempt to upload objects att
- Storage::<T>::upload_data_objects(upload_params.clone())?;
- Ok(())
- }
- fn remove_assets_from_storage(
- assets: &BTreeSet<DataObjectId<T>>,
- channel_id: &T::ChannelId,
- prize_source_account: &T::AccountId,
- ) -> DispatchResult {
- // remove assets if any
- if !assets.is_empty() {
- Storage::<T>::delete_data_objects(
- prize_source_account.clone(),
- Self::bag_id_for_channel(&channel_id),
- assets.clone(),
- )?;
- }
- Ok(())
- }
- }
- decl_event!(
- pub enum Event<T>
- where
- ContentActor = ContentActor<
- <T as ContentActorAuthenticator>::CuratorGroupId,
- <T as ContentActorAuthenticator>::CuratorId,
- <T as common::MembershipTypes>::MemberId,
- >,
- CuratorGroupId = <T as ContentActorAuthenticator>::CuratorGroupId,
- CuratorId = <T as ContentActorAuthenticator>::CuratorId,
- VideoId = <T as Trait>::VideoId,
- VideoCategoryId = <T as Trait>::VideoCategoryId,
- ChannelId = <T as storage::Trait>::ChannelId,
- ChannelCategoryId = <T as Trait>::ChannelCategoryId,
- ChannelOwnershipTransferRequestId = <T as Trait>::ChannelOwnershipTransferRequestId,
- PlaylistId = <T as Trait>::PlaylistId,
- SeriesId = <T as Trait>::SeriesId,
- PersonId = <T as Trait>::PersonId,
- ChannelOwnershipTransferRequest = ChannelOwnershipTransferRequest<T>,
- Series = Series<<T as storage::Trait>::ChannelId, <T as Trait>::VideoId>,
- Channel = Channel<T>,
- DataObjectId = DataObjectId<T>,
- IsCensored = bool,
- ChannelCreationParameters = ChannelCreationParameters<T>,
- ChannelUpdateParameters = ChannelUpdateParameters<T>,
- VideoCreationParameters = VideoCreationParameters<T>,
- VideoUpdateParameters = VideoUpdateParameters<T>,
- StorageAssets = StorageAssets<T>,
- {
- // Curators
- CuratorGroupCreated(CuratorGroupId),
- CuratorGroupStatusSet(CuratorGroupId, bool /* active status */),
- CuratorAdded(CuratorGroupId, CuratorId),
- CuratorRemoved(CuratorGroupId, CuratorId),
- // Channels
- ChannelCreated(ContentActor, ChannelId, Channel, ChannelCreationParameters),
- ChannelUpdated(ContentActor, ChannelId, Channel, ChannelUpdateParameters),
- ChannelAssetsRemoved(ContentActor, ChannelId, BTreeSet<DataObjectId>, Channel),
- ChannelCensorshipStatusUpdated(
- ContentActor,
- ChannelId,
- IsCensored,
- Vec<u8>, /* rationale */
- ),
- // Channel Ownership Transfers
- ChannelOwnershipTransferRequested(
- ContentActor,
- ChannelOwnershipTransferRequestId,
- ChannelOwnershipTransferRequest,
- ),
- ChannelOwnershipTransferRequestWithdrawn(ContentActor, ChannelOwnershipTransferRequestId),
- ChannelOwnershipTransferred(ContentActor, ChannelOwnershipTransferRequestId),
- // Channel Categories
- ChannelCategoryCreated(
- ChannelCategoryId,
- ChannelCategory,
- ChannelCategoryCreationParameters,
- ),
- ChannelCategoryUpdated(
- ContentActor,
- ChannelCategoryId,
- ChannelCategoryUpdateParameters,
- ),
- ChannelCategoryDeleted(ContentActor, ChannelCategoryId),
- // Videos
- VideoCategoryCreated(
- ContentActor,
- VideoCategoryId,
- VideoCategoryCreationParameters,
- ),
- VideoCategoryUpdated(ContentActor, VideoCategoryId, VideoCategoryUpdateParameters),
- VideoCategoryDeleted(ContentActor, VideoCategoryId),
- VideoCreated(ContentActor, ChannelId, VideoId, VideoCreationParameters),
- VideoUpdated(ContentActor, VideoId, VideoUpdateParameters),
- VideoDeleted(ContentActor, VideoId),
- VideoCensorshipStatusUpdated(
- ContentActor,
- VideoId,
- IsCensored,
- Vec<u8>, /* rationale */
- ),
- // Featured Videos
- FeaturedVideosSet(ContentActor, Vec<VideoId>),
- // Video Playlists
- PlaylistCreated(ContentActor, PlaylistId, PlaylistCreationParameters),
- PlaylistUpdated(ContentActor, PlaylistId, PlaylistUpdateParameters),
- PlaylistDeleted(ContentActor, PlaylistId),
- // Series
- SeriesCreated(
- ContentActor,
- SeriesId,
- StorageAssets,
- SeriesParameters<VideoId, StorageAssets>,
- Series,
- ),
- SeriesUpdated(
- ContentActor,
- SeriesId,
- StorageAssets,
- SeriesParameters<VideoId, StorageAssets>,
- Series,
- ),
- SeriesDeleted(ContentActor, SeriesId),
- // Persons
- PersonCreated(
- ContentActor,
- PersonId,
- StorageAssets,
- PersonCreationParameters<StorageAssets>,
- ),
- PersonUpdated(
- ContentActor,
- PersonId,
- StorageAssets,
- PersonUpdateParameters<StorageAssets>,
- ),
- PersonDeleted(ContentActor, PersonId),
- ChannelDeleted(ContentActor, ChannelId),
- }
- );
|