From 1d33e46fd80486fd322bab50953ae2012f0c262e Mon Sep 17 00:00:00 2001 From: Luna Mendes Date: Fri, 19 Oct 2018 19:16:29 -0300 Subject: [PATCH] pubsub: add lazy_guild --- README.md | 8 +++ litecord/pubsub/channel.py | 1 - litecord/pubsub/guild.py | 1 - litecord/pubsub/lazy_guild.py | 94 +++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 litecord/pubsub/lazy_guild.py diff --git a/README.md b/README.md index 4658055..5f5c9c4 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,16 @@ This project is a rewrite of [litecord-reference]. [litecord-reference]: https://gitlab.com/luna/litecord-reference +## Notes + + - There are no testing being run on the current codebase. Which means the code is definitely unstable. + - No voice is planned to be developed, for now. + - You must figure out connecting to the server yourself. Litecord will not distribute + Discord's official client code nor provide ways to modify the client. + ## Install +Requirements: - Python 3.6 or higher - PostgreSQL - [Pipenv] diff --git a/litecord/pubsub/channel.py b/litecord/pubsub/channel.py index 3c3cb2c..621eeff 100644 --- a/litecord/pubsub/channel.py +++ b/litecord/pubsub/channel.py @@ -1,5 +1,4 @@ from typing import Any -from collections import defaultdict from logbook import Logger diff --git a/litecord/pubsub/guild.py b/litecord/pubsub/guild.py index a05373a..6896d93 100644 --- a/litecord/pubsub/guild.py +++ b/litecord/pubsub/guild.py @@ -1,4 +1,3 @@ -from collections import defaultdict from typing import Any from logbook import Logger diff --git a/litecord/pubsub/lazy_guild.py b/litecord/pubsub/lazy_guild.py new file mode 100644 index 0000000..ba8a451 --- /dev/null +++ b/litecord/pubsub/lazy_guild.py @@ -0,0 +1,94 @@ +from collections import defaultdict +from typing import Any + +from logbook import Logger + +from .dispatcher import Dispatcher + +log = Logger(__name__) + + +class GuildMemberList(): + def __init__(self, guild_id: int): + self.guild_id = guild_id + + # TODO: initialize list with actual member info + self._uninitialized = True + self.member_list = [] + + #: holds the state of subscribed users + self.state = set() + + async def _init_check(self): + """Check if the member list is initialized before + messing with it.""" + if self._uninitialized: + await self._init_member_list() + + async def _init_member_list(self): + """Fill in :attr:`GuildMemberList.member_list` + with information about the guilds' members.""" + pass + + async def sub(self, user_id: int): + """Subscribe a user to the member list.""" + await self._init_check() + self.state.add(user_id) + + async def unsub(self, user_id: int): + """Unsubscribe a user from the member list""" + self.state.discard(user_id) + + # once we reach 0 subscribers, + # we drop the current member list we have (for memory) + # but keep the GuildMemberList running (as + # uninitialized) for a future subscriber. + + if not self.state: + self.member_list = [] + self._uninitialized = True + + async def dispatch(self, event: str, data: Any): + """The dispatch() method here, instead of being + about dispatching a single event to the subscribed + users and forgetting about it, is about storing + the actual member list information so that we + can generate the respective events to the users. + + GuildMemberList stores the current guilds' list + in its :attr:`GuildMemberList.member_list` attribute, + with that attribute being modified via different + calls to :meth:`GuildMemberList.dispatch` + """ + + if self._uninitialized: + # if the list is currently uninitialized, + # no subscribers actually happened, so + # we can safely drop the incoming event. + return + + +class LazyGuildDispatcher(Dispatcher): + """Main class holding the member lists for lazy guilds.""" + KEY_TYPE = int + VAL_TYPE = int + + def __init__(self, main): + super().__init__(main) + self.state = defaultdict(GuildMemberList) + + async def sub(self, guild_id, user_id): + await self.state[guild_id].sub(user_id) + + async def unsub(self, guild_id, user_id): + await self.state[guild_id].unsub(user_id) + + async def dispatch(self, guild_id: int, event: str, data): + """Dispatch an event to the member list. + + GuildMemberList will make sure of converting it to + GUILD_MEMBER_LIST_UPDATE events. + """ + member_list = self.state[guild_id] + await member_list.dispatch(event, data) +