refactor(community): add all community function in the backend

This commit is contained in:
Jonathan Rainville 2021-12-16 12:14:55 -05:00 committed by Sale Djenic
parent 0388688e9e
commit d5a3ead0b6
20 changed files with 693 additions and 175 deletions

View File

@ -18,7 +18,7 @@ type
events: EventEmitter events: EventEmitter
contactsService: contact_service.Service contactsService: contact_service.Service
chatService: chat_service.Service chatService: chat_service.Service
communityService: community_service.ServiceInterface communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
activeSectionId: string activeSectionId: string
activeChatId: string activeChatId: string
@ -27,7 +27,7 @@ type
searchTerm: string searchTerm: string
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, contactsService: contact_service.Service, proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, contactsService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service): Controller = messageService: message_service.Service): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate

View File

@ -22,12 +22,12 @@ type
isUsersListAvailable: bool #users list is not available for 1:1 chat isUsersListAvailable: bool #users list is not available for 1:1 chat
contactService: contact_service.Service contactService: contact_service.Service
chatService: chat_service.Service chatService: chat_service.Service
communityService: community_service.ServiceInterface communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, chatId: string, proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service): Controller = messageService: message_service.Service): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate

View File

@ -11,7 +11,7 @@ type
delegate: io_interface.AccessInterface delegate: io_interface.AccessInterface
chatId: string chatId: string
belongsToCommunity: bool belongsToCommunity: bool
communityService: community_service.ServiceInterface communityService: community_service.Service
chatService: chat_service.Service chatService: chat_service.Service
proc newController*( proc newController*(
@ -19,7 +19,7 @@ proc newController*(
chatId: string, chatId: string,
belongsToCommunity: bool, belongsToCommunity: bool,
chatService: chat_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface communityService: community_service.Service
): Controller = ): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate

View File

@ -5,7 +5,7 @@ import view, controller
import ../../../../../global/global_singleton import ../../../../../global/global_singleton
import ../../../../../../app_service/service/chat/service as chat_service import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/community/service_interface as community_service import ../../../../../../app_service/service/community/service as community_service
export io_interface export io_interface
@ -22,7 +22,7 @@ proc newModule*(
chatId: string, chatId: string,
belongsToCommunity: bool, belongsToCommunity: bool,
chatService: chat_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface communityService: community_service.Service
): ):
Module = Module =
result = Module() result = Module()

View File

@ -35,7 +35,7 @@ type
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string, proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service): messageService: message_service.Service):
Module = Module =
result = Module() result = Module()

View File

@ -3,7 +3,7 @@ import controller_interface
import io_interface import io_interface
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/community/service_interface as community_service import ../../../../../../app_service/service/community/service as community_service
import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
@ -19,12 +19,12 @@ type
belongsToCommunity: bool belongsToCommunity: bool
isUsersListAvailable: bool #users list is not available for 1:1 chat isUsersListAvailable: bool #users list is not available for 1:1 chat
contactService: contact_service.Service contactService: contact_service.Service
communityService: community_service.ServiceInterface communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string, proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
communityService: community_service.ServiceInterface, messageService: message_service.Service): communityService: community_service.Service, messageService: message_service.Service):
Controller = Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate

View File

@ -5,7 +5,7 @@ import view, item, model, controller
import ../../../../../global/global_singleton import ../../../../../global/global_singleton
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/community/service_interface as community_service import ../../../../../../app_service/service/community/service as community_service
import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
@ -22,7 +22,7 @@ type
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string, proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
communityService: community_service.ServiceInterface, messageService: message_service.Service): communityService: community_service.Service, messageService: message_service.Service):
Module = Module =
result = Module() result = Module()
result.delegate = delegate result.delegate = delegate

View File

@ -5,7 +5,7 @@ import io_interface
import ../../../../app_service/service/contacts/service as contact_service import ../../../../app_service/service/contacts/service as contact_service
import ../../../../app_service/service/chat/service as chat_service import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/community/service_interface as community_service import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service import ../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
@ -22,12 +22,12 @@ type
events: EventEmitter events: EventEmitter
contactService: contact_service.Service contactService: contact_service.Service
chatService: chat_service.Service chatService: chat_service.Service
communityService: community_service.ServiceInterface communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
proc newController*(delegate: io_interface.AccessInterface, sectionId: string, isCommunity: bool, events: EventEmitter, proc newController*(delegate: io_interface.AccessInterface, sectionId: string, isCommunity: bool, events: EventEmitter,
contactService: contact_service.Service, chatService: chat_service.Service, contactService: contact_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, messageService: message_service.Service): Controller = communityService: community_service.Service, messageService: message_service.Service): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate
result.sectionId = sectionId result.sectionId = sectionId

View File

