From 96b4a6e60f81a7ddcde11eaed5e59b8c6311a695 Mon Sep 17 00:00:00 2001 From: abc641 Date: Thu, 14 May 2020 20:22:49 +0000 Subject: [PATCH] Fix of gateway mass updating --- litecord/blueprints/user/billing.py | 1 + litecord/common/guilds.py | 10 ++++---- litecord/common/users.py | 33 +++++++++++++++---------- litecord/presence.py | 37 +++++++++++++++++++++++++---- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/litecord/blueprints/user/billing.py b/litecord/blueprints/user/billing.py index 5992a68..ce8f64c 100644 --- a/litecord/blueprints/user/billing.py +++ b/litecord/blueprints/user/billing.py @@ -391,6 +391,7 @@ async def _get_billing_payments(): @bp.route("/@me/billing/payment-sources", methods=["POST"]) async def _create_payment_source(): user_id = await token_check() + j = validate(await request.get_json(), PAYMENT_SOURCE) new_source_id = get_snowflake() diff --git a/litecord/common/guilds.py b/litecord/common/guilds.py index a45784d..57c7b82 100644 --- a/litecord/common/guilds.py +++ b/litecord/common/guilds.py @@ -49,14 +49,12 @@ async def remove_member(guild_id: int, member_id: int): ("GUILD_DELETE", {"guild_id": str(guild_id), "unavailable": False}), ) + user = await app.storage.get_user(member_id) + await app.dispatcher.guild.unsub(guild_id, member_id) - await app.lazy_guild.remove_member(member_id) + await app.lazy_guild.remove_member(guild_id, user["id"]) await app.dispatcher.guild.dispatch( - guild_id, - ( - "GUILD_MEMBER_REMOVE", - {"guild_id": str(guild_id), "user": await app.storage.get_user(member_id)}, - ), + guild_id, ("GUILD_MEMBER_REMOVE", {"guild_id": str(guild_id), "user": user},), ) diff --git a/litecord/common/users.py b/litecord/common/users.py index 1e5bdf4..0b9cd49 100644 --- a/litecord/common/users.py +++ b/litecord/common/users.py @@ -35,10 +35,14 @@ log = Logger(__name__) async def mass_user_update(user_id: int) -> Tuple[dict, dict]: - """Dispatch a USER_UPDATE to everyone that is subscribed to the user. + """Dispatch a USER_UPDATE to the user itself + Dispatches GUILD_MEMBER_UPDATE for others sharing guilds with the user + Dispatches PRESENCE_UPDATE for friends outside of guilds - This function guarantees all states will get one USER_UPDATE for simple - cases. Lazy guild users might get updates N times depending of how many + This function guarantees all states will get one of these events for simple + cases. + + Lazy guild users might get updates N times depending of how many lists are they subscribed to. """ session_ids: List[str] = [] @@ -46,28 +50,31 @@ async def mass_user_update(user_id: int) -> Tuple[dict, dict]: public_user = await app.storage.get_user(user_id) private_user = await app.storage.get_user(user_id, secure=True) - session_ids.extend(await dispatch_user(user_id, ("USER_UPDATE", private_user))) + # The user who initiated the profile change should also get possible guild events + await dispatch_user(user_id, ("USER_UPDATE", private_user)) guild_ids: List[int] = await app.user_storage.get_user_guilds(user_id) - friend_ids: List[int] = await app.user_storage.get_friend_ids(user_id) for guild_id in guild_ids: + member = await app.storage.get_member_data_one(guild_id, user_id) + member.pop("joined_at") session_ids.extend( await app.dispatcher.guild.dispatch_filter( guild_id, lambda sess_id: sess_id not in session_ids, - ("USER_UPDATE", public_user), + ("GUILD_MEMBER_UPDATE", {**{"guild_id": str(guild_id)}, **member}), ) ) - for friend_id in friend_ids: - session_ids.extend( - await app.dispatcher.friend.dispatch_filter( - friend_id, - lambda sess_id: sess_id not in session_ids, - ("USER_UPDATE", public_user), - ) + # fetch current user presence + presence = app.presence.fetch_self_presence(user_id) + + # usually this presence should be partial, but there should be no major issue with a full one + session_ids.extend( + await app.presence.dispatch_friends_pres_filter( + public_user, lambda sess_id: sess_id not in session_ids, presence ) + ) for guild_id in guild_ids: await app.lazy_guild.update_user(guild_id, user_id) diff --git a/litecord/presence.py b/litecord/presence.py index a66dba0..2951c13 100644 --- a/litecord/presence.py +++ b/litecord/presence.py @@ -199,6 +199,30 @@ class PresenceManager: return in_lazy + async def dispatch_friends_pres(self, user_id: int, presence: BasePresence) -> None: + """ + Dispatch a new presence to all the user' friend + """ + + user = await self.storage.get_user(user_id) + await app.dispatcher.friend.dispatch( + user_id, ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}), + ) + + async def dispatch_friends_pres_filter( + self, user: dict, filter_function, presence: BasePresence + ) -> None: + """ + Same as dispatch_friends_pres but passes a filter function + Takes in a whole public user object instead of a user id + """ + + return await app.dispatcher.friend.dispatch_filter( + int(user["id"]), + filter_function, + ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}), + ) + async def dispatch_pres(self, user_id: int, presence: BasePresence) -> None: """Dispatch a new presence to all guilds the user is in. @@ -208,11 +232,14 @@ class PresenceManager: for guild_id in guild_ids: await self.dispatch_guild_pres(guild_id, user_id, presence) - # dispatch to all friends that are subscribed to them - user = await self.storage.get_user(user_id) - await app.dispatcher.friend.dispatch( - user_id, ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}), - ) + await self.dispatch_friends_pres(user_id, presence) + + def fetch_self_presence(self, user_id: int) -> BasePresence: + """Fetch a presence for a specifc user. + + This is basically the same as the friend function, so let's just call that + """ + return self.fetch_friend_presence(user_id) def fetch_friend_presence(self, friend_id: int) -> BasePresence: """Fetch a presence for a friend.