lib.rs 39 KB

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