Move /t_ms delta admin text type parsing to separate file and add tests
This commit is contained in:
@@ -59,6 +59,24 @@ from ._delta_class import (
|
||||
ThreadsRead,
|
||||
MessageEvent,
|
||||
)
|
||||
from ._delta_type import (
|
||||
ColorSet,
|
||||
EmojiSet,
|
||||
NicknameSet,
|
||||
AdminsAdded,
|
||||
AdminsRemoved,
|
||||
ApprovalModeSet,
|
||||
CallStarted,
|
||||
CallEnded,
|
||||
CallJoined,
|
||||
PollCreated,
|
||||
PollVoted,
|
||||
PlanCreated,
|
||||
PlanEnded,
|
||||
PlanEdited,
|
||||
PlanDeleted,
|
||||
PlanResponded,
|
||||
)
|
||||
|
||||
from ._client import Client
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
329
fbchat/_delta_type.py
Normal file
329
fbchat/_delta_type.py
Normal file
@@ -0,0 +1,329 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._event_common import attrs_event, Event, UnknownEvent, ThreadEvent
|
||||
from . import _util, _user, _thread, _poll, _plan
|
||||
|
||||
from typing import Sequence, Optional
|
||||
|
||||
|
||||
@attrs_event
|
||||
class ColorSet(ThreadEvent):
|
||||
"""Somebody set the color in a thread."""
|
||||
|
||||
#: The new color. Not limited to the ones in `ThreadABC.set_color`
|
||||
color = attr.ib(type=str)
|
||||
#: When the color was set
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
color = _thread.ThreadABC._parse_color(data["untypedData"]["theme_color"])
|
||||
return cls(author=author, thread=thread, color=color, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class EmojiSet(ThreadEvent):
|
||||
"""Somebody set the emoji in a thread."""
|
||||
|
||||
#: The new emoji
|
||||
emoji = attr.ib(type=str)
|
||||
#: When the emoji was set
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
emoji = data["untypedData"]["thread_icon"]
|
||||
return cls(author=author, thread=thread, emoji=emoji, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class NicknameSet(ThreadEvent):
|
||||
"""Somebody set the nickname of a person in a thread."""
|
||||
|
||||
#: The person whose nickname was set
|
||||
subject = attr.ib(type=str)
|
||||
#: The new nickname. If ``None``, the nickname was cleared
|
||||
nickname = attr.ib(type=Optional[str])
|
||||
#: When the nickname was set
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["participant_id"])
|
||||
nickname = data["untypedData"]["nickname"] or None # None if ""
|
||||
return cls(
|
||||
author=author, thread=thread, subject=subject, nickname=nickname, at=at
|
||||
)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class AdminsAdded(ThreadEvent):
|
||||
"""Somebody added admins to a group."""
|
||||
|
||||
#: The people that were set as admins
|
||||
added = attr.ib(type=Sequence[_user.User])
|
||||
#: When the admins were added
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
return cls(author=author, thread=thread, added=[subject], at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class AdminsRemoved(ThreadEvent):
|
||||
"""Somebody removed admins from a group."""
|
||||
|
||||
#: The people that were removed as admins
|
||||
removed = attr.ib(type=Sequence[_user.User])
|
||||
#: When the admins were removed
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
return cls(author=author, thread=thread, removed=[subject], at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class ApprovalModeSet(ThreadEvent):
|
||||
"""Somebody changed the approval mode in a group."""
|
||||
|
||||
require_admin_approval = attr.ib(type=bool)
|
||||
#: When the approval mode was set
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
raa = data["untypedData"]["APPROVAL_MODE"] == "1"
|
||||
return cls(author=author, thread=thread, require_admin_approval=raa, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class CallStarted(ThreadEvent):
|
||||
"""Somebody started a call."""
|
||||
|
||||
#: When the call was started
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
return cls(author=author, thread=thread, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class CallEnded(ThreadEvent):
|
||||
"""Somebody ended a call."""
|
||||
|
||||
#: How long the call took
|
||||
duration = attr.ib(type=datetime.timedelta)
|
||||
#: When the call ended
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
duration = _util.seconds_to_timedelta(int(data["untypedData"]["call_duration"]))
|
||||
return cls(author=author, thread=thread, duration=duration, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class CallJoined(ThreadEvent):
|
||||
"""Somebody joined a call."""
|
||||
|
||||
#: When the call ended
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
return cls(author=author, thread=thread, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PollCreated(ThreadEvent):
|
||||
"""Somebody created a group poll."""
|
||||
|
||||
#: The new poll
|
||||
poll = attr.ib(type=_poll.Poll)
|
||||
#: When the poll was created
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
poll_data = _util.parse_json(data["untypedData"]["question_json"])
|
||||
poll = _poll.Poll._from_graphql(session, poll_data)
|
||||
return cls(author=author, thread=thread, poll=poll, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PollVoted(ThreadEvent):
|
||||
"""Somebody voted in a group poll."""
|
||||
|
||||
#: The updated poll
|
||||
poll = attr.ib(type=_poll.Poll)
|
||||
#: Ids of the voted options
|
||||
added_ids = attr.ib(type=Sequence[str])
|
||||
#: Ids of the un-voted options
|
||||
removed_ids = attr.ib(type=Sequence[str])
|
||||
#: When the poll was voted in
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
poll_data = _util.parse_json(data["untypedData"]["question_json"])
|
||||
poll = _poll.Poll._from_graphql(session, poll_data)
|
||||
added_ids = _util.parse_json(data["untypedData"]["added_option_ids"])
|
||||
removed_ids = _util.parse_json(data["untypedData"]["removed_option_ids"])
|
||||
return cls(
|
||||
author=author,
|
||||
thread=thread,
|
||||
poll=poll,
|
||||
added_ids=[str(x) for x in added_ids],
|
||||
removed_ids=[str(x) for x in removed_ids],
|
||||
at=at,
|
||||
)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PlanCreated(ThreadEvent):
|
||||
"""Somebody created a plan in a group."""
|
||||
|
||||
#: The new plan
|
||||
plan = attr.ib(type=_plan.PlanData)
|
||||
#: When the plan was created
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
plan = _plan.PlanData._from_pull(session, data["untypedData"])
|
||||
return cls(author=author, thread=thread, plan=plan, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PlanEnded(ThreadEvent):
|
||||
"""A plan ended."""
|
||||
|
||||
#: The ended plan
|
||||
plan = attr.ib(type=_plan.PlanData)
|
||||
#: When the plan ended
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
plan = _plan.PlanData._from_pull(session, data["untypedData"])
|
||||
return cls(author=author, thread=thread, plan=plan, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PlanEdited(ThreadEvent):
|
||||
"""Somebody changed a plan in a group."""
|
||||
|
||||
#: The updated plan
|
||||
plan = attr.ib(type=_plan.PlanData)
|
||||
#: When the plan was updated
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
plan = _plan.PlanData._from_pull(session, data["untypedData"])
|
||||
return cls(author=author, thread=thread, plan=plan, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PlanDeleted(ThreadEvent):
|
||||
"""Somebody removed a plan in a group."""
|
||||
|
||||
#: The removed plan
|
||||
plan = attr.ib(type=_plan.PlanData)
|
||||
#: When the plan was removed
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
plan = _plan.PlanData._from_pull(session, data["untypedData"])
|
||||
return cls(author=author, thread=thread, plan=plan, at=at)
|
||||
|
||||
|
||||
@attrs_event
|
||||
class PlanResponded(ThreadEvent):
|
||||
"""Somebody responded to a plan in a group."""
|
||||
|
||||
#: The plan that was responded to
|
||||
plan = attr.ib(type=_plan.PlanData)
|
||||
#: Whether the author will go to the plan or not
|
||||
take_part = attr.ib(type=bool)
|
||||
#: When the plan was removed
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
plan = _plan.PlanData._from_pull(session, data["untypedData"])
|
||||
take_part = data["untypedData"]["guest_status"] == "GOING"
|
||||
return cls(author=author, thread=thread, plan=plan, take_part=take_part, at=at)
|
||||
|
||||
|
||||
def parse_delta(session, data):
|
||||
type_ = data.get("type")
|
||||
if type_ == "change_thread_theme":
|
||||
return ColorSet._parse(session, data)
|
||||
elif type_ == "change_thread_icon":
|
||||
return EmojiSet._parse(session, data)
|
||||
elif type_ == "change_thread_nickname":
|
||||
return NicknameSet._parse(session, data)
|
||||
elif type_ == "change_thread_admins":
|
||||
event_type = data["untypedData"]["ADMIN_EVENT"]
|
||||
if event_type == "add_admin":
|
||||
return AdminsAdded._parse(session, data)
|
||||
elif event_type == "remove_admin":
|
||||
return AdminsRemoved._parse(session, data)
|
||||
else:
|
||||
pass
|
||||
elif type_ == "change_thread_approval_mode":
|
||||
return ApprovalModeSet._parse(session, data)
|
||||
elif type_ == "instant_game_update":
|
||||
pass # TODO: This
|
||||
elif type_ == "messenger_call_log": # Previously "rtc_call_log"
|
||||
event_type = data["untypedData"]["event"]
|
||||
if event_type == "group_call_started":
|
||||
return CallStarted._parse(session, data)
|
||||
elif event_type in ["group_call_ended", "one_on_one_call_ended"]:
|
||||
return CallEnded._parse(session, data)
|
||||
else:
|
||||
pass
|
||||
elif type_ == "participant_joined_group_call":
|
||||
return CallJoined._parse(session, data)
|
||||
elif type_ == "group_poll":
|
||||
event_type = data["untypedData"]["event_type"]
|
||||
if event_type == "question_creation":
|
||||
return PollCreated._parse(session, data)
|
||||
elif event_type == "update_vote":
|
||||
return PollVoted._parse(session, data)
|
||||
else:
|
||||
pass
|
||||
elif type_ == "lightweight_event_create":
|
||||
return PlanCreated._parse(session, data)
|
||||
elif type_ == "lightweight_event_notify":
|
||||
return PlanEnded._parse(session, data)
|
||||
elif type_ == "lightweight_event_update":
|
||||
return PlanEdited._parse(session, data)
|
||||
elif type_ == "lightweight_event_delete":
|
||||
return PlanDeleted._parse(session, data)
|
||||
elif type_ == "lightweight_event_rsvp":
|
||||
return PlanResponded._parse(session, data)
|
||||
return UnknownEvent(data=data)
|
954
tests/test_delta_type.py
Normal file
954
tests/test_delta_type.py
Normal file
@@ -0,0 +1,954 @@
|
||||
import datetime
|
||||
import pytest
|
||||
from fbchat import (
|
||||
_util,
|
||||
ParseError,
|
||||
User,
|
||||
Group,
|
||||
Poll,
|
||||
PollOption,
|
||||
PlanData,
|
||||
GuestStatus,
|
||||
UnknownEvent,
|
||||
ColorSet,
|
||||
EmojiSet,
|
||||
NicknameSet,
|
||||
AdminsAdded,
|
||||
AdminsRemoved,
|
||||
ApprovalModeSet,
|
||||
CallStarted,
|
||||
CallEnded,
|
||||
CallJoined,
|
||||
PollCreated,
|
||||
PollVoted,
|
||||
PlanCreated,
|
||||
PlanEnded,
|
||||
PlanEdited,
|
||||
PlanDeleted,
|
||||
PlanResponded,
|
||||
)
|
||||
from fbchat._message import Message, MessageData
|
||||
from fbchat._delta_type import parse_delta
|
||||
|
||||
|
||||
def test_color_set(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You changed the chat theme to Orange.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_theme",
|
||||
"untypedData": {
|
||||
"should_show_icon": "1",
|
||||
"theme_color": "FFFF7E29",
|
||||
"accessibility_label": "Orange",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert ColorSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
color="#ff7e29",
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_emoji_set(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You set the emoji to 🌟.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"skipSnippetUpdate": False,
|
||||
"tags": ["source:generic_admin_text"],
|
||||
"threadKey": {"otherUserFbId": "1234"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"type": "change_thread_icon",
|
||||
"untypedData": {
|
||||
"thread_icon_url": "https://www.facebook.com/images/emoji.php/v9/te0/1/16/1f31f.png",
|
||||
"thread_icon": "🌟",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert EmojiSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=User(session=session, id="1234"),
|
||||
emoji="🌟",
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_nickname_set(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You set the nickname for Abc Def to abc.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_nickname",
|
||||
"untypedData": {"nickname": "abc", "participant_id": "2345"},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert NicknameSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
subject=User(session=session, id="2345"),
|
||||
nickname="abc",
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_nickname_clear(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You cleared your nickname.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"skipSnippetUpdate": False,
|
||||
"tags": ["source:generic_admin_text"],
|
||||
"threadKey": {"otherUserFbId": "1234"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"type": "change_thread_nickname",
|
||||
"untypedData": {"nickname": "", "participant_id": "1234"},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert NicknameSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=User(session=session, id="1234"),
|
||||
subject=User(session=session, id="1234"),
|
||||
nickname=None,
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_admins_added(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You added Abc Def as a group admin.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": True,
|
||||
"tags": ["source:titan:web"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_admins",
|
||||
"untypedData": {
|
||||
"THREAD_CATEGORY": "GROUP",
|
||||
"TARGET_ID": "2345",
|
||||
"ADMIN_TYPE": "0",
|
||||
"ADMIN_EVENT": "add_admin",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert AdminsAdded(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
added=[User(session=session, id="2345")],
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_admins_removed(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You removed yourself as a group admin.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": True,
|
||||
"tags": ["source:titan:web"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_admins",
|
||||
"untypedData": {
|
||||
"THREAD_CATEGORY": "GROUP",
|
||||
"TARGET_ID": "1234",
|
||||
"ADMIN_TYPE": "0",
|
||||
"ADMIN_EVENT": "remove_admin",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert AdminsRemoved(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
removed=[User(session=session, id="1234")],
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_approvalmode_set(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You turned on member approval and will review requests to join the group.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": True,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_approval_mode",
|
||||
"untypedData": {"APPROVAL_MODE": "1", "THREAD_CATEGORY": "GROUP"},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert ApprovalModeSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
require_admin_approval=True,
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_approvalmode_unset(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You turned off member approval. Anyone with the link can join the group.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": True,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "change_thread_approval_mode",
|
||||
"untypedData": {"APPROVAL_MODE": "0", "THREAD_CATEGORY": "GROUP"},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert ApprovalModeSet(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
require_admin_approval=False,
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_call_started(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You started a call.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "messenger_call_log",
|
||||
"untypedData": {
|
||||
"call_capture_attachments": "",
|
||||
"caller_id": "1234",
|
||||
"conference_name": "MESSENGER:134845267536444",
|
||||
"rating": "",
|
||||
"messenger_call_instance_id": "0",
|
||||
"video": "",
|
||||
"event": "group_call_started",
|
||||
"server_info": "XYZ123ABC",
|
||||
"call_duration": "0",
|
||||
"callee_id": "0",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
data2 = {
|
||||
"callState": "AUDIO_GROUP_CALL",
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": [],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
},
|
||||
"serverInfoData": "XYZ123ABC",
|
||||
"class": "RtcCallData",
|
||||
}
|
||||
assert CallStarted(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_group_call_ended(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "The call ended.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "messenger_call_log",
|
||||
"untypedData": {
|
||||
"call_capture_attachments": "",
|
||||
"caller_id": "1234",
|
||||
"conference_name": "MESSENGER:1234567890",
|
||||
"rating": "0",
|
||||
"messenger_call_instance_id": "1234567890",
|
||||
"video": "",
|
||||
"event": "group_call_ended",
|
||||
"server_info": "XYZ123ABC",
|
||||
"call_duration": "31",
|
||||
"callee_id": "0",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
data2 = {
|
||||
"callState": "NO_ONGOING_CALL",
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": [],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
},
|
||||
"class": "RtcCallData",
|
||||
}
|
||||
assert CallEnded(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
duration=datetime.timedelta(seconds=31),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_user_call_ended(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "Abc called you.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"skipSnippetUpdate": False,
|
||||
"tags": ["source:generic_admin_text", "no_push"],
|
||||
"threadKey": {"otherUserFbId": "1234"},
|
||||
"threadReadStateEffect": "KEEP_AS_IS",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"type": "messenger_call_log",
|
||||
"untypedData": {
|
||||
"call_capture_attachments": "",
|
||||
"caller_id": "1234",
|
||||
"conference_name": "MESSENGER:1234567890",
|
||||
"rating": "0",
|
||||
"messenger_call_instance_id": "1234567890",
|
||||
"video": "",
|
||||
"event": "one_on_one_call_ended",
|
||||
"server_info": "",
|
||||
"call_duration": "3",
|
||||
"callee_id": "100002950119740",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert CallEnded(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=User(session=session, id="1234"),
|
||||
duration=datetime.timedelta(seconds=3),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_call_joined(session):
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "Abc joined the call.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "participant_joined_group_call",
|
||||
"untypedData": {
|
||||
"server_info_data": "XYZ123ABC",
|
||||
"group_call_type": "0",
|
||||
"joining_user": "2345",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert CallJoined(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_poll_created(session):
|
||||
poll_data = {
|
||||
"id": "112233",
|
||||
"text": "A poll",
|
||||
"total_count": 2,
|
||||
"viewer_has_voted": "true",
|
||||
"options": [
|
||||
{
|
||||
"id": "1001",
|
||||
"text": "Option A",
|
||||
"total_count": 1,
|
||||
"viewer_has_voted": "true",
|
||||
"voters": ["1234"],
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"text": "Option B",
|
||||
"total_count": 0,
|
||||
"viewer_has_voted": "false",
|
||||
"voters": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You created a poll: A poll.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "group_poll",
|
||||
"untypedData": {
|
||||
"added_option_ids": "[]",
|
||||
"removed_option_ids": "[]",
|
||||
"question_json": _util.json_minimal(poll_data),
|
||||
"event_type": "question_creation",
|
||||
"question_id": "112233",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PollCreated(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
poll=Poll(
|
||||
session=session,
|
||||
id="112233",
|
||||
question="A poll",
|
||||
options=[
|
||||
PollOption(
|
||||
id="1001",
|
||||
text="Option A",
|
||||
vote=True,
|
||||
voters=["1234"],
|
||||
votes_count=1,
|
||||
),
|
||||
PollOption(
|
||||
id="1002", text="Option B", vote=False, voters=[], votes_count=0
|
||||
),
|
||||
],
|
||||
options_count=2,
|
||||
),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_poll_answered(session):
|
||||
poll_data = {
|
||||
"id": "112233",
|
||||
"text": "A poll",
|
||||
"total_count": 3,
|
||||
"viewer_has_voted": "true",
|
||||
"options": [
|
||||
{
|
||||
"id": "1002",
|
||||
"text": "Option B",
|
||||
"total_count": 2,
|
||||
"viewer_has_voted": "true",
|
||||
"voters": ["1234", "2345"],
|
||||
},
|
||||
{
|
||||
"id": "1003",
|
||||
"text": "Option C",
|
||||
"total_count": 1,
|
||||
"viewer_has_voted": "true",
|
||||
"voters": ["1234"],
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"text": "Option A",
|
||||
"total_count": 0,
|
||||
"viewer_has_voted": "false",
|
||||
"voters": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": 'You changed your vote to "Option B" and 1 other option in the poll: A poll.',
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "group_poll",
|
||||
"untypedData": {
|
||||
"added_option_ids": "[1002,1003]",
|
||||
"removed_option_ids": "[1001]",
|
||||
"question_json": _util.json_minimal(poll_data),
|
||||
"event_type": "update_vote",
|
||||
"question_id": "112233",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PollVoted(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
poll=Poll(
|
||||
session=session,
|
||||
id="112233",
|
||||
question="A poll",
|
||||
options=[
|
||||
PollOption(
|
||||
id="1002",
|
||||
text="Option B",
|
||||
vote=True,
|
||||
voters=["1234", "2345"],
|
||||
votes_count=2,
|
||||
),
|
||||
PollOption(
|
||||
id="1003",
|
||||
text="Option C",
|
||||
vote=True,
|
||||
voters=["1234"],
|
||||
votes_count=1,
|
||||
),
|
||||
PollOption(
|
||||
id="1001", text="Option A", vote=False, voters=[], votes_count=0
|
||||
),
|
||||
],
|
||||
options_count=3,
|
||||
),
|
||||
added_ids=["1002", "1003"],
|
||||
removed_ids=["1001"],
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_plan_created(session):
|
||||
guest_list = [
|
||||
{"guest_list_state": "INVITED", "node": {"id": "3456"}},
|
||||
{"guest_list_state": "INVITED", "node": {"id": "2345"}},
|
||||
{"guest_list_state": "GOING", "node": {"id": "1234"}},
|
||||
]
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You created a plan.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "lightweight_event_create",
|
||||
"untypedData": {
|
||||
"event_timezone": "",
|
||||
"event_creator_id": "1234",
|
||||
"event_id": "112233",
|
||||
"event_type": "EVENT",
|
||||
"event_track_rsvp": "1",
|
||||
"event_title": "A plan",
|
||||
"event_time": "1600000000",
|
||||
"event_seconds_to_notify_before": "3600",
|
||||
"guest_state_list": _util.json_minimal(guest_list),
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PlanCreated(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
plan=PlanData(
|
||||
session=session,
|
||||
id="112233",
|
||||
time=datetime.datetime(
|
||||
2020, 9, 13, 12, 26, 40, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
title="A plan",
|
||||
author_id="1234",
|
||||
guests={
|
||||
"1234": GuestStatus.GOING,
|
||||
"2345": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.INVITED,
|
||||
},
|
||||
),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Need to gather test data")
|
||||
def test_plan_ended(session):
|
||||
data = {}
|
||||
assert PlanEnded(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
plan=PlanData(
|
||||
session=session,
|
||||
id="112233",
|
||||
time=datetime.datetime(
|
||||
2020, 9, 13, 12, 26, 40, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
title="A plan",
|
||||
author_id="1234",
|
||||
guests={
|
||||
"1234": GuestStatus.GOING,
|
||||
"2345": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.INVITED,
|
||||
},
|
||||
),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_plan_edited(session):
|
||||
guest_list = [
|
||||
{"guest_list_state": "INVITED", "node": {"id": "3456"}},
|
||||
{"guest_list_state": "INVITED", "node": {"id": "2345"}},
|
||||
{"guest_list_state": "GOING", "node": {"id": "1234"}},
|
||||
]
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You named the plan A plan.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "lightweight_event_update",
|
||||
"untypedData": {
|
||||
"event_creator_id": "1234",
|
||||
"latitude": "0",
|
||||
"event_title": "A plan",
|
||||
"event_seconds_to_notify_before": "3600",
|
||||
"guest_state_list": _util.json_minimal(guest_list),
|
||||
"event_end_time": "0",
|
||||
"event_timezone": "",
|
||||
"event_id": "112233",
|
||||
"event_type": "EVENT",
|
||||
"event_location_id": "2233445566",
|
||||
"event_location_name": "",
|
||||
"event_time": "1600000000",
|
||||
"event_note": "",
|
||||
"longitude": "0",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PlanEdited(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
plan=PlanData(
|
||||
session=session,
|
||||
id="112233",
|
||||
time=datetime.datetime(
|
||||
2020, 9, 13, 12, 26, 40, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
title="A plan",
|
||||
location_id="2233445566",
|
||||
author_id="1234",
|
||||
guests={
|
||||
"1234": GuestStatus.GOING,
|
||||
"2345": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.INVITED,
|
||||
},
|
||||
),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_plan_deleted(session):
|
||||
guest_list = [
|
||||
{"guest_list_state": "GOING", "node": {"id": "1234"}},
|
||||
{"guest_list_state": "INVITED", "node": {"id": "3456"}},
|
||||
{"guest_list_state": "INVITED", "node": {"id": "2345"}},
|
||||
]
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You deleted the plan A plan for Mon, 20 Jan at 15:30.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "lightweight_event_delete",
|
||||
"untypedData": {
|
||||
"event_end_time": "0",
|
||||
"event_timezone": "",
|
||||
"event_id": "112233",
|
||||
"event_type": "EVENT",
|
||||
"event_location_id": "2233445566",
|
||||
"latitude": "0",
|
||||
"event_title": "A plan",
|
||||
"event_time": "1600000000",
|
||||
"event_seconds_to_notify_before": "3600",
|
||||
"guest_state_list": _util.json_minimal(guest_list),
|
||||
"event_note": "",
|
||||
"longitude": "0",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PlanDeleted(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
plan=PlanData(
|
||||
session=session,
|
||||
id="112233",
|
||||
time=datetime.datetime(
|
||||
2020, 9, 13, 12, 26, 40, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
title="A plan",
|
||||
location_id="2233445566",
|
||||
author_id=None,
|
||||
guests={
|
||||
"1234": GuestStatus.GOING,
|
||||
"2345": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.INVITED,
|
||||
},
|
||||
),
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_plan_participation(session):
|
||||
guest_list = [
|
||||
{"guest_list_state": "DECLINED", "node": {"id": "1234"}},
|
||||
{"guest_list_state": "GOING", "node": {"id": "2345"}},
|
||||
{"guest_list_state": "INVITED", "node": {"id": "3456"}},
|
||||
]
|
||||
data = {
|
||||
"irisSeqId": "1111111",
|
||||
"irisTags": ["DeltaAdminTextMessage", "is_from_iris_fanout"],
|
||||
"messageMetadata": {
|
||||
"actorFbId": "1234",
|
||||
"adminText": "You responded Can't Go to def.",
|
||||
"folderId": {"systemFolderId": "INBOX"},
|
||||
"messageId": "mid.$XYZ",
|
||||
"offlineThreadingId": "11223344556677889900",
|
||||
"skipBumpThread": False,
|
||||
"tags": ["source:titan:web", "no_push"],
|
||||
"threadKey": {"threadFbId": "4321"},
|
||||
"threadReadStateEffect": "MARK_UNREAD",
|
||||
"timestamp": "1500000000000",
|
||||
"unsendType": "deny_log_message",
|
||||
},
|
||||
"participants": ["1234", "2345", "3456"],
|
||||
"requestContext": {"apiArgs": {}},
|
||||
"tqSeqId": "1111",
|
||||
"type": "lightweight_event_rsvp",
|
||||
"untypedData": {
|
||||
"event_creator_id": "2345",
|
||||
"guest_status": "DECLINED",
|
||||
"latitude": "0",
|
||||
"event_track_rsvp": "1",
|
||||
"event_title": "A plan",
|
||||
"event_seconds_to_notify_before": "3600",
|
||||
"guest_state_list": _util.json_minimal(guest_list),
|
||||
"event_end_time": "0",
|
||||
"event_timezone": "",
|
||||
"event_id": "112233",
|
||||
"event_type": "EVENT",
|
||||
"guest_id": "1234",
|
||||
"event_location_id": "2233445566",
|
||||
"event_time": "1600000000",
|
||||
"event_note": "",
|
||||
"longitude": "0",
|
||||
},
|
||||
"class": "AdminTextMessage",
|
||||
}
|
||||
assert PlanResponded(
|
||||
author=User(session=session, id="1234"),
|
||||
thread=Group(session=session, id="4321"),
|
||||
plan=PlanData(
|
||||
session=session,
|
||||
id="112233",
|
||||
time=datetime.datetime(
|
||||
2020, 9, 13, 12, 26, 40, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
title="A plan",
|
||||
location_id="2233445566",
|
||||
author_id="2345",
|
||||
guests={
|
||||
"1234": GuestStatus.DECLINED,
|
||||
"2345": GuestStatus.GOING,
|
||||
"3456": GuestStatus.INVITED,
|
||||
},
|
||||
),
|
||||
take_part=False,
|
||||
at=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
) == parse_delta(session, data)
|
||||
|
||||
|
||||
def test_parse_delta_unknown(session):
|
||||
assert UnknownEvent(data={"abc": 10}) == parse_delta(session, {"abc": 10})
|
Reference in New Issue
Block a user