lib.rs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. // Ensure we're `no_std` when compiling for Wasm.
  2. #![cfg_attr(not(feature = "std"), no_std)]
  3. #![recursion_limit = "256"]
  4. // #[cfg(test)]
  5. // mod tests;
  6. mod errors;
  7. mod permissions;
  8. pub use errors::*;
  9. pub use permissions::*;
  10. use core::hash::Hash;
  11. use codec::Codec;
  12. use codec::{Decode, Encode};
  13. use frame_support::{
  14. decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, Parameter,
  15. };
  16. #[cfg(feature = "std")]
  17. pub use serde::{Deserialize, Serialize};
  18. use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
  19. use sp_runtime::traits::{MaybeSerializeDeserialize, Member};
  20. use sp_std::collections::btree_set::BTreeSet;
  21. // use sp_std::vec;
  22. use sp_std::vec::Vec;
  23. use system::ensure_signed;
  24. pub use common::storage::{ContentParameters as ContentParametersRecord, StorageSystem};
  25. pub use common::{
  26. currency::{BalanceOf, GovernanceCurrency},
  27. MembershipTypes, StorageOwnership, Url,
  28. };
  29. pub(crate) type ContentId<T> = <T as StorageOwnership>::ContentId;
  30. pub(crate) type DataObjectTypeId<T> = <T as StorageOwnership>::DataObjectTypeId;
  31. pub(crate) type ContentParameters<T> = ContentParametersRecord<ContentId<T>, DataObjectTypeId<T>>;
  32. /// Type, used in diffrent numeric constraints representations
  33. pub type MaxNumber = u32;
  34. /// A numeric identifier trait
  35. pub trait NumericIdentifier:
  36. Parameter
  37. + Member
  38. + BaseArithmetic
  39. + Codec
  40. + Default
  41. + Copy
  42. + Clone
  43. + Hash
  44. + MaybeSerializeDeserialize
  45. + Eq
  46. + PartialEq
  47. + Ord
  48. + Zero
  49. {
  50. }
  51. impl NumericIdentifier for u64 {}
  52. /// Module configuration trait for Content Directory Module
  53. pub trait Trait:
  54. system::Trait
  55. + ContentActorAuthenticator
  56. + Clone
  57. + StorageOwnership
  58. + MembershipTypes
  59. + GovernanceCurrency
  60. {
  61. /// The overarching event type.
  62. type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
  63. /// Channel Transfer Payments Escrow Account seed for ModuleId to compute deterministic AccountId
  64. type ChannelOwnershipPaymentEscrowId: Get<[u8; 8]>;
  65. /// Type of identifier for Videos
  66. type VideoId: NumericIdentifier;
  67. /// Type of identifier for Video Categories
  68. type VideoCategoryId: NumericIdentifier;
  69. /// Type of identifier for Channel Categories
  70. type ChannelCategoryId: NumericIdentifier;
  71. /// Type of identifier for Playlists
  72. type PlaylistId: NumericIdentifier;
  73. /// Type of identifier for Persons
  74. type PersonId: NumericIdentifier;
  75. /// Type of identifier for Channels
  76. type SeriesId: NumericIdentifier;
  77. /// Type of identifier for Channel transfer requests
  78. type ChannelOwnershipTransferRequestId: NumericIdentifier;
  79. /// The maximum number of curators per group constraint
  80. type MaxNumberOfCuratorsPerGroup: Get<MaxNumber>;
  81. // Type that handles asset uploads to storage system
  82. type StorageSystem: StorageSystem<Self>;
  83. }
  84. /// Specifies how a new asset will be provided on creating and updating
  85. /// Channels, Videos, Series and Person
  86. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  87. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  88. pub enum NewAsset<ContentParameters> {
  89. /// Upload to the storage system
  90. Upload(ContentParameters),
  91. /// Multiple url strings pointing at an asset
  92. Urls(Vec<Url>),
  93. }
  94. /// The owner of a channel, is the authorized "actor" that can update
  95. /// or delete or transfer a channel and its contents.
  96. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  97. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  98. pub enum ChannelOwner<MemberId, CuratorGroupId, DAOId> {
  99. /// A Member owns the channel
  100. Member(MemberId),
  101. /// A specific curation group owns the channel
  102. CuratorGroup(CuratorGroupId),
  103. // Native DAO owns the channel
  104. Dao(DAOId),
  105. }
  106. // Default trait implemented only because its used in a Channel which needs to implement a Default trait
  107. // since it is a StorageValue.
  108. impl<MemberId: Default, CuratorGroupId, DAOId> Default
  109. for ChannelOwner<MemberId, CuratorGroupId, DAOId>
  110. {
  111. fn default() -> Self {
  112. ChannelOwner::Member(MemberId::default())
  113. }
  114. }
  115. /// A category which channels can belong to.
  116. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  117. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  118. pub struct ChannelCategory {
  119. // No runtime information is currently stored for a Category.
  120. }
  121. /// Information on the category being created.
  122. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  123. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  124. pub struct ChannelCategoryCreationParameters {
  125. /// Metadata for the category.
  126. meta: Vec<u8>,
  127. }
  128. /// Information on the category being updated.
  129. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  130. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  131. pub struct ChannelCategoryUpdateParameters {
  132. // as this is the only field it is not an Option
  133. /// Metadata update for the category.
  134. new_meta: Vec<u8>,
  135. }
  136. /// Type representing an owned channel which videos, playlists, and series can belong to.
  137. /// If a channel is deleted, all videos, playlists and series will also be deleted.
  138. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  139. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  140. pub struct ChannelRecord<MemberId, CuratorGroupId, DAOId, AccountId, VideoId, PlaylistId, SeriesId>
  141. {
  142. /// The owner of a channel
  143. owner: ChannelOwner<MemberId, CuratorGroupId, DAOId>,
  144. /// The videos under this channel
  145. videos: Vec<VideoId>,
  146. /// The playlists under this channel
  147. playlists: Vec<PlaylistId>,
  148. /// The series under this channel
  149. series: Vec<SeriesId>,
  150. /// If curators have censored this channel or not
  151. is_censored: bool,
  152. /// Reward account where revenue is sent if set.
  153. reward_account: Option<AccountId>,
  154. }
  155. // Channel alias type for simplification.
  156. pub type Channel<T> = ChannelRecord<
  157. <T as MembershipTypes>::MemberId,
  158. <T as ContentActorAuthenticator>::CuratorGroupId,
  159. <T as StorageOwnership>::DAOId,
  160. <T as system::Trait>::AccountId,
  161. <T as Trait>::VideoId,
  162. <T as Trait>::PlaylistId,
  163. <T as Trait>::SeriesId,
  164. >;
  165. /// A request to buy a channel by a new ChannelOwner.
  166. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  167. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  168. pub struct ChannelOwnershipTransferRequestRecord<
  169. ChannelId,
  170. MemberId,
  171. CuratorGroupId,
  172. DAOId,
  173. Balance,
  174. AccountId,
  175. > {
  176. channel_id: ChannelId,
  177. new_owner: ChannelOwner<MemberId, CuratorGroupId, DAOId>,
  178. payment: Balance,
  179. new_reward_account: Option<AccountId>,
  180. }
  181. // ChannelOwnershipTransferRequest type alias for simplification.
  182. pub type ChannelOwnershipTransferRequest<T> = ChannelOwnershipTransferRequestRecord<
  183. <T as StorageOwnership>::ChannelId,
  184. <T as MembershipTypes>::MemberId,
  185. <T as ContentActorAuthenticator>::CuratorGroupId,
  186. <T as StorageOwnership>::DAOId,
  187. BalanceOf<T>,
  188. <T as system::Trait>::AccountId,
  189. >;
  190. /// Information about channel being created.
  191. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  192. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  193. pub struct ChannelCreationParameters<ContentParameters> {
  194. /// Assets referenced by metadata
  195. assets: Vec<NewAsset<ContentParameters>>,
  196. /// Metadata about the channel.
  197. meta: Vec<u8>,
  198. }
  199. /// Information about channel being updated.
  200. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  201. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  202. pub struct ChannelUpdateParameters<ContentParameters> {
  203. /// Assets referenced by metadata
  204. assets: Option<Vec<NewAsset<ContentParameters>>>,
  205. /// If set, metadata update for the channel.
  206. new_meta: Option<Vec<u8>>,
  207. }
  208. /// A category that videos can belong to.
  209. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  210. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  211. pub struct VideoCategory {
  212. // No runtime information is currently stored for a Category.
  213. }
  214. /// Information about the video category being created.
  215. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  216. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  217. pub struct VideoCategoryCreationParameters {
  218. /// Metadata about the video category.
  219. meta: Vec<u8>,
  220. }
  221. /// Information about the video category being updated.
  222. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  223. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  224. pub struct VideoCategoryUpdateParameters {
  225. // Because it is the only field it is not an Option
  226. /// Metadata update for the video category.
  227. new_meta: Vec<u8>,
  228. }
  229. /// Information about the video being created.
  230. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  231. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  232. pub struct VideoCreationParameters<ContentParameters> {
  233. /// Assets referenced by metadata
  234. assets: Vec<NewAsset<ContentParameters>>,
  235. /// Metadata for the video.
  236. meta: Vec<u8>,
  237. }
  238. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  239. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  240. pub struct VideoUpdateParameters<ContentParameters> {
  241. /// Assets referenced by metadata
  242. assets: Option<Vec<NewAsset<ContentParameters>>>,
  243. /// If set, metadata update for the video.
  244. new_meta: Option<Vec<u8>>,
  245. }
  246. /// A video which belongs to a channel. A video may be part of a series or playlist.
  247. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  248. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  249. pub struct Video<ChannelId, SeriesId> {
  250. in_channel: ChannelId,
  251. // keep track of which season the video is in if it is an 'episode'
  252. // - prevent removing a video if it is in a season (because order is important)
  253. in_series: Option<SeriesId>,
  254. /// Whether the curators have censored the video or not.
  255. is_censored: bool,
  256. /// Whether the curators have chosen to feature the video or not.
  257. is_featured: bool,
  258. }
  259. /// Information about the plyalist being created.
  260. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  261. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  262. pub struct PlaylistCreationParameters {
  263. /// Metadata about the playlist.
  264. meta: Vec<u8>,
  265. }
  266. /// Information about the playlist being updated.
  267. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  268. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  269. pub struct PlaylistUpdateParameters {
  270. // It is the only field so its not an Option
  271. /// Metadata update for the playlist.
  272. new_meta: Vec<u8>,
  273. }
  274. /// A playlist is an ordered collection of videos.
  275. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  276. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  277. pub struct Playlist<ChannelId> {
  278. /// The channel the playlist belongs to.
  279. in_channel: ChannelId,
  280. }
  281. /// Information about the episode being created or updated.
  282. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  283. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  284. pub enum EpisodeParameters<VideoId, ContentParameters> {
  285. /// A new video is being added as the episode.
  286. NewVideo(VideoCreationParameters<ContentParameters>),
  287. /// An existing video is being made into an episode.
  288. ExistingVideo(VideoId),
  289. }
  290. /// Information about the season being created or updated.
  291. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  292. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  293. pub struct SeasonParameters<VideoId, ContentParameters> {
  294. /// Season assets referenced by metadata
  295. assets: Option<Vec<NewAsset<ContentParameters>>>,
  296. // ?? It might just be more straighforward to always provide full list of episodes at cost of larger tx.
  297. /// If set, updates the episodes of a season. Extends the number of episodes in a season
  298. /// when length of new_episodes is greater than previously set. Last elements must all be
  299. /// 'Some' in that case.
  300. /// Will truncate existing season when length of new_episodes is less than previously set.
  301. episodes: Option<Vec<Option<EpisodeParameters<VideoId, ContentParameters>>>>,
  302. /// If set, Metadata update for season.
  303. meta: Option<Vec<u8>>,
  304. }
  305. /// Information about the series being created or updated.
  306. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  307. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  308. pub struct SeriesParameters<VideoId, ContentParameters> {
  309. /// Series assets referenced by metadata
  310. assets: Option<Vec<NewAsset<ContentParameters>>>,
  311. // ?? It might just be more straighforward to always provide full list of seasons at cost of larger tx.
  312. /// If set, updates the seasons of a series. Extend a series when length of seasons is
  313. /// greater than previoulsy set. Last elements must all be 'Some' in that case.
  314. /// Will truncate existing series when length of seasons is less than previously set.
  315. seasons: Option<Vec<Option<SeasonParameters<VideoId, ContentParameters>>>>,
  316. meta: Option<Vec<u8>>,
  317. }
  318. /// A season is an ordered list of videos (episodes).
  319. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  320. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  321. pub struct Season<VideoId> {
  322. episodes: Vec<VideoId>,
  323. }
  324. /// A series is an ordered list of seasons that belongs to a channel.
  325. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  326. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  327. pub struct Series<ChannelId, VideoId> {
  328. in_channel: ChannelId,
  329. seasons: Vec<Season<VideoId>>,
  330. }
  331. // The actor the caller/origin is trying to act as for Person creation and update and delete calls.
  332. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  333. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  334. pub enum PersonActor<MemberId, CuratorId> {
  335. Member(MemberId),
  336. Curator(CuratorId),
  337. }
  338. /// The authorized actor that may update or delete a Person.
  339. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  340. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  341. pub enum PersonController<MemberId> {
  342. /// Member controls the person
  343. Member(MemberId),
  344. /// Any curator controls the person
  345. Curators,
  346. }
  347. // Default trait implemented only because its used in Person which needs to implement a Default trait
  348. // since it is a StorageValue.
  349. impl<MemberId: Default> Default for PersonController<MemberId> {
  350. fn default() -> Self {
  351. PersonController::Member(MemberId::default())
  352. }
  353. }
  354. /// Information for Person being created.
  355. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  356. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  357. pub struct PersonCreationParameters<ContentParameters> {
  358. /// Assets referenced by metadata
  359. assets: Vec<NewAsset<ContentParameters>>,
  360. /// Metadata for person.
  361. meta: Vec<u8>,
  362. }
  363. /// Information for Persion being updated.
  364. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  365. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  366. pub struct PersonUpdateParameters<ContentParameters> {
  367. /// Assets referenced by metadata
  368. assets: Option<Vec<NewAsset<ContentParameters>>>,
  369. /// Metadata to update person.
  370. new_meta: Option<Vec<u8>>,
  371. }
  372. /// A Person represents a real person that may be associated with a video.
  373. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  374. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  375. pub struct Person<MemberId> {
  376. /// Who can update or delete this person.
  377. controlled_by: PersonController<MemberId>,
  378. }
  379. decl_storage! {
  380. trait Store for Module<T: Trait> as Content {
  381. pub ChannelById get(fn channel_by_id): map hasher(blake2_128_concat) T::ChannelId => Channel<T>;
  382. pub ChannelCategoryById get(fn channel_category_by_id): map hasher(blake2_128_concat) T::ChannelCategoryId => ChannelCategory;
  383. pub VideoById get(fn video_by_id): map hasher(blake2_128_concat) T::VideoId => Video<T::ChannelId, T::SeriesId>;
  384. pub VideoCategoryById get(fn video_category_by_id): map hasher(blake2_128_concat) T::VideoCategoryId => VideoCategory;
  385. pub PlaylistById get(fn playlist_by_id): map hasher(blake2_128_concat) T::PlaylistId => Playlist<T::ChannelId>;
  386. pub SeriesById get(fn series_by_id): map hasher(blake2_128_concat) T::SeriesId => Series<T::ChannelId, T::VideoId>;
  387. pub PersonById get(fn person_by_id): map hasher(blake2_128_concat) T::PersonId => Person<T::MemberId>;
  388. pub ChannelOwnershipTransferRequestById get(fn channel_ownership_transfer_request_by_id):
  389. map hasher(blake2_128_concat) T::ChannelOwnershipTransferRequestId => ChannelOwnershipTransferRequest<T>;
  390. pub NextChannelCategoryId get(fn next_channel_category_id) config(): T::ChannelCategoryId;
  391. pub NextChannelId get(fn next_channel_id) config(): T::ChannelId;
  392. pub NextVideoCategoryId get(fn next_video_category_id) config(): T::VideoCategoryId;
  393. pub NextVideoId get(fn next_video_id) config(): T::VideoId;
  394. pub NextPlaylistId get(fn next_playlist_id) config(): T::PlaylistId;
  395. pub NextPersonId get(fn next_person_id) config(): T::PersonId;
  396. pub NextSeriesId get(fn next_series_id) config(): T::SeriesId;
  397. pub NextChannelOwnershipTransferRequestId get(fn next_channel_transfer_request_id) config(): T::ChannelOwnershipTransferRequestId;
  398. pub NextCuratorGroupId get(fn next_curator_group_id) config(): T::CuratorGroupId;
  399. /// Map, representing CuratorGroupId -> CuratorGroup relation
  400. pub CuratorGroupById get(fn curator_group_by_id): map hasher(blake2_128_concat) T::CuratorGroupId => CuratorGroup<T>;
  401. }
  402. }
  403. decl_module! {
  404. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  405. /// Predefined errors
  406. type Error = Error<T>;
  407. /// Initializing events
  408. fn deposit_event() = default;
  409. /// Exports const - max number of curators per group
  410. const MaxNumberOfCuratorsPerGroup: MaxNumber = T::MaxNumberOfCuratorsPerGroup::get();
  411. // ======
  412. // Next set of extrinsics can only be invoked by lead.
  413. // ======
  414. /// Add new curator group to runtime storage
  415. #[weight = 10_000_000] // TODO: adjust weight
  416. pub fn create_curator_group(
  417. origin,
  418. ) -> DispatchResult {
  419. // Ensure given origin is lead
  420. ensure_is_lead::<T>(origin)?;
  421. //
  422. // == MUTATION SAFE ==
  423. //
  424. let curator_group_id = Self::next_curator_group_id();
  425. // Insert empty curator group with `active` parameter set to false
  426. <CuratorGroupById<T>>::insert(curator_group_id, CuratorGroup::<T>::default());
  427. // Increment the next curator curator_group_id:
  428. <NextCuratorGroupId<T>>::mutate(|n| *n += T::CuratorGroupId::one());
  429. // Trigger event
  430. Self::deposit_event(RawEvent::CuratorGroupCreated(curator_group_id));
  431. Ok(())
  432. }
  433. /// Remove curator group under given `curator_group_id` from runtime storage
  434. #[weight = 10_000_000] // TODO: adjust weight
  435. pub fn delete_curator_group(
  436. origin,
  437. curator_group_id: T::CuratorGroupId,
  438. ) -> DispatchResult {
  439. // Ensure given origin is lead
  440. ensure_is_lead::<T>(origin)?;
  441. // Ensure CuratorGroup under given curator_group_id exists
  442. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  443. // We should previously ensure that curator_group owns no channels to be able to remove it
  444. curator_group.ensure_curator_group_owns_no_channels()?;
  445. //
  446. // == MUTATION SAFE ==
  447. //
  448. // Remove curator group under given curator group id from runtime storage
  449. <CuratorGroupById<T>>::remove(curator_group_id);
  450. // Trigger event
  451. Self::deposit_event(RawEvent::CuratorGroupDeleted(curator_group_id));
  452. Ok(())
  453. }
  454. /// Set `is_active` status for curator group under given `curator_group_id`
  455. #[weight = 10_000_000] // TODO: adjust weight
  456. pub fn set_curator_group_status(
  457. origin,
  458. curator_group_id: T::CuratorGroupId,
  459. is_active: bool,
  460. ) -> DispatchResult {
  461. // Ensure given origin is lead
  462. ensure_is_lead::<T>(origin)?;
  463. // Ensure curator group under provided curator_group_id already exist
  464. Self::ensure_curator_group_under_given_id_exists(&curator_group_id)?;
  465. //
  466. // == MUTATION SAFE ==
  467. //
  468. // Set `is_active` status for curator group under given `curator_group_id`
  469. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  470. curator_group.set_status(is_active)
  471. });
  472. // Trigger event
  473. Self::deposit_event(RawEvent::CuratorGroupStatusSet(curator_group_id, is_active));
  474. Ok(())
  475. }
  476. /// Add curator to curator group under given `curator_group_id`
  477. #[weight = 10_000_000] // TODO: adjust weight
  478. pub fn add_curator_to_group(
  479. origin,
  480. curator_group_id: T::CuratorGroupId,
  481. curator_id: T::CuratorId,
  482. ) -> DispatchResult {
  483. // Ensure given origin is lead
  484. ensure_is_lead::<T>(origin)?;
  485. // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
  486. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  487. // Ensure max number of curators per group limit not reached yet
  488. curator_group.ensure_max_number_of_curators_limit_not_reached()?;
  489. // Ensure curator under provided curator_id isn`t a CuratorGroup member yet
  490. curator_group.ensure_curator_in_group_does_not_exist(&curator_id)?;
  491. //
  492. // == MUTATION SAFE ==
  493. //
  494. // Insert curator_id into curator_group under given curator_group_id
  495. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  496. curator_group.get_curators_mut().insert(curator_id);
  497. });
  498. // Trigger event
  499. Self::deposit_event(RawEvent::CuratorAdded(curator_group_id, curator_id));
  500. Ok(())
  501. }
  502. /// Remove curator from a given curator group
  503. #[weight = 10_000_000] // TODO: adjust weight
  504. pub fn remove_curator_from_group(
  505. origin,
  506. curator_group_id: T::CuratorGroupId,
  507. curator_id: T::CuratorId,
  508. ) -> DispatchResult {
  509. // Ensure given origin is lead
  510. ensure_is_lead::<T>(origin)?;
  511. // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
  512. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  513. // Ensure curator under provided curator_id is CuratorGroup member
  514. curator_group.ensure_curator_in_group_exists(&curator_id)?;
  515. //
  516. // == MUTATION SAFE ==
  517. //
  518. // Remove curator_id from curator_group under given curator_group_id
  519. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  520. curator_group.get_curators_mut().remove(&curator_id);
  521. });
  522. // Trigger event
  523. Self::deposit_event(RawEvent::CuratorRemoved(curator_group_id, curator_id));
  524. Ok(())
  525. }
  526. #[weight = 10_000_000] // TODO: adjust weight
  527. pub fn create_channel(
  528. origin,
  529. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  530. params: ChannelCreationParameters<ContentParameters<T>>,
  531. ) -> DispatchResult {
  532. Ok(())
  533. }
  534. #[weight = 10_000_000] // TODO: adjust weight
  535. pub fn update_channel(
  536. origin,
  537. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  538. channel_id: T::ChannelId,
  539. params: ChannelUpdateParameters<ContentParameters<T>>,
  540. ) -> DispatchResult {
  541. Ok(())
  542. }
  543. #[weight = 10_000_000] // TODO: adjust weight
  544. pub fn delete_channel(
  545. origin,
  546. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  547. channel_id: T::ChannelId,
  548. ) -> DispatchResult {
  549. Ok(())
  550. }
  551. #[weight = 10_000_000] // TODO: adjust weight
  552. pub fn request_channel_transfer(
  553. origin,
  554. new_owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  555. channel_id: T::ChannelId,
  556. payment: BalanceOf<T>,
  557. ) -> DispatchResult {
  558. // requester must be new_owner
  559. Ok(())
  560. }
  561. #[weight = 10_000_000] // TODO: adjust weight
  562. pub fn cancel_channel_transfer_request(
  563. origin,
  564. request_id: T::ChannelOwnershipTransferRequestId,
  565. ) -> DispatchResult {
  566. // origin must be original requester (ie. proposed new channel owner)
  567. Ok(())
  568. }
  569. #[weight = 10_000_000] // TODO: adjust weight
  570. pub fn accept_channel_transfer(
  571. origin,
  572. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  573. request_id: T::ChannelOwnershipTransferRequestId,
  574. ) -> DispatchResult {
  575. // only current owner of channel can approve
  576. Ok(())
  577. }
  578. #[weight = 10_000_000] // TODO: adjust weight
  579. pub fn create_video(
  580. origin,
  581. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  582. channel_id: T::ChannelId,
  583. params: VideoCreationParameters<ContentParameters<T>>,
  584. ) -> DispatchResult {
  585. Ok(())
  586. }
  587. #[weight = 10_000_000] // TODO: adjust weight
  588. pub fn update_video(
  589. origin,
  590. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  591. video: T::VideoId,
  592. params: VideoUpdateParameters<ContentParameters<T>>,
  593. ) -> DispatchResult {
  594. Ok(())
  595. }
  596. #[weight = 10_000_000] // TODO: adjust weight
  597. pub fn delete_video(
  598. origin,
  599. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  600. video: T::VideoId,
  601. ) -> DispatchResult {
  602. Ok(())
  603. }
  604. #[weight = 10_000_000] // TODO: adjust weight
  605. pub fn create_playlist(
  606. origin,
  607. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  608. channel_id: T::ChannelId,
  609. params: PlaylistCreationParameters,
  610. ) -> DispatchResult {
  611. Ok(())
  612. }
  613. #[weight = 10_000_000] // TODO: adjust weight
  614. pub fn update_playlist(
  615. origin,
  616. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  617. playlist: T::PlaylistId,
  618. params: PlaylistUpdateParameters,
  619. ) -> DispatchResult {
  620. Ok(())
  621. }
  622. #[weight = 10_000_000] // TODO: adjust weight
  623. pub fn delete_playlist(
  624. origin,
  625. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  626. channel_id: T::ChannelId,
  627. playlist: T::PlaylistId,
  628. ) -> DispatchResult {
  629. Ok(())
  630. }
  631. #[weight = 10_000_000] // TODO: adjust weight
  632. pub fn set_featured_videos(
  633. origin,
  634. list: Vec<T::VideoId>
  635. ) -> DispatchResult {
  636. // can only be set by lead
  637. Ok(())
  638. }
  639. #[weight = 10_000_000] // TODO: adjust weight
  640. pub fn create_video_category(
  641. origin,
  642. curator: T::CuratorId,
  643. params: VideoCategoryCreationParameters,
  644. ) -> DispatchResult {
  645. Ok(())
  646. }
  647. #[weight = 10_000_000] // TODO: adjust weight
  648. pub fn update_video_category(
  649. origin,
  650. curator: T::CuratorId,
  651. category: T::VideoCategoryId,
  652. params: VideoCategoryUpdateParameters,
  653. ) -> DispatchResult {
  654. Ok(())
  655. }
  656. #[weight = 10_000_000] // TODO: adjust weight
  657. pub fn delete_video_category(
  658. origin,
  659. curator: T::CuratorId,
  660. category: T::VideoCategoryId,
  661. ) -> DispatchResult {
  662. Ok(())
  663. }
  664. #[weight = 10_000_000] // TODO: adjust weight
  665. pub fn create_channel_category(
  666. origin,
  667. curator: T::CuratorId,
  668. params: ChannelCategoryCreationParameters,
  669. ) -> DispatchResult {
  670. Ok(())
  671. }
  672. #[weight = 10_000_000] // TODO: adjust weight
  673. pub fn update_channel_category(
  674. origin,
  675. curator: T::CuratorId,
  676. category: T::ChannelCategoryId,
  677. params: ChannelCategoryUpdateParameters,
  678. ) -> DispatchResult {
  679. Ok(())
  680. }
  681. #[weight = 10_000_000] // TODO: adjust weight
  682. pub fn delete_channel_category(
  683. origin,
  684. curator: T::CuratorId,
  685. category: T::ChannelCategoryId,
  686. ) -> DispatchResult {
  687. Ok(())
  688. }
  689. #[weight = 10_000_000] // TODO: adjust weight
  690. pub fn create_person(
  691. origin,
  692. actor: PersonActor<T::MemberId, T::CuratorId>,
  693. params: PersonCreationParameters<ContentParameters<T>>,
  694. ) -> DispatchResult {
  695. Ok(())
  696. }
  697. #[weight = 10_000_000] // TODO: adjust weight
  698. pub fn update_person(
  699. origin,
  700. actor: PersonActor<T::MemberId, T::CuratorId>,
  701. person: T::PersonId,
  702. params: PersonUpdateParameters<ContentParameters<T>>,
  703. ) -> DispatchResult {
  704. Ok(())
  705. }
  706. #[weight = 10_000_000] // TODO: adjust weight
  707. pub fn delete_person(
  708. origin,
  709. actor: PersonActor<T::MemberId, T::CuratorId>,
  710. person: T::PersonId,
  711. ) -> DispatchResult {
  712. Ok(())
  713. }
  714. #[weight = 10_000_000] // TODO: adjust weight
  715. pub fn add_person_to_video(
  716. origin,
  717. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  718. video_id: T::VideoId,
  719. person: T::PersonId
  720. ) -> DispatchResult {
  721. Ok(())
  722. }
  723. #[weight = 10_000_000] // TODO: adjust weight
  724. pub fn remove_person_from_video(
  725. origin,
  726. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  727. video_id: T::VideoId
  728. ) -> DispatchResult {
  729. Ok(())
  730. }
  731. #[weight = 10_000_000] // TODO: adjust weight
  732. pub fn censor_video(
  733. origin,
  734. curator_id: T::CuratorId,
  735. video_id: T::VideoId,
  736. rationale: Vec<u8>,
  737. ) -> DispatchResult {
  738. Ok(())
  739. }
  740. #[weight = 10_000_000] // TODO: adjust weight
  741. pub fn censor_channel(
  742. origin,
  743. curator_id: T::CuratorId,
  744. channel_id: T::ChannelId,
  745. rationale: Vec<u8>,
  746. ) -> DispatchResult {
  747. Ok(())
  748. }
  749. #[weight = 10_000_000] // TODO: adjust weight
  750. pub fn uncensor_video(
  751. origin,
  752. curator_id: T::CuratorId,
  753. video_id: T::VideoId,
  754. rationale: Vec<u8>
  755. ) -> DispatchResult {
  756. Ok(())
  757. }
  758. #[weight = 10_000_000] // TODO: adjust weight
  759. pub fn uncensor_channel(
  760. origin,
  761. curator_id: T::CuratorId,
  762. channel_id: T::ChannelId,
  763. rationale: Vec<u8>,
  764. ) -> DispatchResult {
  765. Ok(())
  766. }
  767. #[weight = 10_000_000] // TODO: adjust weight
  768. pub fn create_series(
  769. origin,
  770. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  771. channel_id: T::ChannelId,
  772. params: SeriesParameters<T::VideoId, ContentParameters<T>>,
  773. ) -> DispatchResult {
  774. Ok(())
  775. }
  776. #[weight = 10_000_000] // TODO: adjust weight
  777. pub fn update_series(
  778. origin,
  779. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  780. channel_id: T::ChannelId,
  781. params: SeriesParameters<T::VideoId, ContentParameters<T>>,
  782. ) -> DispatchResult {
  783. Ok(())
  784. }
  785. #[weight = 10_000_000] // TODO: adjust weight
  786. pub fn delete_series(
  787. origin,
  788. owner: ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
  789. series: T::SeriesId,
  790. ) -> DispatchResult {
  791. Ok(())
  792. }
  793. }
  794. }
  795. impl<T: Trait> Module<T> {
  796. // TODO: make this private again after used in module
  797. /// Increment number of channels, maintained by each curator group
  798. pub fn increment_number_of_channels_owned_by_curator_groups(
  799. curator_group_ids: BTreeSet<T::CuratorGroupId>,
  800. ) {
  801. curator_group_ids.into_iter().for_each(|curator_group_id| {
  802. Self::increment_number_of_channels_owned_by_curator_group(curator_group_id);
  803. });
  804. }
  805. // TODO: make this private again after used in module
  806. /// Decrement number of channels, maintained by each curator group
  807. pub fn decrement_number_of_channels_owned_by_curator_groups(
  808. curator_group_ids: BTreeSet<T::CuratorGroupId>,
  809. ) {
  810. curator_group_ids.into_iter().for_each(|curator_group_id| {
  811. Self::decrement_number_of_channels_owned_by_curator_group(curator_group_id);
  812. });
  813. }
  814. // TODO: make this private again after used in module
  815. /// Increment number of channels, maintained by curator group
  816. pub fn increment_number_of_channels_owned_by_curator_group(
  817. curator_group_id: T::CuratorGroupId,
  818. ) {
  819. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  820. curator_group.increment_number_of_channels_owned_count();
  821. });
  822. }
  823. // TODO: make this private again after used in module
  824. /// Decrement number of channels, maintained by curator group
  825. pub fn decrement_number_of_channels_owned_by_curator_group(
  826. curator_group_id: T::CuratorGroupId,
  827. ) {
  828. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  829. curator_group.decrement_number_of_channels_owned_count();
  830. });
  831. }
  832. /// Ensure `CuratorGroup` under given id exists
  833. pub fn ensure_curator_group_under_given_id_exists(
  834. curator_group_id: &T::CuratorGroupId,
  835. ) -> Result<(), Error<T>> {
  836. ensure!(
  837. <CuratorGroupById<T>>::contains_key(curator_group_id),
  838. Error::<T>::CuratorGroupDoesNotExist
  839. );
  840. Ok(())
  841. }
  842. /// Ensure `CuratorGroup` under given id exists, return corresponding one
  843. pub fn ensure_curator_group_exists(
  844. curator_group_id: &T::CuratorGroupId,
  845. ) -> Result<CuratorGroup<T>, Error<T>> {
  846. Self::ensure_curator_group_under_given_id_exists(curator_group_id)?;
  847. Ok(Self::curator_group_by_id(curator_group_id))
  848. }
  849. /// Ensure all `CuratorGroup`'s under given ids exist
  850. pub fn ensure_curator_groups_exist(
  851. curator_groups: &BTreeSet<T::CuratorGroupId>,
  852. ) -> Result<(), Error<T>> {
  853. for curator_group in curator_groups {
  854. // Ensure CuratorGroup under given id exists
  855. Self::ensure_curator_group_exists(curator_group)?;
  856. }
  857. Ok(())
  858. }
  859. }
  860. // Some initial config for the module on runtime upgrade
  861. impl<T: Trait> Module<T> {
  862. pub fn on_runtime_upgrade() {
  863. <NextChannelCategoryId<T>>::put(T::ChannelCategoryId::one());
  864. <NextVideoCategoryId<T>>::put(T::VideoCategoryId::one());
  865. <NextVideoId<T>>::put(T::VideoId::one());
  866. <NextChannelId<T>>::put(T::ChannelId::one());
  867. <NextPlaylistId<T>>::put(T::PlaylistId::one());
  868. <NextSeriesId<T>>::put(T::SeriesId::one());
  869. <NextPersonId<T>>::put(T::PersonId::one());
  870. <NextChannelOwnershipTransferRequestId<T>>::put(T::ChannelOwnershipTransferRequestId::one());
  871. }
  872. }
  873. decl_event!(
  874. pub enum Event<T>
  875. where
  876. CuratorGroupId = <T as ContentActorAuthenticator>::CuratorGroupId,
  877. CuratorId = <T as ContentActorAuthenticator>::CuratorId,
  878. VideoId = <T as Trait>::VideoId,
  879. VideoCategoryId = <T as Trait>::VideoCategoryId,
  880. ChannelId = <T as StorageOwnership>::ChannelId,
  881. MemberId = <T as MembershipTypes>::MemberId,
  882. NewAsset = NewAsset<ContentParameters<T>>,
  883. ChannelCategoryId = <T as Trait>::ChannelCategoryId,
  884. ChannelOwnershipTransferRequestId = <T as Trait>::ChannelOwnershipTransferRequestId,
  885. PlaylistId = <T as Trait>::PlaylistId,
  886. SeriesId = <T as Trait>::SeriesId,
  887. PersonId = <T as Trait>::PersonId,
  888. DAOId = <T as StorageOwnership>::DAOId,
  889. ChannelOwnershipTransferRequest = ChannelOwnershipTransferRequest<T>,
  890. Series = Series<<T as StorageOwnership>::ChannelId, <T as Trait>::VideoId>,
  891. ContentParameters = ContentParameters<T>,
  892. {
  893. // Curators
  894. CuratorGroupCreated(CuratorGroupId),
  895. CuratorGroupDeleted(CuratorGroupId),
  896. CuratorGroupStatusSet(CuratorGroupId, bool /* active status */),
  897. CuratorAdded(CuratorGroupId, CuratorId),
  898. CuratorRemoved(CuratorGroupId, CuratorId),
  899. // Channels
  900. ChannelCreated(
  901. ChannelId,
  902. ChannelOwner<MemberId, CuratorGroupId, DAOId>,
  903. Vec<NewAsset>,
  904. ChannelCreationParameters<ContentParameters>,
  905. ),
  906. ChannelUpdated(
  907. ChannelId,
  908. Vec<NewAsset>,
  909. ChannelUpdateParameters<ContentParameters>,
  910. ),
  911. ChannelDeleted(ChannelId),
  912. ChannelCensored(ChannelId, Vec<u8> /* rationale */),
  913. ChannelUncensored(ChannelId, Vec<u8> /* rationale */),
  914. // Channel Ownership Transfers
  915. ChannelOwnershipTransferRequested(
  916. ChannelOwnershipTransferRequestId,
  917. ChannelOwnershipTransferRequest,
  918. ),
  919. ChannelOwnershipTransferRequestWithdrawn(ChannelOwnershipTransferRequestId),
  920. ChannelOwnershipTransferred(ChannelOwnershipTransferRequestId),
  921. // Channel Categories
  922. ChannelCategoryCreated(ChannelCategoryId, ChannelCategoryCreationParameters),
  923. ChannelCategoryUpdated(ChannelCategoryUpdateParameters),
  924. ChannelCategoryDeleted(ChannelCategoryId),
  925. // Videos
  926. VideoCategoryCreated(VideoCategoryId, VideoCategoryCreationParameters),
  927. VideoCategoryUpdated(VideoCategoryId, VideoCategoryUpdateParameters),
  928. VideoCategoryDeleted(VideoCategoryId),
  929. VideoCreated(
  930. VideoId,
  931. Vec<NewAsset>,
  932. VideoCreationParameters<ContentParameters>,
  933. ),
  934. VideoUpdated(
  935. VideoId,
  936. Vec<NewAsset>,
  937. VideoUpdateParameters<ContentParameters>,
  938. ),
  939. VideoDeleted(VideoId),
  940. VideoCensored(VideoId, Vec<u8> /* rationale */),
  941. VideoUncensored(VideoId, Vec<u8> /* rationale */),
  942. // Featured Videos
  943. FeaturedVideosSet(Vec<VideoId>),
  944. // Video Playlists
  945. PlaylistCreated(PlaylistId, PlaylistCreationParameters),
  946. PlaylistUpdated(PlaylistId, PlaylistUpdateParameters),
  947. PlaylistDeleted(PlaylistId),
  948. // Series
  949. SeriesCreated(
  950. SeriesId,
  951. Vec<NewAsset>,
  952. SeriesParameters<VideoId, ContentParameters>,
  953. Series,
  954. ),
  955. SeriesUpdated(
  956. SeriesId,
  957. Vec<NewAsset>,
  958. SeriesParameters<VideoId, ContentParameters>,
  959. Series,
  960. ),
  961. SeriesDeleted(SeriesId),
  962. // Persons
  963. PersonCreated(
  964. PersonId,
  965. Vec<NewAsset>,
  966. PersonCreationParameters<ContentParameters>,
  967. ),
  968. PersonUpdated(
  969. PersonId,
  970. Vec<NewAsset>,
  971. PersonUpdateParameters<ContentParameters>,
  972. ),
  973. PersonDeleted(PersonId),
  974. }
  975. );