From adc89b072cfb2d885e7faf96b6f9730cc95f1438 Mon Sep 17 00:00:00 2001
From: Tulir Asokan <tulir@maunium.net>
Date: Tue, 19 Nov 2019 21:38:52 +0200
Subject: [PATCH] Update fbchat

---
 example-config.yaml                         |   4 +-
 mautrix_facebook/__main__.py                |   2 +-
 mautrix_facebook/commands/auth.py           |  19 +-
 mautrix_facebook/commands/facebook.py       |   8 +-
 mautrix_facebook/db/portal.py               |   2 +-
 mautrix_facebook/formatter/from_facebook.py |   2 +-
 mautrix_facebook/formatter/from_matrix.py   |   2 +-
 mautrix_facebook/matrix.py                  |   2 +-
 mautrix_facebook/portal.py                  |  32 +--
 mautrix_facebook/puppet.py                  |   2 +-
 mautrix_facebook/user.py                    | 298 ++++++++++----------
 11 files changed, 189 insertions(+), 184 deletions(-)

diff --git a/example-config.yaml b/example-config.yaml
index 48d8b2f..18719af 100644
--- a/example-config.yaml
+++ b/example-config.yaml
@@ -1,9 +1,9 @@
 # Homeserver details
 homeserver:
     # The address that this appservice can use to connect to the homeserver.
-    address: https://matrix.org
+    address: https://example.com
     # The domain of the homeserver (for MXIDs, etc).
-    domain: matrix.org
+    domain: example.com
     # Whether or not to verify the SSL certificate of the homeserver.
     # Only applies if address starts with https://
     verify_ssl: true
diff --git a/mautrix_facebook/__main__.py b/mautrix_facebook/__main__.py
index eb2af04..c8c815a 100644
--- a/mautrix_facebook/__main__.py
+++ b/mautrix_facebook/__main__.py
@@ -55,7 +55,7 @@ class MessengerBridge(Bridge):
             puppet.stop()
         self.log.debug("Saving user sessions and stopping listeners")
         for mxid, user in User.by_mxid.items():
-            user.stopListening()
+            user.stop_listening()
             user.save()
 
 
diff --git a/mautrix_facebook/commands/auth.py b/mautrix_facebook/commands/auth.py
index 8061bbc..69bead9 100644
--- a/mautrix_facebook/commands/auth.py
+++ b/mautrix_facebook/commands/auth.py
@@ -18,7 +18,7 @@ import random
 
 from aiohttp.cookiejar import SimpleCookie
 
-from fbchat.models import FBchatUserError
+from fbchat import FBchatException
 from mautrix.client import Client
 
 from .. import puppet as pu
@@ -31,13 +31,14 @@ USER_AGENTS = [
 
     "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0",
 
-    "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like"
-    " Gecko) Version/12.1.1 Mobile/15E148 Safari/604.1",
+    # "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like"
+    # " Gecko) Version/12.1.1 Mobile/15E148 Safari/604.1",
 
     "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0",
 
-    "Mozilla/5.0 (Linux; Android 9; SM-G960F Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML,"
-    " like Gecko) Version/4.0 Chrome/74.0.3729.157 Mobile Safari/537.36",
+    # "Mozilla/5.0 (Linux; Android 9; SM-G960F Build/PPR1.180610.011; wv) AppleWebKit/537.36
+    # (KHTML,"
+    # " like Gecko) Version/4.0 Chrome/74.0.3729.157 Mobile Safari/537.36",
 ]
 
 
@@ -56,10 +57,10 @@ async def login(evt: CommandEvent) -> None:
         evt.sender.user_agent = random.choice(USER_AGENTS)
     await evt.reply("Logging in...")
     try:
-        await evt.sender.login(evt.args[0], " ".join(evt.args[1:]), max_tries=1,
+        await evt.sender.login(evt.args[0], " ".join(evt.args[1:]),
                                user_agent=evt.sender.user_agent)
         evt.sender.command_status = None
-    except FBchatUserError as e:
+    except FBchatException as e:
         evt.sender.command_status = None
         await evt.reply(f"Failed to log in: {e}")
         evt.log.exception("Failed to log in")
@@ -122,12 +123,12 @@ async def enter_login_cookies(evt: CommandEvent) -> None:
     cookie = SimpleCookie()
     cookie["c_user"] = evt.sender.command_status["c_user"]
     cookie["xs"] = evt.args[0]
-    ok = (await evt.sender.setSession(cookie, user_agent=evt.sender.user_agent)
+    ok = (await evt.sender.set_session(cookie, user_agent=evt.sender.user_agent)
           and await evt.sender.is_logged_in(True))
     if not ok:
         await evt.reply("Failed to log in (see logs for more details)")
     else:
-        await evt.sender.onLoggedIn(evt.sender.command_status["c_user"])
+        await evt.sender.on_logged_in(evt.sender.command_status["c_user"])
     evt.sender.command_status = None
 
 
diff --git a/mautrix_facebook/commands/facebook.py b/mautrix_facebook/commands/facebook.py
index bad289d..fe326d3 100644
--- a/mautrix_facebook/commands/facebook.py
+++ b/mautrix_facebook/commands/facebook.py
@@ -16,7 +16,7 @@
 from typing import Iterable, List
 import asyncio
 
-from fbchat.models import User, ThreadLocation
+from fbchat import User, ThreadLocation
 
 from .. import puppet as pu, portal as po, user as u
 from ..db import UserPortal as DBUserPortal
@@ -27,13 +27,13 @@ from . import command_handler, CommandEvent, SECTION_MISC
                  help_section=SECTION_MISC, help_text="Search for a Facebook user",
                  help_args="<_search query_>")
 async def search(evt: CommandEvent) -> None:
-    res = await evt.sender.searchForUsers(" ".join(evt.args))
+    res = await evt.sender.search_for_users(" ".join(evt.args))
     await evt.reply(await _handle_search_result(evt.sender, res))
 
 
 @command_handler(needs_auth=True, management_only=False)
 async def search_by_id(evt: CommandEvent) -> None:
-    res = await evt.sender.fetchUserInfo(*evt.args)
+    res = await evt.sender.fetch_user_info(*evt.args)
     await evt.reply(await _handle_search_result(evt.sender, res.values()))
 
 
@@ -65,7 +65,7 @@ async def sync(evt: CommandEvent) -> None:
         else:
             limit = int(arg)
 
-    threads = await evt.sender.fetchThreads(limit=limit, thread_location=ThreadLocation.INBOX)
+    threads = await evt.sender.fetch_threads(limit=limit, thread_location=ThreadLocation.INBOX)
     ups = DBUserPortal.all(evt.sender.fbid)
     for thread in threads:
         portal = po.Portal.get_by_thread(thread, evt.sender.fbid)
diff --git a/mautrix_facebook/db/portal.py b/mautrix_facebook/db/portal.py
index 666eada..5a870b4 100644
--- a/mautrix_facebook/db/portal.py
+++ b/mautrix_facebook/db/portal.py
@@ -17,7 +17,7 @@ from typing import Optional, Iterator
 
 from sqlalchemy import Column, String, Enum, and_
 
-from fbchat.models import ThreadType
+from fbchat import ThreadType
 from mautrix.types import RoomID
 from mautrix.util.db import Base
 
diff --git a/mautrix_facebook/formatter/from_facebook.py b/mautrix_facebook/formatter/from_facebook.py
index 5c7f027..2a9eaae 100644
--- a/mautrix_facebook/formatter/from_facebook.py
+++ b/mautrix_facebook/formatter/from_facebook.py
@@ -17,7 +17,7 @@ from typing import Tuple, List, Optional, Match
 from html import escape
 import re
 
-from fbchat.models import Message
+from fbchat import Message
 
 from mautrix.types import TextMessageEventContent, Format, MessageType
 
diff --git a/mautrix_facebook/formatter/from_matrix.py b/mautrix_facebook/formatter/from_matrix.py
index defd2e3..442fb4c 100644
--- a/mautrix_facebook/formatter/from_matrix.py
+++ b/mautrix_facebook/formatter/from_matrix.py
@@ -15,7 +15,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 from typing import Optional, cast
 
-from fbchat.models import Message, Mention
+from fbchat import Message, Mention
 
 from mautrix.types import TextMessageEventContent, Format, UserID, RoomID, RelationType
 from mautrix.util.formatter import (MatrixParser as BaseMatrixParser, MarkdownString, EntityString,
diff --git a/mautrix_facebook/matrix.py b/mautrix_facebook/matrix.py
index 2ee796d..eb99a31 100644
--- a/mautrix_facebook/matrix.py
+++ b/mautrix_facebook/matrix.py
@@ -15,7 +15,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 from typing import List, Union, TYPE_CHECKING
 
-from fbchat.models import ThreadType
+from fbchat import ThreadType
 from mautrix.types import (EventID, RoomID, UserID, Event, EventType, MessageEvent, StateEvent,
                            RedactionEvent, PresenceEventContent, ReceiptEvent, PresenceState,
                            ReactionEvent, ReactionEventContent, RelationType, PresenceEvent,
diff --git a/mautrix_facebook/portal.py b/mautrix_facebook/portal.py
index 001ce2a..86cca7c 100644
--- a/mautrix_facebook/portal.py
+++ b/mautrix_facebook/portal.py
@@ -22,10 +22,10 @@ from yarl import URL
 import aiohttp
 import magic
 
-from fbchat.models import (ThreadType, Thread, User as FBUser, Group as FBGroup, Page as FBPage,
-                           Message as FBMessage, Sticker as FBSticker, AudioAttachment,
-                           VideoAttachment, FileAttachment, ImageAttachment, LocationAttachment,
-                           ShareAttachment, TypingStatus, MessageReaction)
+from fbchat import (ThreadType, Thread, User as FBUser, Group as FBGroup, Page as FBPage,
+                    Message as FBMessage, Sticker as FBSticker, AudioAttachment, VideoAttachment,
+                    FileAttachment, ImageAttachment, LocationAttachment, ShareAttachment,
+                    TypingStatus, MessageReaction)
 from mautrix.types import (RoomID, EventType, ContentURI, MessageEventContent, EventID,
                            ImageInfo, MessageType, LocationMessageEventContent, LocationInfo,
                            ThumbnailInfo, FileInfo, AudioInfo, VideoInfo, Format, RelatesTo,
@@ -223,12 +223,12 @@ class Portal:
             return
         elif not self.mxid:
             return
-        users = await source.fetchAllUsersFromThreads([info])
-        puppets = {user: p.Puppet.get_by_fbid(user.uid) for user in users}
+        users = await source.fetch_all_users_from_threads([info])
+        puppets = [(user, p.Puppet.get_by_fbid(user.uid)) for user in users]
         await asyncio.gather(*[puppet.update_info(source=source, info=user)
-                               for user, puppet in puppets.items()])
+                               for user, puppet in puppets])
         await asyncio.gather(*[puppet.intent_for(self).ensure_joined(self.mxid)
-                               for puppet in puppets.values()])
+                               for user, puppet in puppets])
 
     # endregion
     # region Matrix room creation
@@ -386,7 +386,7 @@ class Portal:
         data = await self.main_intent.download_media(message.url)
         mime = message.info.mimetype or magic.from_buffer(data, mime=True)
         files = await sender._upload([(message.body, data, mime)])
-        return await sender._sendFiles(files, thread_id=self.fbid, thread_type=self.fb_type)
+        return await sender._send_files(files, thread_id=self.fbid, thread_type=self.fb_type)
 
     async def _handle_matrix_location(self, sender: 'u.User',
                                       message: LocationMessageEventContent) -> str:
@@ -409,7 +409,7 @@ class Portal:
         if reaction:
             try:
                 reaction.delete()
-                await sender.reactToMessage(reaction.fb_msgid, reaction=None)
+                await sender.react_to_message(reaction.fb_msgid, reaction=None)
             except Exception:
                 self.log.exception("Removing reaction failed")
 
@@ -442,7 +442,7 @@ class Portal:
             if existing and existing.reaction == reaction.value:
                 return
 
-            await sender.reactToMessage(message.fbid, reaction)
+            await sender.react_to_message(message.fbid, reaction)
             await self._upsert_reaction(existing, self.main_intent, event_id, message, sender,
                                         reaction.value)
 
@@ -455,9 +455,9 @@ class Portal:
             self.log.debug(f"{user.mxid} left portal to {self.fbid}")
 
     async def handle_matrix_typing(self, users: Set['u.User']) -> None:
