Skip to content

API Design - Request for feedback #526

@madsmtm

Description

@madsmtm

Hi everyone, I've been working on v2 for a while now, and it's getting close to a point where I can start making alpha releases!

However, reworking this has been a mostly one-man effort, and I'd really like some input on how these changes are going to suit everyone else (after all, you're probably using this library more than I am 😁). Additionally, if you need me to elaborate on something, or explain the reasoning behind these API choices, I'd be more than happy to!

You can also use this issue as a way of requesting features, if there's something, important or not, we're missing!

A quick primer of major changes before we begin:

  • No Python 2 support
  • Type hints
  • Better listening system (no more error-prone subclassing)
  • Cleaner way of interracting with threads
    • client.changeThreadColor(color, thread_id=thread_id) -> thread.set_color(color)
  • async/await, backed by asyncio - Not yet implemented, follow asyncio fbchat #411 for more

Interracting with threads

Digging a bit further into the details, I'd like input on the changed API when interracting with threads. Previously, you'd call a method in Client with a thread ID and a ThreadType. This was pretty error prone, and involved a lot of extra typing. Now you simply create a Group/User object (or more often, fetch it from somewhere), and call methods on that.

An example:

# Old
import fbchat
client = fbchat.Client("<email>", "<password>")
print("Own id: {}".format(client.uid))

client.send(fbchat.Message(text="Hi me!"), thread_id=client.uid, thread_type=fbchat.ThreadType.USER)

client.send(fbchat.Message(text="Hi group!"), thread_id="<group id>", thread_type=fbchat.ThreadType.GROUP)

# New
import fbchat
session = fbchat.Session.login("<email>", "<password>")
print("Own id: {}".format(session.user.id))

session.user.send_text("Hi me!")

group = fbchat.Group(session=session, id="<group id>")
group.send_text("Hi group!")

Note also how we have pretty clear separation of concerns (Session handles logging in, Group handles interracting with the group).

Listening

Regarding listening, you'd previously override Client, and provide a custom implementation of an onX method. This was pretty error prone, and made it difficult for me to add new features. Now you create a Listener object, and register methods based on type hints.
How this is going to work exactly is very much up for discussion, so please comment on this!

An example:

# Old
import fbchat

class CustomClient(fbchat.Client):
    def onMessage(self, author_id, message, thread_id, thread_type, **kwargs):
        # If you're not the author, echo
        if author_id != self.uid:
            self.send(fbchat.Message(text=message), thread_id=thread_id, thread_type=thread_type)

client = CustomClient("<email>", "<password>")
client.listen()

# New
import fbchat
session = fbchat.Session.login("<email>", "<password>")
listener = fbchat.Listener(session=session, ...)  # TODO: Addition parameters

@listener.register
def on_message(event: fbchat.MessageEvent):
    # If you're not the author, echo
    if event.author.id != session.user.id:
        event.thread.send_text(event.message.text)

listener.run()

A few notes before we round this off:

  • I probably won't be adding caching, the requirements for this changes vastly across applications, so I'd rather provide a solid foundation that people can build this upon
  • See Version 2 wishlist #396 for the wishlist, and feature requests
  • If you want to see more examples of how the API has changed, you can look at the difference between the v1 examples and the current WIP examples

Thanks for your time 👍

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions