Move /t_ms delta admin text type parsing to separate file and add tests
This commit is contained in:
@@ -16,6 +16,7 @@ from . import (
|
||||
_event_common,
|
||||
_client_payload,
|
||||
_delta_class,
|
||||
_delta_type,
|
||||
)
|
||||
|
||||
from ._thread import ThreadLocation
|
||||
@@ -609,244 +610,8 @@ class Client:
|
||||
"""
|
||||
|
||||
def _parse_delta(self, delta):
|
||||
def get_thread(data):
|
||||
if "threadFbId" in data["threadKey"]:
|
||||
group_id = str(data["threadKey"]["threadFbId"])
|
||||
return Group(session=self.session, id=group_id)
|
||||
elif "otherUserFbId" in data["threadKey"]:
|
||||
user_id = str(data["threadKey"]["otherUserFbId"])
|
||||
return User(session=self.session, id=user_id)
|
||||
return None
|
||||
|
||||
delta_type = delta.get("type")
|
||||
metadata = delta.get("messageMetadata")
|
||||
|
||||
if metadata:
|
||||
mid = metadata["messageId"]
|
||||
author_id = str(metadata["actorFbId"])
|
||||
at = _util.millis_to_datetime(int(metadata.get("timestamp")))
|
||||
|
||||
# Color change
|
||||
if delta_type == "change_thread_theme":
|
||||
thread = get_thread(metadata)
|
||||
self.on_color_change(
|
||||
mid=mid,
|
||||
author_id=author_id,
|
||||
new_color=_thread.ThreadABC._parse_color(
|
||||
delta["untypedData"]["theme_color"]
|
||||
),
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Emoji change
|
||||
elif delta_type == "change_thread_icon":
|
||||
new_emoji = delta["untypedData"]["thread_icon"]
|
||||
self.on_emoji_change(
|
||||
mid=mid,
|
||||
author_id=author_id,
|
||||
new_emoji=new_emoji,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Nickname change
|
||||
elif delta_type == "change_thread_nickname":
|
||||
changed_for = str(delta["untypedData"]["participant_id"])
|
||||
new_nickname = delta["untypedData"]["nickname"]
|
||||
self.on_nickname_change(
|
||||
mid=mid,
|
||||
author_id=author_id,
|
||||
changed_for=changed_for,
|
||||
new_nickname=new_nickname,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Admin added or removed in a group thread
|
||||
elif delta_type == "change_thread_admins":
|
||||
target_id = delta["untypedData"]["TARGET_ID"]
|
||||
admin_event = delta["untypedData"]["ADMIN_EVENT"]
|
||||
if admin_event == "add_admin":
|
||||
self.on_admin_added(
|
||||
mid=mid,
|
||||
added_id=target_id,
|
||||
author_id=author_id,
|
||||
group=get_thread(metadata),
|
||||
at=at,
|
||||
)
|
||||
elif admin_event == "remove_admin":
|
||||
self.on_admin_removed(
|
||||
mid=mid,
|
||||
removed_id=target_id,
|
||||
author_id=author_id,
|
||||
group=get_thread(metadata),
|
||||
at=at,
|
||||
)
|
||||
|
||||
# Group approval mode change
|
||||
elif delta_type == "change_thread_approval_mode":
|
||||
approval_mode = bool(int(delta["untypedData"]["APPROVAL_MODE"]))
|
||||
self.on_approval_mode_change(
|
||||
mid=mid,
|
||||
approval_mode=approval_mode,
|
||||
author_id=author_id,
|
||||
group=get_thread(metadata),
|
||||
at=at,
|
||||
)
|
||||
|
||||
# Game played
|
||||
elif delta_type == "instant_game_update":
|
||||
game_id = delta["untypedData"]["game_id"]
|
||||
game_name = delta["untypedData"]["game_name"]
|
||||
score = delta["untypedData"].get("score")
|
||||
if score is not None:
|
||||
score = int(score)
|
||||
leaderboard = delta["untypedData"].get("leaderboard")
|
||||
if leaderboard is not None:
|
||||
leaderboard = _util.parse_json(leaderboard)["scores"]
|
||||
self.on_game_played(
|
||||
mid=mid,
|
||||
author_id=author_id,
|
||||
game_id=game_id,
|
||||
game_name=game_name,
|
||||
score=score,
|
||||
leaderboard=leaderboard,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Group call started/ended
|
||||
elif delta_type == "rtc_call_log":
|
||||
call_status = delta["untypedData"]["event"]
|
||||
call_duration = _util.seconds_to_timedelta(
|
||||
int(delta["untypedData"]["call_duration"])
|
||||
)
|
||||
is_video_call = bool(int(delta["untypedData"]["is_video_call"]))
|
||||
if call_status == "call_started":
|
||||
self.on_call_started(
|
||||
mid=mid,
|
||||
caller_id=author_id,
|
||||
is_video_call=is_video_call,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
elif call_status == "call_ended":
|
||||
self.on_call_ended(
|
||||
mid=mid,
|
||||
caller_id=author_id,
|
||||
is_video_call=is_video_call,
|
||||
call_duration=call_duration,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# User joined to group call
|
||||
elif delta_type == "participant_joined_group_call":
|
||||
is_video_call = bool(int(delta["untypedData"]["group_call_type"]))
|
||||
self.on_user_joined_call(
|
||||
mid=mid,
|
||||
joined_id=author_id,
|
||||
is_video_call=is_video_call,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Group poll event
|
||||
elif delta_type == "group_poll":
|
||||
event_type = delta["untypedData"]["event_type"]
|
||||
poll_json = _util.parse_json(delta["untypedData"]["question_json"])
|
||||
poll = _poll.Poll._from_graphql(self.session, poll_json)
|
||||
if event_type == "question_creation":
|
||||
# User created group poll
|
||||
self.on_poll_created(
|
||||
mid=mid,
|
||||
poll=poll,
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
elif event_type == "update_vote":
|
||||
# User voted on group poll
|
||||
added = _util.parse_json(delta["untypedData"]["added_option_ids"])
|
||||
removed = _util.parse_json(delta["untypedData"]["removed_option_ids"])
|
||||
self.on_poll_voted(
|
||||
mid=mid,
|
||||
poll=poll,
|
||||
added_options=added,
|
||||
removed_options=removed,
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Plan created
|
||||
elif delta_type == "lightweight_event_create":
|
||||
self.on_plan_created(
|
||||
mid=mid,
|
||||
plan=PlanData._from_pull(self.session, delta["untypedData"]),
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Plan ended
|
||||
elif delta_type == "lightweight_event_notify":
|
||||
self.on_plan_ended(
|
||||
mid=mid,
|
||||
plan=PlanData._from_pull(self.session, delta["untypedData"]),
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Plan edited
|
||||
elif delta_type == "lightweight_event_update":
|
||||
self.on_plan_edited(
|
||||
mid=mid,
|
||||
plan=PlanData._from_pull(self.session, delta["untypedData"]),
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Plan deleted
|
||||
elif delta_type == "lightweight_event_delete":
|
||||
self.on_plan_deleted(
|
||||
mid=mid,
|
||||
plan=PlanData._from_pull(self.session, delta["untypedData"]),
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Plan participation change
|
||||
elif delta_type == "lightweight_event_rsvp":
|
||||
take_part = delta["untypedData"]["guest_status"] == "GOING"
|
||||
self.on_plan_participation(
|
||||
mid=mid,
|
||||
plan=PlanData._from_pull(self.session, delta["untypedData"]),
|
||||
take_part=take_part,
|
||||
author_id=author_id,
|
||||
thread=get_thread(metadata),
|
||||
at=at,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Client payload (that weird numbers)
|
||||
elif delta.get("class") == "ClientPayload":
|
||||
if delta.get("class") == "ClientPayload":
|
||||
for event in _client_payload.parse_client_payloads(self.session, delta):
|
||||
self.on_event(event)
|
||||
|
||||
@@ -855,6 +620,9 @@ class Client:
|
||||
if event:
|
||||
self.on_event(event)
|
||||
|
||||
elif delta.get("type"):
|
||||
self.on_event(_delta_type.parse_delta(self.session, delta))
|
||||
|
||||
# Unknown message type
|
||||
else:
|
||||
self.on_unknown_messsage_type(msg=delta)
|
||||
@@ -984,120 +752,6 @@ class Client:
|
||||
"""Called when the client is listening, and an event happens."""
|
||||
log.info("Got event: %s", event)
|
||||
|
||||
def on_color_change(
|
||||
self,
|
||||
mid=None,
|
||||
author_id=None,
|
||||
new_color=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody changes a thread's color.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
author_id: The ID of the person who changed the color
|
||||
new_color: The new color. Not limited to the ones in `ThreadABC.set_color`
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("Color change from {} in {}: {}".format(author_id, thread, new_color))
|
||||
|
||||
def on_emoji_change(
|
||||
self,
|
||||
mid=None,
|
||||
author_id=None,
|
||||
new_emoji=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody changes a thread's emoji.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
author_id: The ID of the person who changed the emoji
|
||||
new_emoji: The new emoji
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("Emoji change from {} in {}: {}".format(author_id, thread, new_emoji))
|
||||
|
||||
def on_nickname_change(
|
||||
self,
|
||||
mid=None,
|
||||
author_id=None,
|
||||
changed_for=None,
|
||||
new_nickname=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody changes a nickname.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
author_id: The ID of the person who changed the nickname
|
||||
changed_for: The ID of the person whom got their nickname changed
|
||||
new_nickname: The new nickname
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info(
|
||||
"Nickname change from {} in {} for {}: {}".format(
|
||||
author_id, thread, changed_for, new_nickname
|
||||
)
|
||||
)
|
||||
|
||||
def on_admin_added(
|
||||
self, mid=None, added_id=None, author_id=None, group=None, at=None
|
||||
):
|
||||
"""Called when the client is listening, and somebody adds an admin to a group.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
added_id: The ID of the admin who got added
|
||||
author_id: The ID of the person who added the admins
|
||||
group: Group that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
"""
|
||||
log.info("{} added admin: {} in {}".format(author_id, added_id, group))
|
||||
|
||||
def on_admin_removed(
|
||||
self, mid=None, removed_id=None, author_id=None, group=None, at=None
|
||||
):
|
||||
"""Called when the client is listening, and somebody is removed as an admin in a group.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
removed_id: The ID of the admin who got removed
|
||||
author_id: The ID of the person who removed the admins
|
||||
group: Group that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
"""
|
||||
log.info("{} removed admin: {} in {}".format(author_id, removed_id, group))
|
||||
|
||||
def on_approval_mode_change(
|
||||
self, mid=None, approval_mode=None, author_id=None, group=None, at=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody changes approval mode in a group.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
approval_mode: True if approval mode is activated
|
||||
author_id: The ID of the person who changed approval mode
|
||||
group: Group that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
"""
|
||||
if approval_mode:
|
||||
log.info("{} activated approval mode in {}".format(author_id, group))
|
||||
else:
|
||||
log.info("{} disabled approval mode in {}".format(author_id, group))
|
||||
|
||||
def on_friend_request(self, from_id=None):
|
||||
"""Called when the client is listening, and somebody sends a friend request.
|
||||
|
||||
@@ -1128,229 +782,6 @@ class Client:
|
||||
"""
|
||||
pass
|
||||
|
||||
def on_game_played(
|
||||
self,
|
||||
mid=None,
|
||||
author_id=None,
|
||||
game_id=None,
|
||||
game_name=None,
|
||||
score=None,
|
||||
leaderboard=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody plays a game.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
author_id: The ID of the person who played the game
|
||||
game_id: The ID of the game
|
||||
game_name: Name of the game
|
||||
score: Score obtained in the game
|
||||
leaderboard: Actual leader board of the game in the thread
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info('{} played "{}" in {}'.format(author_id, game_name, thread))
|
||||
|
||||
def on_call_started(
|
||||
self,
|
||||
mid=None,
|
||||
caller_id=None,
|
||||
is_video_call=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody starts a call in a group.
|
||||
|
||||
Todo:
|
||||
Make this work with private calls.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
caller_id: The ID of the person who started the call
|
||||
is_video_call: True if it's video call
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} started call in {}".format(caller_id, thread))
|
||||
|
||||
def on_call_ended(
|
||||
self,
|
||||
mid=None,
|
||||
caller_id=None,
|
||||
is_video_call=None,
|
||||
call_duration=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody ends a call in a group.
|
||||
|
||||
Todo:
|
||||
Make this work with private calls.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
caller_id: The ID of the person who ended the call
|
||||
is_video_call: True if it was video call
|
||||
call_duration (datetime.timedelta): Call duration
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} ended call in {}".format(caller_id, thread))
|
||||
|
||||
def on_user_joined_call(
|
||||
self,
|
||||
mid=None,
|
||||
joined_id=None,
|
||||
is_video_call=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody joins a group call.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
joined_id: The ID of the person who joined the call
|
||||
is_video_call: True if it's video call
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} joined call in {}".format(joined_id, thread))
|
||||
|
||||
def on_poll_created(
|
||||
self, mid=None, poll=None, author_id=None, thread=None, at=None, metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody creates a group poll.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
poll (Poll): Created poll
|
||||
author_id: The ID of the person who created the poll
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} created poll {} in {}".format(author_id, poll, thread))
|
||||
|
||||
def on_poll_voted(
|
||||
self,
|
||||
mid=None,
|
||||
poll=None,
|
||||
added_options=None,
|
||||
removed_options=None,
|
||||
author_id=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody votes in a group poll.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
poll (Poll): Poll, that user voted in
|
||||
author_id: The ID of the person who voted in the poll
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} voted in poll {} in {}".format(author_id, poll, thread))
|
||||
|
||||
def on_plan_created(
|
||||
self, mid=None, plan=None, author_id=None, thread=None, at=None, metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody creates a plan.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
plan (Plan): Created plan
|
||||
author_id: The ID of the person who created the plan
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} created plan {} in {}".format(author_id, plan, thread))
|
||||
|
||||
def on_plan_ended(self, mid=None, plan=None, thread=None, at=None, metadata=None):
|
||||
"""Called when the client is listening, and a plan ends.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
plan (Plan): Ended plan
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("Plan {} has ended in {}".format(plan, thread))
|
||||
|
||||
def on_plan_edited(
|
||||
self, mid=None, plan=None, author_id=None, thread=None, at=None, metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody edits a plan.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
plan (Plan): Edited plan
|
||||
author_id: The ID of the person who edited the plan
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} edited plan {} in {}".format(author_id, plan, thread))
|
||||
|
||||
def on_plan_deleted(
|
||||
self, mid=None, plan=None, author_id=None, thread=None, at=None, metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody deletes a plan.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
plan (Plan): Deleted plan
|
||||
author_id: The ID of the person who deleted the plan
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
log.info("{} deleted plan {} in {}".format(author_id, plan, thread))
|
||||
|
||||
def on_plan_participation(
|
||||
self,
|
||||
mid=None,
|
||||
plan=None,
|
||||
take_part=None,
|
||||
author_id=None,
|
||||
thread=None,
|
||||
at=None,
|
||||
metadata=None,
|
||||
):
|
||||
"""Called when the client is listening, and somebody takes part in a plan or not.
|
||||
|
||||
Args:
|
||||
mid: The action ID
|
||||
plan (Plan): Plan
|
||||
take_part (bool): Whether the person takes part in the plan or not
|
||||
author_id: The ID of the person who will participate in the plan or not
|
||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||
at (datetime.datetime): When the action was executed
|
||||
metadata: Extra metadata about the action
|
||||
"""
|
||||
if take_part:
|
||||
log.info(
|
||||
"{} will take part in {} in {} ({})".format(author_id, plan, thread)
|
||||
)
|
||||
else:
|
||||
log.info(
|
||||
"{} won't take part in {} in {} ({})".format(author_id, plan, thread)
|
||||
)
|
||||
|
||||
def on_chat_timestamp(self, buddylist=None):
|
||||
"""Called when the client receives chat online presence update.
|
||||
|
||||
|
Reference in New Issue
Block a user