-        stopped_typing = [user.setTypingStatus(TypingStatus.STOPPED, self.fbid, self.fb_type)
+        stopped_typing = [user.set_typing_status(TypingStatus.STOPPED, self.fbid, self.fb_type)
                           for user in self._typing - users]
-        started_typing = [user.setTypingStatus(TypingStatus.TYPING, self.fbid, self.fb_type)
+        started_typing = [user.set_typing_status(TypingStatus.TYPING, self.fbid, self.fb_type)
                           for user in users - self._typing]
         self._typing = users
         await asyncio.gather(*stopped_typing, *started_typing, loop=self.loop)
@@ -479,7 +479,7 @@ class Portal:
                                       message: FBMessage) -> None:
         async with self.optional_send_lock(sender.fbid):
             if message.uid in self._dedup:
-                await source.markAsDelivered(self.fbid, message.uid)
+                await source.mark_as_delivered(self.fbid, message.uid)
                 return
             self._dedup.appendleft(message.uid)
         if not self.mxid:
@@ -505,7 +505,7 @@ class Portal:
             self.log.warning(f"Unhandled Messenger message: {message}")
         DBMessage.bulk_create(fbid=message.uid, fb_receiver=self.fb_receiver, mx_room=self.mxid,
                               event_ids=[event_id for event_id in event_ids if event_id])
-        await source.markAsDelivered(self.fbid, message.uid)
+        await source.mark_as_delivered(self.fbid, message.uid)
 
     async def _add_facebook_reply(self, content: TextMessageEventContent, reply: str) -> None:
         if reply:
@@ -631,7 +631,7 @@ class Portal:
         # When we fetch thread info manually, we only get the URL instead of the ID,
         # so we can't use the actual ID here either.
         # self.photo_id = new_photo_id
-        photo_url = await source.fetchImageUrl(new_photo_id)
+        photo_url = await source.fetch_image_url(new_photo_id)
         photo_id = self._get_photo_id(photo_url)
         if self.photo_id == photo_id:
             return
diff --git a/mautrix_facebook/puppet.py b/mautrix_facebook/puppet.py
index 4808fc7..f896680 100644
--- a/mautrix_facebook/puppet.py
+++ b/mautrix_facebook/puppet.py
@@ -18,7 +18,7 @@ import logging
 import asyncio
 import attr
 
-from fbchat.models import User as FBUser
+from fbchat import User as FBUser
 from mautrix.types import UserID, RoomID, SyncToken
 from mautrix.appservice import AppService, IntentAPI
 from mautrix.bridge.custom_puppet import CustomPuppetMixin
diff --git a/mautrix_facebook/user.py b/mautrix_facebook/user.py
index 8ef9f92..554cd52 100644
--- a/mautrix_facebook/user.py
+++ b/mautrix_facebook/user.py
@@ -18,8 +18,7 @@ from http.cookies import SimpleCookie
 import asyncio
 import logging
 
-from fbchat import Client
-from fbchat.models import Message, ThreadType, User as FBUser, ActiveStatus, MessageReaction
+from fbchat import Client, Message, ThreadType, User as FBUser, ActiveStatus, MessageReaction
 
 from mautrix.types import UserID, PresenceState
 from mautrix.appservice import AppService
@@ -73,7 +72,7 @@ class User(Client):
         self._log = self._log.getChild(self.mxid)
         self._req_log = self._req_log.getChild(self.mxid)
         self._util_log = self._util_log.getChild(self.mxid)
-        self.setActiveStatus(False)
+        self.set_active_status(False)
 
     # region Sessions
 
@@ -84,13 +83,14 @@ class User(Client):
     @property
     def db_instance(self) -> DBUser:
         if not self._db_instance:
-            self._db_instance = DBUser(mxid=self.mxid, session=self._session_data, fbid=self.uid, user_agent=self.user_agent)
+            self._db_instance = DBUser(mxid=self.mxid, session=self._session_data, fbid=self.uid,
+                                       user_agent=self.user_agent)
         return self._db_instance
 
     def save(self, _update_session_data: bool = True) -> None:
         self.log.debug("Saving session")
         if _update_session_data:
-            self._session_data = self.getSession()
+            self._session_data = self.get_session()
         self.db_instance.edit(session=self._session_data, fbid=self.uid,
                               user_agent=self.user_agent)
 
@@ -142,7 +142,7 @@ class User(Client):
             return True
         elif not self._session_data:
             return False
-        ok = (await self.setSession(self._session_data, user_agent=self.user_agent)
+        ok = (await self.set_session(self._session_data, user_agent=self.user_agent)
               and await self.is_logged_in(True))
         if ok:
             self.log.info("Loaded session successfully")
@@ -152,13 +152,13 @@ class User(Client):
 
     async def is_logged_in(self, _override: bool = False) -> bool:
         if self._is_logged_in is None or _override:
-            self._is_logged_in = await self.isLoggedIn()
+            self._is_logged_in = await super().is_logged_in()
         return self._is_logged_in
 
     # endregion
 
     async def logout(self) -> bool:
-        self.stopListening()
+        self.stop_listening()
         ok = await super().logout()
         self._session_data = None
         self._is_logged_in = False
@@ -172,7 +172,7 @@ class User(Client):
         await self.sync_contacts()
         await self.sync_threads()
         self.log.debug("Updating own puppet info")
-        own_info = (await self.fetchUserInfo(self.uid))[self.uid]
+        own_info = (await self.fetch_user_info(self.uid))[self.uid]
         puppet = pu.Puppet.get_by_fbid(self.uid, create=True)
         await puppet.update_info(source=self, info=own_info)
 
@@ -217,7 +217,7 @@ class User(Client):
     async def sync_contacts(self):
         try:
             self.log.debug("Fetching contacts...")
-            users = await self.fetchAllUsers()
+            users = await self.fetch_all_users()
             self.log.debug(f"Fetched {len(users)} contacts")
             contacts = DBContact.all(self.fbid)
             update_avatars = config["bridge.update_avatar_initial_sync"]
@@ -234,7 +234,7 @@ class User(Client):
             if sync_count <= 0:
                 return
             self.log.debug("Fetching threads...")
-            threads = await self.fetchThreadList(limit=sync_count)
+            threads = await self.fetch_thread_list(limit=sync_count)
             ups = DBUserPortal.all(self.fbid)
             contacts = DBContact.all(self.fbid)
             for thread in threads:
@@ -257,10 +257,10 @@ class User(Client):
 
     # region Facebook event handling
 
-    async def onLoggingIn(self, email: str = None) -> None:
+    async def on_logging_in(self, email: str = None) -> None:
         self.log.info("Logging in {}...".format(email))
 
-    async def on2FACode(self) -> str:
+    async def on2fa_code(self) -> str:
         if self.command_status and self.command_status.get("action", "") == "Login":
             future = self.loop.create_future()
             self.command_status["future"] = future
@@ -272,7 +272,7 @@ class User(Client):
         self.log.warning("Unexpected on2FACode call")
         # raise RuntimeError("No ongoing login command")
 
-    async def onLoggedIn(self, email: str = None) -> None:
+    async def on_logged_in(self, email: str = None) -> None:
         """
         Called when the client is successfully logged in
 
@@ -288,11 +288,11 @@ class User(Client):
         self.log.warning("Unexpected onLoggedIn call")
         # raise RuntimeError("No ongoing login command")
 
-    async def onListening(self) -> None:
+    async def on_listening(self) -> None:
         """Called when the client is listening"""
         self.log.info("Listening...")
 
-    async def onListenError(self, exception: Exception = None) -> bool:
+    async def on_listen_error(self, exception: Exception = None) -> bool:
         """
         Called when an error was encountered while listening
 
@@ -303,10 +303,10 @@ class User(Client):
         await asyncio.sleep(10)
         return True
 
-    async def onMessage(self, mid: str = None, author_id: str = None, message: str = None,
-                        message_object: Message = None, thread_id: str = None,
-                        thread_type: ThreadType = ThreadType.USER, ts: int = None,
-                        metadata: Any = None, msg: Any = None) -> None:
+    async def on_message(self, mid: str = None, author_id: str = None, message: str = None,
+                         message_object: Message = None, thread_id: str = None,
+                         thread_type: ThreadType = ThreadType.USER, at: int = None,
+                         metadata: Any = None, msg: Any = None) -> None:
         """
         Called when the client is listening, and somebody sends a message
 
@@ -316,7 +316,7 @@ class User(Client):
         :param message_object: The message (As a `Message` object)
         :param thread_id: Thread ID that the message was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the message was sent to. See :ref:`intro_threads`
-        :param ts: The timestamp of the message
+        :param at: The timestamp of the message
         :param metadata: Extra metadata about the message
         :param msg: A full set of the data recieved
         :type message_object: models.Message
@@ -331,9 +331,9 @@ class User(Client):
         message_object.uid = mid
         await portal.handle_facebook_message(self, puppet, message_object)
 
-    async def onColorChange(self, mid=None, author_id=None, new_color=None, thread_id=None,
-                            thread_type=ThreadType.USER, ts=None, metadata=None, msg=None
-                            ) -> None:
+    async def on_color_change(self, mid=None, author_id=None, new_color=None, thread_id=None,
+                              thread_type=ThreadType.USER, at=None, metadata=None, msg=None
+                              ) -> None:
         """
         Called when the client is listening, and somebody changes a thread's color
 
@@ -342,7 +342,7 @@ class User(Client):
         :param new_color: The new color
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type new_color: models.ThreadColor
@@ -354,9 +354,9 @@ class User(Client):
             )
         )
 
