diff --git a/src/base/constants/types.cairo b/src/base/constants/types.cairo index 2a8ca39..979aaee 100644 --- a/src/base/constants/types.cairo +++ b/src/base/constants/types.cairo @@ -182,7 +182,8 @@ pub struct CommunityDetails { community_metadata_uri: ByteArray, community_nft_address: ContractAddress, community_total_members: u256, - community_premium_status: bool + community_premium_status: bool, + community_type: ByteArray } // /** @@ -202,6 +203,13 @@ pub struct CommunityMember { ban_status: bool, } +#[derive(Debug, Drop, Serde, starknet::Store, Clone)] +pub struct CommunityMod { + community_id: u256, + transaction_executor: ContractAddress, + mod_address: ContractAddress, +} + // /** // * @notice An enum specifically used in a helper function to easily retrieve the publication type for integrations. // * diff --git a/src/community/community.cairo b/src/community/community.cairo index 4d3f984..bcc8655 100644 --- a/src/community/community.cairo +++ b/src/community/community.cairo @@ -15,7 +15,7 @@ mod CommunityComponent { // }; use karst::base::constants::types::{ - CommunityParams, CommunityDetails, GateKeepType, CommunityType + CommunityParams, CommunityDetails, GateKeepType, CommunityType, CommunityMod }; // ************************************************************************* @@ -25,17 +25,17 @@ mod CommunityComponent { struct Storage { communities_counts: u256, communities_owner: LegacyMap, // map - communities: LegacyMap< - u256, CommunityDetails - >, // map + communities: LegacyMap, // map member_community_id: LegacyMap< ContractAddress, u256 >, // map community_member: LegacyMap< ContractAddress, Vec >, // map - community_mod: LegacyMap, // map > - community_gate_keep: LegacyMap> + community_mod: LegacyMap>, // map + community_gate_keep: LegacyMap< + u256, Vec + > // map > } // ************************************************************************* @@ -114,7 +114,8 @@ mod CommunityComponent { community_metadata_uri: "", community_nft_address: community_param.community_nft_address, community_premium_status: community_param.community_premium_status, - community_total_members: 0 + community_total_members: 0, + community_type: "Free", }; self.communities.write(community_id, community_details); @@ -122,9 +123,9 @@ mod CommunityComponent { self .emit( CommunityCreated { - community_id: u256, - community_owner: ContractAddress, - community_nft_address: ContractAddress, + community_id: community_id, + community_owner: community_owner, + community_nft_address: community_param.community_nft_address, block_timestamp: get_block_timestamp() } ); @@ -150,21 +151,25 @@ mod CommunityComponent { let member_details = self.community_member.read(member_address); member_details.append(community_member); self.community_member.write(member_address, member_details); + + // update community member count + community.community_total_members = community.community_total_members + 1; + self.communities.write(community_id, community); } fn leave_community(ref self: ComponentState, community_id: u256) { let member_address = get_caller_address(); let community = self.communities.read(community_id); - if (!community) { + if (!community) { panic('Community does not exist') } let member_community_id = self.member_community_id.read(member_address); assert(member_community_id != community_id, "Already a member"); // remove the member_community_id - self.member_community_id.write(member_address, 0); + self.member_community_id.write(member_address, 0); - // remove member details - let community_member = CommunityMember { + // remove member details + let community_member = CommunityMember { profile_address: member_address, community_id: 0, total_publications: 0, @@ -173,16 +178,225 @@ mod CommunityComponent { }; let member_details = self.community_member.read(member_address); member_details.append(community_member); - self.community_member.write(member_address, member_details); + self.community_member.write(member_address, member_details); + + // update community member count + community.community_total_members = community.community_total_members - 1; + self.communities.write(community_id, community); + } + fn set_community_metadata_uri( + ref self: ComponentState, community_id: u256, metadata_uri: ByteArray + ) { + let community_owner = get_caller_address(); + let comminuty_main_id = self.communities_owner.read(community_owner); + assert(comminuty_main_id != community_id, "Not Community Owner"); + let community_details = self.communities.read(comminuty_main_id); + community_details.community_metadata_uri = metadata_uri; + self.communities.write(comminuty_main_id.community_details) + } + + fn add_community_mods( + ref self: ComponentState, community_id: u256, moderator: ContractAddress + ) { + // community owner should be able to set a mod + let community_owner = get_caller_address(); + let owner_community_id = self.communities_owner.read(community_owner); + let community = self.communities.read(community_id); + assert(owner_community_id != community_id, "Not Community Owner"); + let community_mod = self.community_mod.read(community_id); + let moderator_details = community_mods + .iter() + .find((community_mod), community_mod.mod_address == moderator); + if (moderator_details) { + moderator_details.community_id = community_id; + moderator_details.transaction_executor = community_owner; + moderator_details.mod_address = moderator; + community_mod.append(moderator_details); + self.community_mod.write(community_id, community_mod) + } + + let new_community_mod = CommunityMod { + community_id: community_id, + transaction_executor: community_owner, + mod_address: moderator + }; + community_mod.append(new_community_mod); + + self.community_mod.write(community_id, community_mod); + + self + .emit( + CommunityModAdded { + community_id: community_id, + transaction_executor: community_owner, + community_nft_address: community.community_nft_address, + block_timestamp: get_block_timestamp() + } + ) + } + + fn remove_community_mods( + ref self: ComponentState, community_id: u256, moderator: ContractAddress + ) { + let community_owner = get_caller_address(); + let owner_community_id = self.communities_owner.read(community_owner); + let community = self.communities.read(community_id); + assert(owner_community_id != community_id, "Not Community Owner"); + + let community_mod = self.community_mod.read(community_id); + let moderator_details = community_mods + .iter() + .find((community_mod), community_mod.mod_address == moderator); + + if (!moderator_details) { + panic!("Cannot remove mod") + } + + moderator_details.community_id = 0; + moderator_details.transaction_executor = ""; + mod_address = ""; + community_mod.append(moderator_details); + self.community_mod.write(community_id, community_mod); + self + .emit( + CommunityModRemoved { + community_id: community_id, + transaction_executor: community_owner, + community_nft_address: community.community_nft_address, + block_timestamp: get_block_timestamp() + } + ); + } + + fn set_ban_status( + ref self: ComponentState, + community_id: u256, + profile: ContractAddress, + ban_status: bool + ) { + let community_owner = get_caller_address(); + + // only community owner can take this action + let community = self.communities.read(community_id); + + assert(commuity.community_owner == community_owner, "Not Community Owner"); + + let community = self.communities.read(community_id); + if (!community) { + panic('Community does not exist'); + } + + let member_community_id = self.member_community_id.read(profile); + assert(member_community_id == community_id, "Not a member"); + + let community_members = self.community_member.read(profile); + let memeber_details = community_members + .iter() + .find((community_member), community_member.profile_address == profile); + member_details.ban_status = ban_status; + community_members.append(memeber_details); + self.community_member.write(profile, member_details); + + self + .emit( + CommunityBanStatusUpdated { + community_id: community_id, + transaction_executor: community_owner, + profile: profile, + block_timestamp: get_block_timestamp() + } + ); + } + + fn upgrade_community( + ref self: ComponentState, + community_id: u256, + upgrade_type: CommunityType + ) { + let community = self.communities.read(community_id); + if (!community) { + panic('Community does not exist'); + } + + // only owner can upgrade community + assert(commuity.community_owner == community_owner, "Not Community Owner"); + community.community_type = upgrade_type; + self.communities.write(community_id, community); + + self + .emit( + CommunityUpgraded { + community_id: community_id, + transaction_executor: community_owner, + premiumType: upgrade_type, + block_timestamp: get_block_timestamp() + } + ); + } + // IN_COMPLET + fn gatekeep( + ref self: ComponentState, + community_id: u256, + gatekeep_type: GateKeepType, + nft_contract_address: ContractAddress, + permissioned_addresses: Array + ) {} + + fn get_community( + self: @ComponentState, community_id: u256 + ) -> CommunityDetails { + self.communities.read(community_id); + } + fn get_community_metadata_uri( + self: @ComponentState, community_id: u256 + ) -> ByteArray { + let community = self.communities.read(community_id); + community.community_metadata_uri + } + fn is_community_member( + self: @ComponentState, profile: ContractAddress, community_id: u256 + ) -> (bool, u256) { + let is_community_member_id = self.member_community_id.read(profile); + if (is_community_member_id != community_id) { + (false, community_id) + } + (true, community_id) + } + fn get_total_members(self: @ComponentState, community_id: u256) -> u256 { + let community = self.communities.read(community_id); + community.community_total_members + } + + fn is_community_mod( + self: @ComponentState, profile: ContractAddress, community_id: u256 + ) -> bool { + let community_mod = self.community_mod.read(community_id); + let moderator_details = community_mods + .iter() + .find((community_mod), community_mod.mod_address == moderator); + + if (moderator_details) { + true + } + false } - fn set_community_metadata_uri(ref self: ComponentState, community_id: u256, metadata_uri: ByteArray) { - let community_owner = get_caller_address(); - let comminuty_main_id = self.communities_owner.read(community_owner); - assert(comminuty_main_id != community_id, "Not Community Owner"); - let community_details = self.communities.read(comminuty_main_id); - community_details.community_metadata_uri = metadata_uri; - self.communities.write(comminuty_main_id. community_details) - } + fn get_ban_status( + self: @ComponentState, profile: ContractAddress, community_id: u256 + ) -> bool { + let community_members = self.community_member.read(profile); + let memeber_details = community_members + .iter() + .find((community_member), community_member.profile_address == profile); + memeber_details.ban_status + } + fn is_premium_community(self: @TState, community_id: u256) -> (bool, CommunityType) { + let community = self.communities.read(community_id); + (community.community_type, community.community_premium_status) + } + // INCOMPLETE + fn is_gatekeeped(ref self: TState, community_id: u256) -> (bool, GateKeepType) { + (true, "Paid") + } } } diff --git a/src/interfaces/ICommunity.cairo b/src/interfaces/ICommunity.cairo index 04fedc5..06d3dc6 100644 --- a/src/interfaces/ICommunity.cairo +++ b/src/interfaces/ICommunity.cairo @@ -1,5 +1,5 @@ use starknet::ContractAddress; -use karst::base::constants::types::{CommunityParams, GateKeepType, CommunityType}; +use karst::base::constants::types::{CommunityParams, GateKeepType, CommunityType, CommunityDetails}; // ************************************************************************* // INTERFACE of ICommunity @@ -28,4 +28,18 @@ pub trait ICommunity { nft_contract_address: ContractAddress, permissioned_addresses: Array ); + + // ************************************************************************* + // GETTERS + // ************************************************************************* + fn get_community(self: @TState, community_id: u256) -> CommunityDetails; + fn get_community_metadata_uri(self: @TState, community_id: u256) -> ByteArray; + fn is_community_member( + self: @TState, profile: ContractAddress, community_id: u256 + ) -> (bool, u256); + fn get_total_members(self: @TState, community_id: u256) -> u256; + fn is_community_mod(self: @TState, profile: ContractAddress, community_id: u256) -> bool; + fn get_ban_status(self: @TState, profile: ContractAddress, channel_id: u256) -> bool; + fn is_premium_community(self: @TState, community_id: u256) -> (bool, CommunityType); + fn is_gatekeeped(ref self: TState, community_id: u256) -> (bool, GateKeepType); }