Fix of gateway mass updating

This commit is contained in:
abc641 2020-05-14 20:22:49 +00:00 committed by Luna
parent 0876c74575
commit 96b4a6e60f
4 changed files with 57 additions and 24 deletions

View File

@ -391,6 +391,7 @@ async def _get_billing_payments():
@bp.route("/@me/billing/payment-sources", methods=["POST"]) @bp.route("/@me/billing/payment-sources", methods=["POST"])
async def _create_payment_source(): async def _create_payment_source():
user_id = await token_check() user_id = await token_check()
j = validate(await request.get_json(), PAYMENT_SOURCE) j = validate(await request.get_json(), PAYMENT_SOURCE)
new_source_id = get_snowflake() new_source_id = get_snowflake()

View File

@ -49,14 +49,12 @@ async def remove_member(guild_id: int, member_id: int):
("GUILD_DELETE", {"guild_id": str(guild_id), "unavailable": False}), ("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.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( await app.dispatcher.guild.dispatch(
guild_id, guild_id, ("GUILD_MEMBER_REMOVE", {"guild_id": str(guild_id), "user": user},),
(
"GUILD_MEMBER_REMOVE",
{"guild_id": str(guild_id), "user": await app.storage.get_user(member_id)},
),
) )

View File

@ -35,10 +35,14 @@ log = Logger(__name__)
async def mass_user_update(user_id: int) -> Tuple[dict, dict]: 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 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 cases.
Lazy guild users might get updates N times depending of how many
lists are they subscribed to. lists are they subscribed to.
""" """
session_ids: List[str] = [] session_ids: List[str] = []
@ -46,26 +50,29 @@ async def mass_user_update(user_id: int) -> Tuple[dict, dict]:
public_user = await app.storage.get_user(user_id) public_user = await app.storage.get_user(user_id)
private_user = await app.storage.get_user(user_id, secure=True) 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) 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: 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( session_ids.extend(
await app.dispatcher.guild.dispatch_filter( await app.dispatcher.guild.dispatch_filter(
guild_id, guild_id,
lambda sess_id: sess_id not in session_ids, 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: # 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( session_ids.extend(
await app.dispatcher.friend.dispatch_filter( await app.presence.dispatch_friends_pres_filter(
friend_id, public_user, lambda sess_id: sess_id not in session_ids, presence
lambda sess_id: sess_id not in session_ids,
("USER_UPDATE", public_user),
) )
) )

View File

@ -199,6 +199,30 @@ class PresenceManager:
return in_lazy 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: async def dispatch_pres(self, user_id: int, presence: BasePresence) -> None:
"""Dispatch a new presence to all guilds the user is in. """Dispatch a new presence to all guilds the user is in.
@ -208,11 +232,14 @@ class PresenceManager:
for guild_id in guild_ids: for guild_id in guild_ids:
await self.dispatch_guild_pres(guild_id, user_id, presence) await self.dispatch_guild_pres(guild_id, user_id, presence)
# dispatch to all friends that are subscribed to them await self.dispatch_friends_pres(user_id, presence)
user = await self.storage.get_user(user_id)
await app.dispatcher.friend.dispatch( def fetch_self_presence(self, user_id: int) -> BasePresence:
user_id, ("PRESENCE_UPDATE", {**presence.partial_dict, **{"user": user}}), """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: def fetch_friend_presence(self, friend_id: int) -> BasePresence:
"""Fetch a presence for a friend. """Fetch a presence for a friend.