-    async def onEmojiChange(self, mid=None, author_id=None, new_emoji=None, thread_id=None,
-                            thread_type=ThreadType.USER, ts=None, metadata=None, msg=None
-                            ) -> None:
+    async def on_emoji_change(self, mid=None, author_id=None, new_emoji=None, thread_id=None,
+                              thread_type=ThreadType.USER, at=None, metadata=None, msg=None
+                              ) -> None:
         """
         Called when the client is listening, and somebody changes a thread's emoji
 
@@ -365,7 +365,7 @@ class User(Client):
         :param new_emoji: The new emoji
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -376,9 +376,9 @@ class User(Client):
             )
         )
 
-    async def onTitleChange(self, mid=None, author_id=None, new_title=None, thread_id=None,
-                            thread_type=ThreadType.USER, ts=None, metadata=None, msg=None
-                            ) -> None:
+    async def on_title_change(self, mid=None, author_id=None, new_title=None, thread_id=None,
+                              thread_type=ThreadType.USER, at=None, metadata=None, msg=None
+                              ) -> None:
         """
         Called when the client is listening, and somebody changes the title of a thread
 
@@ -387,7 +387,7 @@ class User(Client):
         :param new_title: The new title
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -401,9 +401,9 @@ class User(Client):
             return
         await portal.handle_facebook_name(self, sender, new_title, mid)
 
-    async def onImageChange(self, mid: str = None, author_id: str = None, new_image: str = None,
-                            thread_id: str = None, thread_type: ThreadType = ThreadType.GROUP,
-                            ts: int = None, msg: Any = None) -> None:
+    async def on_image_change(self, mid: str = None, author_id: str = None, new_image: str = None,
+                              thread_id: str = None, thread_type: ThreadType = ThreadType.GROUP,
+                              at: int = None, msg: Any = None) -> None:
         """
         Called when the client is listening, and somebody changes the image of a thread
 
@@ -412,7 +412,7 @@ class User(Client):
         :param new_image: The ID of the new image
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
@@ -425,9 +425,11 @@ class User(Client):
             return
         await portal.handle_facebook_photo(self, sender, new_image, mid)
 
-    async def onNicknameChange(self, mid=None, author_id=None, changed_for=None, new_nickname=None,
-                               thread_id=None, thread_type=ThreadType.USER, ts=None, metadata=None,
-                               msg=None) -> None:
+    async def on_nickname_change(self, mid=None, author_id=None, changed_for=None,
+                                 new_nickname=None,
+                                 thread_id=None, thread_type=ThreadType.USER, at=None,
+                                 metadata=None,
+                                 msg=None) -> None:
         """
         Called when the client is listening, and somebody changes the nickname of a person
 
@@ -437,7 +439,7 @@ class User(Client):
         :param new_nickname: The new nickname
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -448,8 +450,8 @@ class User(Client):
             )
         )
 