@ -7,7 +7,7 @@ import chat_content/module as chat_content_module
import ../../../../app_service/service/contacts/service as contact_service import ../../../../app_service/service/contacts/service as contact_service
import ../../../../app_service/service/chat/service as chat_service import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/community/service_interface as community_service import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service import ../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
@ -34,7 +34,7 @@ proc newModule*(
isCommunity: bool, isCommunity: bool,
contactService: contact_service.Service, contactService: contact_service.Service,
chatService: chat_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, communityService: community_service.Service,
messageService: message_service.Service messageService: message_service.Service
): Module = ): Module =
result = Module() result = Module()
@ -60,7 +60,7 @@ method isCommunity*(self: Module): bool =
proc addSubmodule(self: Module, chatId: string, belongToCommunity: bool, isUsersListAvailable: bool, events: EventEmitter, proc addSubmodule(self: Module, chatId: string, belongToCommunity: bool, isUsersListAvailable: bool, events: EventEmitter,
contactService: contact_service.Service, chatService: chat_service.Service, contactService: contact_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, messageService: message_service.Service) = communityService: community_service.Service, messageService: message_service.Service) =
self.chatContentModule[chatId] = chat_content_module.newModule(self, events, self.controller.getMySectionId(), chatId, self.chatContentModule[chatId] = chat_content_module.newModule(self, events, self.controller.getMySectionId(), chatId,
belongToCommunity, isUsersListAvailable, contactService, chatService, communityService, messageService) belongToCommunity, isUsersListAvailable, contactService, chatService, communityService, messageService)
@ -70,7 +70,7 @@ proc removeSubmodule(self: Module, chatId: string) =
self.chatContentModule.del(chatId) self.chatContentModule.del(chatId)
proc buildChatUI(self: Module, events: EventEmitter, contactService: contact_service.Service, proc buildChatUI(self: Module, events: EventEmitter, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service) = messageService: message_service.Service) =
let types = @[ChatType.OneToOne, ChatType.Public, ChatType.PrivateGroupChat] let types = @[ChatType.OneToOne, ChatType.Public, ChatType.PrivateGroupChat]
let chats = self.controller.getChatDetailsForChatTypes(types) let chats = self.controller.getChatDetailsForChatTypes(types)
@ -99,7 +99,7 @@ proc buildChatUI(self: Module, events: EventEmitter, contactService: contact_ser
self.setActiveItemSubItem(selectedItemId, "") self.setActiveItemSubItem(selectedItemId, "")
proc buildCommunityUI(self: Module, events: EventEmitter, contactService: contact_service.Service, proc buildCommunityUI(self: Module, events: EventEmitter, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service) = messageService: message_service.Service) =
var selectedItemId = "" var selectedItemId = ""
var selectedSubItemId = "" var selectedSubItemId = ""
@ -160,7 +160,7 @@ proc buildCommunityUI(self: Module, events: EventEmitter, contactService: contac
self.setActiveItemSubItem(selectedItemId, selectedSubItemId) self.setActiveItemSubItem(selectedItemId, selectedSubItemId)
method load*(self: Module, events: EventEmitter, contactService: contact_service.Service, method load*(self: Module, events: EventEmitter, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service) = messageService: message_service.Service) =
self.controller.init() self.controller.init()
self.view.load() self.view.load()
@ -243,7 +243,7 @@ method createPublicChat*(self: Module, chatId: string) =
self.controller.createPublicChat(chatId) self.controller.createPublicChat(chatId)
method addNewChat*(self: Module, chatDto: ChatDto, events: EventEmitter, contactService: contact_service.Service, method addNewChat*(self: Module, chatDto: ChatDto, events: EventEmitter, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service) = messageService: message_service.Service) =
let hasNotification = chatDto.unviewedMessagesCount > 0 or chatDto.unviewedMentionsCount > 0 let hasNotification = chatDto.unviewedMessagesCount > 0 or chatDto.unviewedMentionsCount > 0
let notificationsCount = chatDto.unviewedMentionsCount let notificationsCount = chatDto.unviewedMentionsCount

View File

@ -2,7 +2,7 @@ import NimQml
import ../../../../../app_service/service/contacts/service as contact_service import ../../../../../app_service/service/contacts/service as contact_service
import ../../../../../app_service/service/chat/service as chat_service import ../../../../../app_service/service/chat/service as chat_service
import ../../../../../app_service/service/community/service_interface as community_service import ../../../../../app_service/service/community/service as community_service
import ../../../../../app_service/service/message/service as message_service import ../../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
@ -11,7 +11,7 @@ method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface, events: EventEmitter, contactService: contact_service.Service, method load*(self: AccessInterface, events: EventEmitter, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.ServiceInterface, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service) {.base.} = messageService: message_service.Service) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -3,7 +3,7 @@ method activeItemSubItemSet*(self: AccessInterface, itemId: string, subItemId: s
method addNewChat*(self: AccessInterface, chatDto: ChatDto, events: EventEmitter, method addNewChat*(self: AccessInterface, chatDto: ChatDto, events: EventEmitter,
contactService: contact_service.Service, chatService: chat_service.Service, contactService: contact_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, messageService: message_service.Service) {.base.} = communityService: community_service.Service, messageService: message_service.Service) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onChatMuted*(self: AccessInterface, chatId: string) {.base.} = method onChatMuted*(self: AccessInterface, chatId: string) {.base.} =

View File

@ -31,6 +31,140 @@ method init*[T](self: Controller[T]) =
let communities = self.communityService.getAllCommunities() let communities = self.communityService.getAllCommunities()
self.delegate.setAllCommunities(communities) self.delegate.setAllCommunities(communities)
self.events.on(SIGNAL_COMMUNITY_MY_REQUEST_ADDED) do(e:Args):
let args = CommunityRequestArgs(e)
# TODO process the request being added
self.events.on(SIGNAL_COMMUNITY_LEFT) do(e:Args):
let args = CommunityIdArgs(e)
# TODO process the community being left
self.events.on(SIGNAL_COMMUNITY_CREATED) do(e:Args):
let args = CommunityArgs(e)
# TODO process the community being created
self.events.on(SIGNAL_COMMUNITY_CHANNEL_CREATED) do(e:Args):
let args = CommunityChatArgs(e)
# TODO process the community chat being created
self.events.on(SIGNAL_COMMUNITY_CHANNEL_EDITED) do(e:Args):
let args = CommunityChatArgs(e)
# TODO process the community chat being edited
self.events.on(SIGNAL_COMMUNITY_CHANNEL_REORDERED) do(e:Args):
let args = CommunityChatOrderArgs(e)
# TODO process the community chat being reordered
self.events.on(SIGNAL_COMMUNITY_CHANNEL_DELETED) do(e:Args):
let args = CommunityChatIdArgs(e)
# TODO process the community chat being deleted
self.events.on(SIGNAL_COMMUNITY_CATEGORY_CREATED) do(e:Args):
let args = CommunityCategoryArgs(e)
# TODO process the community category being created
self.events.on(SIGNAL_COMMUNITY_CATEGORY_EDITED) do(e:Args):
let args = CommunityCategoryArgs(e)
# TODO process the community category being edited
self.events.on(SIGNAL_COMMUNITY_CATEGORY_DELETED) do(e:Args):
let args = CommunityCategoryArgs(e)
# TODO process the community category being deleted
method joinCommunity*[T](self: Controller[T], communityId: string): string = method joinCommunity*[T](self: Controller[T], communityId: string): string =
self.communityService.joinCommunity(communityId) self.communityService.joinCommunity(communityId)
method requestToJoinCommunity*[T](self: Controller[T], communityId: string, ensName: string) =
self.communityService.requestToJoinCommunity(communityId, ensName)
method leaveCommunity*[T](self: Controller[T], communityId: string) =
self.communityService.leaveCommunity(communityId)
method createCommunity*[T](
self: Controller[T],
name: string,
description: string,
access: int,
ensOnly: bool,
color: string,
imageUrl: string,
aX: int, aY: int, bX: int, bY: int) =
self.communityService.createCommunity(
name,
description,
access,
ensOnly,
color,
imageUrl,
aX, aY, bX, bY)
method createCommunityChannel*[T](
self: Controller[T],
communityId: string,
name: string,
description: string) =
self.communityService.createCommunityChannel(communityId, name, description)
method editCommunityChannel*[T](
self: Controller[T],
communityId: string,
channelId: string,
name: string,
description: string,
categoryId: string,
position: int) =
self.communityService.editCommunityChannel(
communityId,
channelId,
name,
description,
categoryId,
position)
method reorderCommunityChat*[T](
self: Controller[T],
communityId: string,
categoryId: string,
chatId: string,
position: int) =
self.communityService.reorderCommunityChat(
communityId,
categoryId,
chatId,
position)
method deleteCommunityChat*[T](
self: Controller[T],
communityId: string,
chatId: string) =
self.communityService.deleteCommunityChat(communityId, chatId)
method createCommunityCategory*[T](
self: Controller[T],
communityId: string,
name: string,
channels: seq[string]) =
self.communityService.createCommunityCategory(communityId, name, channels)
method editCommunityCategory*[T](
self: Controller[T],
communityId: string,
categoryId: string,
name: string,
channels: seq[string]) =
self.communityService.editCommunityCategory(communityId, categoryId, name, channels)
method deleteCommunityCategory*[T](
self: Controller[T],
communityId: string,
categoryId: string) =
self.communityService.deleteCommunityCategory(communityId, categoryId)
method requestCommunityInfo*[T](self: Controller[T], communityId: string) =
self.communityService.requestCommunityInfo(communityId)
method importCommunity*[T](self: Controller[T], communityKey: string) =
self.communityService.importCommunity(communityKey)
method exportCommunity*[T](self: Controller[T], communityId: string): string =
self.communityService.exportCommunity(communityId)

View File

@ -13,6 +13,45 @@ method init*(self: AccessInterface) {.base.} =
method joinCommunity*(self: AccessInterface, communityId: string): string {.base.} = method joinCommunity*(self: AccessInterface, communityId: string): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method requestToJoinCommunity*(self: AccessInterface, communityId: string, ensName: string) {.base.} =
raise newException(ValueError, "No implementation available")
method leaveCommunity*(self: AccessInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunity*(self: AccessInterface, name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunityChannel*(self: AccessInterface, communityId: string, name: string, description: string) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunityChannel*(self: AccessInterface, communityId: string, chatId: string, name: string, description: string, categoryId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
method reorderCommunityChat*(self: AccessInterface, communityId: string, categoryId: string, chatId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
method deleteCommunityChat*(self: AccessInterface, communityId: string, chatId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunityCategory*(self: AccessInterface, communityId: string, name: string, channels: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunityCategory*(self: AccessInterface, communityId: string, categoryId: string, name: string, channels: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method deleteCommunityCategory*(self: AccessInterface, communityId: string, categoryId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method requestCommunityInfo*(self: AccessInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method importCommunity*(self: AccessInterface, communityKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method exportCommunity*(self: AccessInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
type type
## Abstract class (concept) which must be implemented by object/s used in this ## Abstract class (concept) which must be implemented by object/s used in this
## module. ## module.

View File

@ -25,7 +25,7 @@ type
keychainService: keychain_service.Service keychainService: keychain_service.Service
accountsService: accounts_service.ServiceInterface accountsService: accounts_service.ServiceInterface
chatService: chat_service.Service chatService: chat_service.Service
communityService: community_service.ServiceInterface communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
contactsService: contacts_service.Service contactsService: contacts_service.Service
activeSectionId: string activeSectionId: string
@ -36,7 +36,7 @@ proc newController*(delegate: io_interface.AccessInterface,
keychainService: keychain_service.Service, keychainService: keychain_service.Service,
accountsService: accounts_service.ServiceInterface, accountsService: accounts_service.ServiceInterface,
chatService: chat_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, communityService: community_service.Service,
contactsService: contacts_service.Service, contactsService: contacts_service.Service,
messageService: message_service.Service): messageService: message_service.Service):
Controller = Controller =

View File

@ -1,5 +1,5 @@
import ../shared_models/section_item import ../shared_models/section_item
import ../../../app_service/service/community/service_interface as community_service import ../../../app_service/service/community/service as community_service
type type
AccessInterface* {.pure inheritable.} = ref object of RootObj AccessInterface* {.pure inheritable.} = ref object of RootObj

View File

@ -395,7 +395,7 @@ method communityJoined*[T](
events: EventEmitter, events: EventEmitter,
contactsService: contacts_service.Service, contactsService: contacts_service.Service,
chatService: chat_service.Service, chatService: chat_service.Service,
communityService: community_service.ServiceInterface, communityService: community_service.Service,
messageService: message_service.Service messageService: message_service.Service
) = ) =
self.communitySectionsModule[community.id] = chat_section_module.newModule( self.communitySectionsModule[community.id] = chat_section_module.newModule(

View File

@ -18,5 +18,5 @@ method enableSection*(self: AccessInterface, sectionType: SectionType) {.base.}
method disableSection*(self: AccessInterface, sectionType: SectionType) {.base.} = method disableSection*(self: AccessInterface, sectionType: SectionType) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method communityJoined*(self: AccessInterface, community: CommunityDto, events: EventEmitter, contactsService: contacts_service.Service, chatService: chat_service.Service, communityService: community_service.ServiceInterface, messageService: message_service.Service) {.base.} = method communityJoined*(self: AccessInterface, community: CommunityDto, events: EventEmitter, contactsService: contacts_service.Service, chatService: chat_service.Service, communityService: community_service.Service, messageService: message_service.Service) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -57,6 +57,14 @@ type CommunityDto* = object
isMember*: bool isMember*: bool
muted*: bool muted*: bool
type CommunityMembershipRequestDto* = object
id*: string
publicKey*: string
chatId*: string
communityId*: string
state*: int
our*: string
proc toPermission(jsonObj: JsonNode): Permission = proc toPermission(jsonObj: JsonNode): Permission =
result = Permission() result = Permission()
discard jsonObj.getProp("access", result.access) discard jsonObj.getProp("access", result.access)
@ -73,7 +81,7 @@ proc toImages(jsonObj: JsonNode): Images =
if(jsonObj.getProp("thumbnail", thumbnailObj)): if(jsonObj.getProp("thumbnail", thumbnailObj)):
discard thumbnailObj.getProp("uri", result.thumbnail) discard thumbnailObj.getProp("uri", result.thumbnail)
proc toChat(jsonObj: JsonNode): Chat = proc toChat*(jsonObj: JsonNode): Chat =
result = Chat() result = Chat()
discard jsonObj.getProp("id", result.id) discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("name", result.name) discard jsonObj.getProp("name", result.name)
@ -87,13 +95,14 @@ proc toChat(jsonObj: JsonNode): Chat =
discard jsonObj.getProp("position", result.position) discard jsonObj.getProp("position", result.position)
discard jsonObj.getProp("categoryID", result.categoryId) discard jsonObj.getProp("categoryID", result.categoryId)
proc toCategory(jsonObj: JsonNode): Category = proc toCategory*(jsonObj: JsonNode): Category =
result = Category() result = Category()
if (not jsonObj.getProp("category_id", result.id)):
discard jsonObj.getProp("id", result.id) discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("name", result.name) discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("position", result.position) discard jsonObj.getProp("position", result.position)
proc toMember(jsonObj: JsonNode, memberId: string): Member = proc toMember*(jsonObj: JsonNode, memberId: string): Member =
# Mapping this DTO is not strightforward since only keys are used for id. We # Mapping this DTO is not strightforward since only keys are used for id. We
# handle it a bit different. # handle it a bit different.
result = Member() result = Member()
@ -144,6 +153,15 @@ proc toCommunityDto*(jsonObj: JsonNode): CommunityDto =
discard jsonObj.getProp("isMember", result.isMember) discard jsonObj.getProp("isMember", result.isMember)
discard jsonObj.getProp("muted", result.muted) discard jsonObj.getProp("muted", result.muted)
proc toCommunityMembershipRequestDto*(jsonObj: JsonNode): CommunityMembershipRequestDto =
result = CommunityMembershipRequestDto()
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("publicKey", result.publicKey)
discard jsonObj.getProp("chatId", result.chatId)
discard jsonObj.getProp("state", result.state)
discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("our", result.our)
proc parseCommunities*(response: RpcResponse[JsonNode]): seq[CommunityDto] = proc parseCommunities*(response: RpcResponse[JsonNode]): seq[CommunityDto] =
result = map(response.result.getElems(), result = map(response.result.getElems(),
proc(x: JsonNode): CommunityDto = x.toCommunityDto()) proc(x: JsonNode): CommunityDto = x.toCommunityDto())

View File

@ -1,14 +1,11 @@
import Tables, json, sequtils, std/algorithm, strformat, chronicles import NimQml, Tables, json, sequtils, std/algorithm, strformat, chronicles, json_serialization
import eventemitter import eventemitter
import service_interface, ./dto/community import ./dto/community as community_dto
export community_dto
import ../chat/service as chat_service
import status/statusgo_backend_new/communities as status_go import status/statusgo_backend_new/communities as status_go
export service_interface
logScope: logScope:
topics = "community-service" topics = "community-service"
@ -17,29 +14,67 @@ type
CommunityArgs* = ref object of Args CommunityArgs* = ref object of Args
community*: CommunityDto community*: CommunityDto
CommunityChatArgs* = ref object of Args
chat*: Chat
CommunityIdArgs* = ref object of Args
communityId*: string
CommunityChatIdArgs* = ref object of Args
communityId*: string
chatId*: string
CommunityRequestArgs* = ref object of Args
communityRequest*: CommunityMembershipRequestDto
CommunityChatOrderArgs* = ref object of Args
communityId*: string
chatId*: string
categoryId*: string
position*: int
CommunityCategoryArgs* = ref object of Args
communityId*: string
category*: Category
channels*: seq[string]
# Signals which may be emitted by this service: # Signals which may be emitted by this service:
const SIGNAL_COMMUNITY_JOINED* = "SIGNAL_COMMUNITY_JOINED" const SIGNAL_COMMUNITY_JOINED* = "SIGNAL_COMMUNITY_JOINED"
const SIGNAL_COMMUNITY_MY_REQUEST_ADDED* = "SIGNAL_COMMUNITY_MY_REQUEST_ADDED"
const SIGNAL_COMMUNITY_LEFT* = "SIGNAL_COMMUNITY_LEFT"
const SIGNAL_COMMUNITY_CREATED* = "SIGNAL_COMMUNITY_CREATED"
const SIGNAL_COMMUNITY_CHANNEL_CREATED* = "SIGNAL_COMMUNITY_CHANNEL_CREATED"
const SIGNAL_COMMUNITY_CHANNEL_EDITED* = "SIGNAL_COMMUNITY_CHANNEL_EDITED"
const SIGNAL_COMMUNITY_CHANNEL_REORDERED* = "SIGNAL_COMMUNITY_CHANNEL_REORDERED"
const SIGNAL_COMMUNITY_CHANNEL_DELETED* = "SIGNAL_COMMUNITY_CHANNEL_DELETED"
const SIGNAL_COMMUNITY_CATEGORY_CREATED* = "SIGNAL_COMMUNITY_CATEGORY_CREATED"
const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "SIGNAL_COMMUNITY_CATEGORY_EDITED"
const SIGNAL_COMMUNITY_CATEGORY_DELETED* = "SIGNAL_COMMUNITY_CATEGORY_DELETED"
type QtObject:
Service* = ref object of service_interface.ServiceInterface type
Service* = ref object of QObject
events: EventEmitter events: EventEmitter
joinedCommunities: Table[string, CommunityDto] # [community_id, CommunityDto] joinedCommunities: Table[string, CommunityDto] # [community_id, CommunityDto]
allCommunities: Table[string, CommunityDto] # [community_id, CommunityDto] allCommunities: Table[string, CommunityDto] # [community_id, CommunityDto]
myCommunityRequests*: seq[CommunityMembershipRequestDto]
# Forward declaration # Forward declaration
method loadAllCommunities(self: Service): seq[CommunityDto] proc loadAllCommunities(self: Service): seq[CommunityDto]
method loadJoinedComunities(self: Service): seq[CommunityDto] proc loadJoinedComunities(self: Service): seq[CommunityDto]
proc loadMyPendingRequestsToJoin*(self: Service)
method delete*(self: Service) = proc delete*(self: Service) =
discard discard
proc newService*(events: EventEmitter): Service = proc newService*(events: EventEmitter): Service =
result = Service() result = Service()
result.events = events result.events = events
result.joinedCommunities = initTable[string, CommunityDto]() result.joinedCommunities = initTable[string, CommunityDto]()
result.allCommunities = initTable[string, CommunityDto]() result.allCommunities = initTable[string, CommunityDto]()
result.myCommunityRequests = @[]
method init*(self: Service) = proc init*(self: Service) =
try: try:
let joinedCommunities = self.loadJoinedComunities() let joinedCommunities = self.loadJoinedComunities()
for community in joinedCommunities: for community in joinedCommunities:
@ -49,36 +84,38 @@ method init*(self: Service) =
for community in allCommunities: for community in allCommunities:
self.allCommunities[community.id] = community self.allCommunities[community.id] = community
self.loadMyPendingRequestsToJoin()
except Exception as e: except Exception as e:
let errDesription = e.msg let errDesription = e.msg
error "error: ", errDesription error "error: ", errDesription
return return
method loadAllCommunities(self: Service): seq[CommunityDto] = proc loadAllCommunities(self: Service): seq[CommunityDto] =
let response = status_go.getAllCommunities() let response = status_go.getAllCommunities()
return parseCommunities(response) return parseCommunities(response)
method loadJoinedComunities(self: Service): seq[CommunityDto] = proc loadJoinedComunities(self: Service): seq[CommunityDto] =
let response = status_go.getJoinedComunities() let response = status_go.getJoinedComunities()
return parseCommunities(response) return parseCommunities(response)
method getJoinedCommunities*(self: Service): seq[CommunityDto] = proc getJoinedCommunities*(self: Service): seq[CommunityDto] =
return toSeq(self.joinedCommunities.values) return toSeq(self.joinedCommunities.values)
method getAllCommunities*(self: Service): seq[CommunityDto] = proc getAllCommunities*(self: Service): seq[CommunityDto] =
return toSeq(self.allCommunities.values) return toSeq(self.allCommunities.values)
method getCommunityById*(self: Service, communityId: string): CommunityDto = proc getCommunityById*(self: Service, communityId: string): CommunityDto =
if(not self.joinedCommunities.hasKey(communityId)): if(not self.joinedCommunities.hasKey(communityId)):
error "error: requested community doesn't exists" error "error: requested community doesn't exists"
return return
return self.joinedCommunities[communityId] return self.joinedCommunities[communityId]
method getCommunityIds*(self: Service): seq[string] = proc getCommunityIds*(self: Service): seq[string] =
return toSeq(self.joinedCommunities.keys) return toSeq(self.joinedCommunities.keys)
proc sortAsc[T](t1, t2: T): int = proc sortAsc[T](t1, t2: T): int =
if(t1.position > t2.position): if(t1.position > t2.position):
return 1 return 1
elif (t1.position < t2.position): elif (t1.position < t2.position):
@ -86,7 +123,7 @@ proc sortAsc[T](t1, t2: T): int =
else: else:
return 0 return 0
proc sortDesc[T](t1, t2: T): int = proc sortDesc[T](t1, t2: T): int =
if(t1.position < t2.position): if(t1.position < t2.position):
return 1 return 1
elif (t1.position > t2.position): elif (t1.position > t2.position):
@ -94,7 +131,7 @@ proc sortDesc[T](t1, t2: T): int =
else: else:
return 0 return 0
method getCategories*(self: Service, communityId: string, order: SortOrder = SortOrder.Ascending): seq[Category] = proc getCategories*(self: Service, communityId: string, order: SortOrder = SortOrder.Ascending): seq[Category] =
if(not self.joinedCommunities.contains(communityId)): if(not self.joinedCommunities.contains(communityId)):
error "trying to get community categories for an unexisting community id" error "trying to get community categories for an unexisting community id"
return return
@ -105,7 +142,7 @@ method getCategories*(self: Service, communityId: string, order: SortOrder = Sor
else: else:
result.sort(sortDesc[Category]) result.sort(sortDesc[Category])
method getChats*(self: Service, communityId: string, categoryId = "", order = SortOrder.Ascending): seq[Chat] = proc getChats*(self: Service, communityId: string, categoryId = "", order = SortOrder.Ascending): seq[Chat] =
## By default returns chats which don't belong to any category, for passed `communityId`. ## By default returns chats which don't belong to any category, for passed `communityId`.
## If `categoryId` is set then only chats belonging to that category for passed `communityId` will be returned. ## If `categoryId` is set then only chats belonging to that category for passed `communityId` will be returned.
## Returned chats are sorted by position following set `order` parameter. ## Returned chats are sorted by position following set `order` parameter.
@ -124,7 +161,7 @@ method getChats*(self: Service, communityId: string, categoryId = "", order = So
else: else:
result.sort(sortDesc[Chat]) result.sort(sortDesc[Chat])
method getAllChats*(self: Service, communityId: string, order = SortOrder.Ascending): seq[Chat] = proc getAllChats*(self: Service, communityId: string, order = SortOrder.Ascending): seq[Chat] =
## Returns all chats belonging to the community with passed `communityId`, sorted by position. ## Returns all chats belonging to the community with passed `communityId`, sorted by position.
## Returned chats are sorted by position following set `order` parameter. ## Returned chats are sorted by position following set `order` parameter.
if(not self.joinedCommunities.contains(communityId)): if(not self.joinedCommunities.contains(communityId)):
@ -138,17 +175,17 @@ method getAllChats*(self: Service, communityId: string, order = SortOrder.Ascend
else: else:
result.sort(sortDesc[Chat]) result.sort(sortDesc[Chat])
method isUserMemberOfCommunity*(self: Service, communityId: string): bool = proc isUserMemberOfCommunity*(self: Service, communityId: string): bool =
if(not self.allCommunities.contains(communityId)): if(not self.allCommunities.contains(communityId)):
return false return false
return self.allCommunities[communityId].joined and self.allCommunities[communityId].isMember return self.allCommunities[communityId].joined and self.allCommunities[communityId].isMember
method userCanJoin*(self: Service, communityId: string): bool = proc userCanJoin*(self: Service, communityId: string): bool =
if(not self.allCommunities.contains(communityId)): if(not self.allCommunities.contains(communityId)):
return false return false
return self.allCommunities[communityId].canJoin return self.allCommunities[communityId].canJoin
method joinCommunity*(self: Service, communityId: string): string = proc joinCommunity*(self: Service, communityId: string): string =
result = "" result = ""
try: try:
if (not self.userCanJoin(communityId) or self.isUserMemberOfCommunity(communityId)): if (not self.userCanJoin(communityId) or self.isUserMemberOfCommunity(communityId)):
@ -161,3 +198,251 @@ method joinCommunity*(self: Service, communityId: string): string =
except Exception as e: except Exception as e:
error "Error joining the community", msg = e.msg error "Error joining the community", msg = e.msg
result = fmt"Error joining the community: {e.msg}" result = fmt"Error joining the community: {e.msg}"
proc requestToJoinCommunity*(self: Service, communityId: string, ensName: string) =
try:
let response = status_go.requestToJoinCommunity(communityId, ensName)
if response.result{"requestsToJoinCommunity"} != nil and response.result{"requestsToJoinCommunity"}.kind != JNull:
for jsonCommunityReqest in response.result["requestsToJoinCommunity"]:
let communityRequest = jsonCommunityReqest.toCommunityMembershipRequestDto()
self.myCommunityRequests.add(communityRequest)
self.events.emit(SIGNAL_COMMUNITY_MY_REQUEST_ADDED, CommunityRequestArgs(communityRequest: communityRequest))
except Exception as e:
error "Error requesting to join the community", msg = e.msg, communityId, ensName
proc loadMyPendingRequestsToJoin*(self: Service) =
try:
let response = status_go.myPendingRequestsToJoin()
if response.result.kind != JNull:
for jsonCommunityReqest in response.result:
let communityRequest = jsonCommunityReqest.toCommunityMembershipRequestDto()
self.myCommunityRequests.add(communityRequest)
self.events.emit(SIGNAL_COMMUNITY_MY_REQUEST_ADDED, CommunityRequestArgs(communityRequest: communityRequest))
except Exception as e:
error "Error fetching my community requests", msg = e.msg
proc leaveCommunity*(self: Service, communityId: string) =
try:
discard status_go.leaveCommunity(communityId)
self.events.emit(SIGNAL_COMMUNITY_LEFT, CommunityIdArgs(communityId: communityId))
except Exception as e:
error "Error leaving community", msg = e.msg, communityId
proc createCommunity*(
self: Service,
name: string,
description: string,
access: int,
ensOnly: bool,
color: string,
imageUrl: string,
aX: int, aY: int, bX: int, bY: int) =
try:
let response = status_go.createCommunity(
name,
description,
access,
ensOnly,
color,
imageUrl,
aX, aY, bX, bY)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error creating community: " & error.message)
if response.result != nil and response.result.kind != JNull:
let community = response.result["communities"][0].toCommunityDto()
self.events.emit(SIGNAL_COMMUNITY_CREATED, CommunityArgs(community: community))
except Exception as e:
error "Error creating community", msg = e.msg
raise newException(RpcException, "Error creating community: " & e.msg)
proc createCommunityChannel*(
self: Service,
communityId: string,
name: string,
description: string) =
try:
let response = status_go.createCommunityChannel(communityId, name, description)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error creating community channel: " & error.message)
if response.result != nil and response.result.kind != JNull:
let chat = response.result["chats"][0].toChat()
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CREATED, CommunityChatArgs(chat: chat))
except Exception as e:
error "Error creating community channel", msg = e.msg, communityId, name, description
raise newException(RpcException, "Error creating community channel: " & e.msg)
proc editCommunityChannel*(
self: Service,
communityId: string,
channelId: string,
name: string,
description: string,
categoryId: string,
position: int) =
try:
let response = status_go.editCommunityChannel(
communityId,
channelId,
name,
description,
categoryId,
position)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error editing community channel: " & error.message)
if response.result != nil and response.result.kind != JNull:
let chat = response.result["chats"][0].toChat()
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_EDITED, CommunityChatArgs(chat: chat))
except Exception as e:
error "Error editing community channel", msg = e.msg, communityId, channelId
raise newException(RpcException, "Error editing community channel: " & e.msg)
proc reorderCommunityChat*(
self: Service,
communityId: string,
categoryId: string,
chatId: string,
position: int) =
try:
let response = status_go.reorderCommunityChat(
communityId,
categoryId,
chatId,
position)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error reordering community channel: " & error.message)
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED,
CommunityChatOrderArgs(
communityId: communityId,
categoryId: categoryId,
chatId: chatId,
position: position
)
)
except Exception as e:
error "Error reordering community channel", msg = e.msg, communityId, chatId, position
raise newException(RpcException, "Error reordering community channel: " & e.msg)
proc deleteCommunityChat*(self: Service, communityId: string, chatId: string) =
try:
let response = status_go.deleteCommunityChat(communityId, chatId)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error deleting community chat: " & error.message)
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_DELETED,
CommunityChatIdArgs(
communityId: communityId,
chatId: chatId
)
)
except Exception as e:
error "Error deleting community channel", msg = e.msg, communityId, chatId
raise newException(RpcException, "Error deleting community channel: " & e.msg)
proc createCommunityCategory*(
self: Service,
communityId: string,
name: string,
channels: seq[string]) =
try:
let response = status_go.createCommunityCategory(communityId, name, channels)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error creating community category: " & error.message)
if response.result != nil and response.result.kind != JNull:
for k, v in response.result["communityChanges"].getElems()[0]["categoriesAdded"].pairs():
let category = v.toCategory()
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_CREATED,
CommunityCategoryArgs(communityId: communityId, category: category, channels: channels))
except Exception as e:
error "Error creating community category", msg = e.msg, communityId, name
raise newException(RpcException, "Error creating community category: " & e.msg)
proc editCommunityCategory*(
self: Service,
communityId: string,
categoryId: string,
name: string,
channels: seq[string]) =
try:
let response = status_go.editCommunityCategory(communityId, categoryId, name, channels)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error creating community category: " & error.message)
if response.result != nil and response.result.kind != JNull:
for k, v in response.result["communityChanges"].getElems()[0]["categoriesModified"].pairs():
let category = v.toCategory()
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_EDITED,
CommunityCategoryArgs(communityId: communityId, category: category, channels: channels))
except Exception as e:
error "Error creating community category", msg = e.msg, communityId, name
raise newException(RpcException, "Error creating community category: " & e.msg)
proc deleteCommunityCategory*(self: Service, communityId: string, categoryId: string) =
try:
let response = status_go.deleteCommunityCategory(communityId, categoryId)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "Error deleting community category: " & error.message)
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_DELETED,
CommunityCategoryArgs(
communityId: communityId,
category: Category(id: categoryId)
)
)
except Exception as e:
error "Error deleting community category", msg = e.msg, communityId, categoryId
raise newException(RpcException, "Error deleting community category: " & e.msg)
proc requestCommunityInfo*(self: Service, communityId: string) =
try:
let response = status_go.requestCommunityInfo(communityId)
if (response.error != nil):
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, fmt"Error requesting community info: {error.message}")
except Exception as e:
error "Error requesting community info", msg = e.msg, communityId
raise newException(RpcException, "Error requesting community info: " & e.msg)
proc importCommunity*(self: Service, communityKey: string) =
try:
let response = status_go.importCommunity(communityKey)
if (response.error != nil):
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, fmt"Error importing the community: {error.message}")
except Exception as e:
error "Error requesting community info", msg = e.msg
raise newException(RpcException, "Error requesting community info: " & e.msg)
proc exportCommunity*(self: Service, communityId: string): string =
try:
let response = status_go.exportCommunity(communityId)
if (response.result != nil):
return response.result.getStr
except Exception as e:
error "Error exporting community", msg = e.msg
raise newException(RpcException, "Error exporting community: " & e.msg)

View File

@ -47,3 +47,45 @@ method userCanJoin*(self: ServiceInterface, communityId: string) {.base.} =
method joinCommunity*(self: ServiceInterface, communityId: string) {.base.} = method joinCommunity*(self: ServiceInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method requestToJoinCommunity*(self: ServiceInterface, communityId: string, ensName: string) {.base.} =
raise newException(ValueError, "No implementation available")
method loadMyPendingRequestsToJoin*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method leaveCommunity*(self: ServiceInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunity*(self: ServiceInterface, name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunityChannel*(self: ServiceInterface, communityId: string, name: string, description: string) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunityChannel*(self: ServiceInterface, communityId: string, channelId: string, name: string, description: string, categoryId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
method reorderCommunityChat*(self: ServiceInterface, communityId: string, categoryId: string, chatId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
method deleteCommunityChat*(self: ServiceInterface, communityId: string, chatId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method createCommunityCategory*(self: ServiceInterface, communityId: string, name: string, channels: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunityCategory*(self: ServiceInterface, communityId: string, categoryId: string, name: string, channels: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method deleteCommunityCategory*(self: ServiceInterface, communityId: string, categoryId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method requestCommunityInfo*(self: ServiceInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method importCommunity*(self: ServiceInterface, communityKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method exportCommunity*(self: ServiceInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")