-    async def onAdminAdded(self, mid=None, added_id=None, author_id=None, thread_id=None,
-                           thread_type=ThreadType.GROUP, ts=None, msg=None) -> None:
+    async def on_admin_added(self, mid=None, added_id=None, author_id=None, thread_id=None,
+                             thread_type=ThreadType.GROUP, at=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody adds an admin to a group thread
 
@@ -458,13 +460,13 @@ class User(Client):
         :param author_id: The ID of the person who added the admins
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         self.log.info("{} added admin: {} in {}".format(author_id, added_id, thread_id))
 
-    async def onAdminRemoved(self, mid=None, removed_id=None, author_id=None, thread_id=None,
-                             thread_type=ThreadType.GROUP, ts=None, msg=None):
+    async def on_admin_removed(self, mid=None, removed_id=None, author_id=None, thread_id=None,
+                               thread_type=ThreadType.GROUP, at=None, msg=None):
         """
         Called when the client is listening, and somebody removes an admin from a group thread
 
@@ -472,14 +474,15 @@ class User(Client):
         :param removed_id: The ID of the admin who got removed
         :param author_id: The ID of the person who removed the admins
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         self.log.info("{} removed admin: {} in {}".format(author_id, removed_id, thread_id))
 
-    async def onApprovalModeChange(self, mid=None, approval_mode=None, author_id=None,
-                                   thread_id=None, thread_type=ThreadType.GROUP, ts=None,
-                                   msg=None) -> None:
+    async def on_approval_mode_change(self, mid=None, approval_mode=None, author_id=None,
+                                      thread_id=None, thread_type=ThreadType.GROUP, at=None,
+                                      msg=None) -> None:
         """
         Called when the client is listening, and somebody changes approval mode in a group thread
 
@@ -487,7 +490,8 @@ class User(Client):
         :param approval_mode: True if approval mode is activated
         :param author_id: The ID of the person who changed approval mode
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         if approval_mode:
@@ -495,17 +499,17 @@ class User(Client):
         else:
             self.log.info("{} disabled approval mode in {}".format(author_id, thread_id))
 
-    async def onMessageSeen(self, seen_by: str = None, thread_id: str = None,
-                            thread_type=ThreadType.USER, seen_ts: int = None, ts: int = None,
-                            metadata: Any = None, msg: Any = None) -> None:
+    async def on_message_seen(self, seen_by: str = None, thread_id: str = None,
+                              thread_type=ThreadType.USER, seen_at: int = None, at: int = None,
+                              metadata: Any = None, msg: Any = None) -> None:
         """
         Called when the client is listening, and somebody marks a message as seen
 
         :param seen_by: The ID of the person who marked the message as seen
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param seen_ts: A timestamp of when the person saw the message
-        :param ts: A timestamp of the action
+        :param seen_at: A timestamp of when the person saw the message
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -515,9 +519,9 @@ class User(Client):
         puppet = pu.Puppet.get_by_fbid(seen_by)
         await portal.handle_facebook_seen(self, puppet)
 
-    async def onMessageDelivered(self, msg_ids=None, delivered_for=None, thread_id=None,
-                                 thread_type=ThreadType.USER, ts=None, metadata=None, msg=None
-                                 ) -> None:
+    async def on_message_delivered(self, msg_ids=None, delivered_for=None, thread_id=None,
+                                   thread_type=ThreadType.USER, at=None, metadata=None, msg=None
+                                   ) -> None:
         """
         Called when the client is listening, and somebody marks messages as delivered
 
@@ -525,39 +529,37 @@ class User(Client):
         :param delivered_for: The person that marked the messages as delivered
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
         self.log.info(
             "Messages {} delivered to {} in {} ({}) at {}s".format(
-                msg_ids, delivered_for, thread_id, thread_type.name, ts / 1000
+                msg_ids, delivered_for, thread_id, thread_type.name, at
             )
         )
 
-    async def onMarkedSeen(self, threads=None, seen_ts=None, ts=None, metadata=None, msg=None
-                           ) -> None:
+    async def on_marked_seen(self, threads=None, seen_at=None, at=None, metadata=None, msg=None
+                             ) -> None:
         """
         Called when the client is listening, and the client has successfully marked threads as seen
 
         :param threads: The threads that were marked
-        :param author_id: The ID of the person who changed the emoji
-        :param seen_ts: A timestamp of when the threads were seen
-        :param ts: A timestamp of the action
+        :param seen_at: A timestamp of when the threads were seen
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
-        :type thread_type: models.ThreadType
         """
         self.log.info(
             "Marked messages as seen in threads {} at {}s".format(
-                [(x[0], x[1].name) for x in threads], seen_ts / 1000
+                [(x[0], x[1].name) for x in threads], seen_at
             )
         )
 
-    async def onMessageUnsent(self, mid: str = None, author_id: str = None, thread_id: str = None,
-                              thread_type: ThreadType = None, ts: int = None,
-                              msg: Any = None) -> None:
+    async def on_message_unsent(self, mid: str = None, author_id: str = None,
+                                thread_id: str = None, thread_type: ThreadType = None,
+                                at: int = None, msg: Any = None) -> None:
         """
         Called when the client is listening, and someone unsends (deletes for everyone) a message
 
@@ -565,7 +567,7 @@ class User(Client):
         :param author_id: The ID of the person who unsent the message
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
@@ -574,8 +576,8 @@ class User(Client):
         puppet = pu.Puppet.get_by_fbid(author_id)
         await portal.handle_facebook_unsend(self, puppet, mid)
 
-    async def onPeopleAdded(self, mid=None, added_ids=None, author_id=None, thread_id=None,
-                            ts=None, msg=None) -> None:
+    async def on_people_added(self, mid=None, added_ids=None, author_id=None, thread_id=None,
+                              at=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody adds people to a group thread
 
@@ -583,15 +585,15 @@ class User(Client):
         :param added_ids: The IDs of the people who got added
         :param author_id: The ID of the person who added the people
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         self.log.info(
             "{} added: {} in {}".format(author_id, ", ".join(added_ids), thread_id)
         )
 
-    async def onPersonRemoved(self, mid=None, removed_id=None, author_id=None, thread_id=None,
-                              ts=None, msg=None) -> None:
+    async def on_person_removed(self, mid=None, removed_id=None, author_id=None, thread_id=None,
+                                at=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody removes a person from a group thread
 
@@ -599,12 +601,12 @@ class User(Client):
         :param removed_id: The ID of the person who got removed
         :param author_id: The ID of the person who removed the person
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         self.log.info("{} removed: {} in {}".format(author_id, removed_id, thread_id))
 
-    async def onFriendRequest(self, from_id=None, msg=None) -> None:
+    async def on_friend_request(self, from_id=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody sends a friend request
 
@@ -613,7 +615,7 @@ class User(Client):
         """
         self.log.info("Friend request from {}".format(from_id))
 
-    async def onInbox(self, unseen=None, unread=None, recent_unread=None, msg=None) -> None:
+    async def on_inbox(self, unseen=None, unread=None, recent_unread=None, msg=None) -> None:
         """
         .. todo::
             Documenting this
@@ -625,8 +627,8 @@ class User(Client):
         """
         self.log.info("Inbox event: {}, {}, {}".format(unseen, unread, recent_unread))
 
-    async def onTyping(self, author_id=None, status=None, thread_id=None, thread_type=None,
-                       msg=None) -> None:
+    async def on_typing(self, author_id=None, status=None, thread_id=None, thread_type=None,
+                        msg=None) -> None:
         """
         Called when the client is listening, and somebody starts or stops typing into a chat
 
@@ -635,14 +637,14 @@ class User(Client):
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
         :param msg: A full set of the data recieved
-        :type typing_status: models.TypingStatus
         :type thread_type: models.ThreadType
         """
         self.log.info(f"User is typing: {author_id} {status} in {thread_id} {thread_type}")
 
-    async def onGamePlayed(self, mid=None, author_id=None, game_id=None, game_name=None,
-                           score=None, leaderboard=None, thread_id=None, thread_type=None, ts=None,
-                           metadata=None, msg=None) -> None:
+    async def on_game_played(self, mid=None, author_id=None, game_id=None, game_name=None,
+                             score=None, leaderboard=None, thread_id=None, thread_type=None,
+                             at=None,
+                             metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody plays a game
 
@@ -654,7 +656,7 @@ class User(Client):
         :param leaderboard: Actual leaderboard of the game in the thread
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -665,10 +667,10 @@ class User(Client):
             )
         )
 
-    async def onReactionAdded(self, mid: str = None, reaction: MessageReaction = None,
-                              author_id: str = None, thread_id: str = None,
-                              thread_type: ThreadType = None, ts: int = None, msg: Any = None
-                              ) -> None:
+    async def on_reaction_added(self, mid: str = None, reaction: MessageReaction = None,
+                                author_id: str = None, thread_id: str = None,
+                                thread_type: ThreadType = None, at: int = None, msg: Any = None
+                                ) -> None:
         """
         Called when the client is listening, and somebody reacts to a message
 
@@ -677,7 +679,7 @@ class User(Client):
         :param author_id: The ID of the person who reacted to the message
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type reaction: models.MessageReaction
         :type thread_type: models.ThreadType
@@ -689,9 +691,9 @@ class User(Client):
         puppet = pu.Puppet.get_by_fbid(author_id)
         await portal.handle_facebook_reaction_add(self, puppet, mid, reaction.value)
 
-    async def onReactionRemoved(self, mid: str = None, author_id: str = None,
-                                thread_id: str = None, thread_type: ThreadType = None,
-                                ts: int = None, msg: Any = None) -> None:
+    async def on_reaction_removed(self, mid: str = None, author_id: str = None,
+                                  thread_id: str = None, thread_type: ThreadType = None,
+                                  at: int = None, msg: Any = None) -> None:
         """
         Called when the client is listening, and somebody removes reaction from a message
 
@@ -699,7 +701,7 @@ class User(Client):
         :param author_id: The ID of the person who removed reaction
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
@@ -709,15 +711,15 @@ class User(Client):
         puppet = pu.Puppet.get_by_fbid(author_id)
         await portal.handle_facebook_reaction_remove(self, puppet, mid)
 
-    async def onBlock(self, author_id=None, thread_id=None, thread_type=None, ts=None, msg=None
-                      ) -> None:
+    async def on_block(self, author_id=None, thread_id=None, thread_type=None, at=None, msg=None
+                       ) -> None:
         """
         Called when the client is listening, and somebody blocks client
 
         :param author_id: The ID of the person who blocked
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
@@ -725,15 +727,15 @@ class User(Client):
             "{} blocked {} ({}) thread".format(author_id, thread_id, thread_type.name)
         )
 
-    async def onUnblock(self, author_id=None, thread_id=None, thread_type=None, ts=None, msg=None
-                        ) -> None:
+    async def on_unblock(self, author_id=None, thread_id=None, thread_type=None, at=None, msg=None
+                         ) -> None:
         """
         Called when the client is listening, and somebody blocks client
 
         :param author_id: The ID of the person who unblocked
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
         """
@@ -741,8 +743,8 @@ class User(Client):
             "{} unblocked {} ({}) thread".format(author_id, thread_id, thread_type.name)
         )
 
-    async def onLiveLocation(self, mid=None, location=None, author_id=None, thread_id=None,
-                             thread_type=None, ts=None, msg=None) -> None:
+    async def on_live_location(self, mid=None, location=None, author_id=None, thread_id=None,
+                               thread_type=None, at=None, msg=None) -> None:
         """
         Called when the client is listening and somebody sends live location info
 
@@ -751,7 +753,7 @@ class User(Client):
         :param author_id: The ID of the person who sent location info
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         :type location: models.LiveLocationAttachment
         :type thread_type: models.ThreadType
@@ -762,8 +764,8 @@ class User(Client):
             )
         )
 
-    async def onCallStarted(self, mid=None, caller_id=None, is_video_call=None, thread_id=None,
-                            thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_call_started(self, mid=None, caller_id=None, is_video_call=None, thread_id=None,
+                              thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         .. todo::
             Make this work with private calls
@@ -775,7 +777,7 @@ class User(Client):
         :param is_video_call: True if it's video call
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -784,9 +786,9 @@ class User(Client):
             "{} started call in {} ({})".format(caller_id, thread_id, thread_type.name)
         )
 
-    async def onCallEnded(self, mid=None, caller_id=None, is_video_call=None, call_duration=None,
-                          thread_id=None, thread_type=None, ts=None, metadata=None, msg=None
-                          ) -> None:
+    async def on_call_ended(self, mid=None, caller_id=None, is_video_call=None, call_duration=None,
+                            thread_id=None, thread_type=None, at=None, metadata=None, msg=None
+                            ) -> None:
         """
         .. todo::
             Make this work with private calls
@@ -799,7 +801,7 @@ class User(Client):
         :param call_duration: Call duration in seconds
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -808,8 +810,9 @@ class User(Client):
             "{} ended call in {} ({})".format(caller_id, thread_id, thread_type.name)
         )
 
-    async def onUserJoinedCall(self, mid=None, joined_id=None, is_video_call=None, thread_id=None,
-                               thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_user_joined_call(self, mid=None, joined_id=None, is_video_call=None,
+                                  thread_id=None,
+                                  thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody joins a group call
 
@@ -818,7 +821,7 @@ class User(Client):
         :param is_video_call: True if it's video call
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type thread_type: models.ThreadType
@@ -827,8 +830,8 @@ class User(Client):
             "{} joined call in {} ({})".format(joined_id, thread_id, thread_type.name)
         )
 
-    async def onPollCreated(self, mid=None, poll=None, author_id=None, thread_id=None,
-                            thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_poll_created(self, mid=None, poll=None, author_id=None, thread_id=None,
+                              thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody creates a group poll
 
@@ -837,7 +840,7 @@ class User(Client):
         :param author_id: The ID of the person who created the poll
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type poll: models.Poll
@@ -849,9 +852,10 @@ class User(Client):
             )
         )
 
-    async def onPollVoted(self, mid=None, poll=None, added_options=None, removed_options=None,
-                          author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None,
-                          msg=None) -> None:
+    async def on_poll_voted(self, mid=None, poll=None, added_options=None, removed_options=None,
+                            author_id=None, thread_id=None, thread_type=None, at=None,
+                            metadata=None,
+                            msg=None) -> None:
         """
         Called when the client is listening, and somebody votes in a group poll
 
@@ -860,7 +864,7 @@ class User(Client):
         :param author_id: The ID of the person who voted in the poll
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type poll: models.Poll
@@ -872,8 +876,8 @@ class User(Client):
             )
         )
 
-    async def onPlanCreated(self, mid=None, plan=None, author_id=None, thread_id=None,
-                            thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_plan_created(self, mid=None, plan=None, author_id=None, thread_id=None,
+                              thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody creates a plan
 
@@ -882,7 +886,7 @@ class User(Client):
         :param author_id: The ID of the person who created the plan
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type plan: models.Plan
@@ -894,8 +898,8 @@ class User(Client):
             )
         )
 
-    async def onPlanEnded(self, mid=None, plan=None, thread_id=None, thread_type=None, ts=None,
-                          metadata=None, msg=None):
+    async def on_plan_ended(self, mid=None, plan=None, thread_id=None, thread_type=None, at=None,
+                            metadata=None, msg=None):
         """
         Called when the client is listening, and a plan ends
 
@@ -903,7 +907,7 @@ class User(Client):
         :param plan: Ended plan
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type plan: models.Plan
@@ -913,8 +917,8 @@ class User(Client):
             "Plan {} has ended in {} ({})".format(plan, thread_id, thread_type.name)
         )
 
-    async def onPlanEdited(self, mid=None, plan=None, author_id=None, thread_id=None,
-                           thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_plan_edited(self, mid=None, plan=None, author_id=None, thread_id=None,
+                             thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody edits a plan
 
@@ -923,7 +927,7 @@ class User(Client):
         :param author_id: The ID of the person who edited the plan
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type plan: models.Plan
@@ -935,8 +939,8 @@ class User(Client):
             )
         )
 
-    async def onPlanDeleted(self, mid=None, plan=None, author_id=None, thread_id=None,
-                            thread_type=None, ts=None, metadata=None, msg=None) -> None:
+    async def on_plan_deleted(self, mid=None, plan=None, author_id=None, thread_id=None,
+                              thread_type=None, at=None, metadata=None, msg=None) -> None:
         """
         Called when the client is listening, and somebody deletes a plan
 
@@ -945,7 +949,7 @@ class User(Client):
         :param author_id: The ID of the person who deleted the plan
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type plan: models.Plan
@@ -957,9 +961,9 @@ class User(Client):
             )
         )
 
-    async def onPlanParticipation(self, mid=None, plan=None, take_part=None, author_id=None,
-                                  thread_id=None, thread_type=None, ts=None, metadata=None,
-                                  msg=None) -> None:
+    async def on_plan_participation(self, mid=None, plan=None, take_part=None, author_id=None,
+                                    thread_id=None, thread_type=None, at=None, metadata=None,
+                                    msg=None) -> None:
         """
         Called when the client is listening, and somebody takes part in a plan or not
 
@@ -969,7 +973,7 @@ class User(Client):
         :param author_id: The ID of the person who will participate in the plan or not
         :param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
         :param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param metadata: Extra metadata about the action
         :param msg: A full set of the data recieved
         :type plan: models.Plan
@@ -989,17 +993,17 @@ class User(Client):
                 )
             )
 
-    async def onQprimer(self, ts=None, msg=None) -> None:
+    async def on_qprimer(self, at=None, msg=None) -> None:
         """
         Called when the client just started listening
 
-        :param ts: A timestamp of the action
+        :param at: A timestamp of the action
         :param msg: A full set of the data recieved
         """
         pass
 
-    async def onChatTimestamp(self, buddylist: Dict[str, ActiveStatus] = None, msg: Any = None
-                              ) -> None:
+    async def on_chat_timestamp(self, buddylist: Dict[str, ActiveStatus] = None, msg: Any = None
+                                ) -> None:
         """
         Called when the client receives chat online presence update
 
@@ -1013,8 +1017,8 @@ class User(Client):
                     presence=PresenceState.ONLINE if status.active else PresenceState.OFFLINE,
                     ignore_cache=True)
 
-    async def onBuddylistOverlay(self, statuses: Dict[str, ActiveStatus] = None, msg: Any = None
-                                 ) -> None:
+    async def on_buddylist_overlay(self, statuses: Dict[str, ActiveStatus] = None, msg: Any = None
+                                   ) -> None:
         """
         Called when the client is listening and client receives information about friend active status
 
@@ -1022,9 +1026,9 @@ class User(Client):
         :param msg: A full set of the data recieved
         :type statuses: dict
         """
-        await self.onChatTimestamp(statuses, msg)
+        await self.on_chat_timestamp(statuses, msg)
 
-    async def onUnknownMesssageType(self, msg: Any = None) -> None:
+    async def on_unknown_messsage_type(self, msg: Any = None) -> None:
         """
         Called when the client is listening, and some unknown data was recieved
 
@@ -1032,7 +1036,7 @@ class User(Client):
         """
         self.log.debug("Unknown message received: {}".format(msg))
 
-    async def onMessageError(self, exception: Exception = None, msg: Any = None) -> None:
+    async def on_message_error(self, exception: Exception = None, msg: Any = None) -> None:
         """
         Called when an error was encountered while parsing recieved data
 
-- 
GitLab