-
Notifications
You must be signed in to change notification settings - Fork 412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API Design - Request for feedback #526
Comments
Oops sorry for getting to this so late. I do have some input Interacting with threads looks a lot better now! But I still have one concern. Since all of this is done by ID and I don't want to send too many requests and get banned (I've gotten temporarily suspended more than I would like). My solution to this is making two dictionaries that maps a persons/group name to their/its id and backwards. So I can do something like this
Now you definitely have to make an object per group/person you're interacting with. Originally I could just do The listening seems pretty intuitive which is great! My guess is for the onX methods, youd just do more of
Is that right? If we have to do that, what is the default use? Originally, you could see what the Client's method was and then override it. Mostly it was just printing stuff out Lastly, how difficult would it be to change from the v1 to the new v2? I assume that installing will be as easy as a pip install but the code would need a refactoring? I know this is a ways out though. Ive lost a few projects due to unfortunate events so I have to redo them . But I don't want to get too deep into a v1 project if I can wait for v2 |
This is important. Is User/Group already in |
I'll try to answer as best as I can, @syspic, but I may not have understood everything fully, so please elaborate if my answer doesn't make sense 😉.
A problem with
Like @TheLastGimbus noted, the
I haven't really thought this through entirely, but I think I wanted it to work with type hints. So the function name is irrelevant. The following two functions would both listen to the @listener.register
def do_echo(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.register
def kick_people(event: fbchat.MessageEvent):
if event.message.text == 'Kick me!':
event.thread.remove_participant(event.author) Alternatively, if this seems a little magical, we could just take a parameter to the @listener.register(fbchat.MessageEvent)
def do_echo(event):
# If you're not the author, echo
if event.author.id != session.user.id:
event.thread.send_text(event.message.text)
Probably very. The API surface was almost entirely on the Hope that answers your concerns, thanks for the questions! |
To @TheLastGimbus, if you know the ID, creating a new |
Okay, so how do I know User.name by just passing it ID? How does it know? Does Group contain something like Group.members? |
A little explanation: user = fbchat.User(session=session, id="123") # Does not call facebook, therefore doesn't contain further data
user.send_text('abc')
user.name # Raises an error And then there's users = list(client.search_for_users('Abc', limit=1)) # Calls facebook, and recieves relevant data
print(users[0].name)
users[0].send_text('abc') So when listening for messages, you would get a id_to_name = {}
@listener.register(fbchat.MessageEvent)
def do_echo(event):
if event.author.id not in id_to_name:
# Fetch name, and cache for future usage
author, = client.fetch_thread_info([event.author.id])
id_to_name[author.id] = author.name
if event.author.id != session.user.id:
event.thread.send_text(f"Hello there {id_to_name[event.author.id]}") |
I hope this makes sense, if you have ideas on how to improve this design, or if it seems confusing, let me know! 🙂 |
Thank you for your work on Fbchat. I used it once but it received an error due to fact the my message was in the MARKETPLACE folder. Have you or are you planning on supporting this addition object? Additionally, have you looked at using BERT in text analytics within FB messages?
Many thanks
Tim Zimmerman
Sent from Yahoo Mail for iPhone
On Wednesday, February 5, 2020, 8:19 AM, Mads Marquart <[email protected]> wrote:
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 #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 #396 for the wishlist, and feature requests
Thanks for your time 👍
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Hmm, I don't know what BERT is? But yeah, I do want to support the MARKETPLACE stuff, I just haven't had access to it myself, so I haven't seen the errors everyone else are getting 🙄 |
Thank you for the response. I will have to go to the office to see if I can recreate the error. You might just go to marketplace and post something for sale and have some friends of yours send you some messages for your test data.
Here is the info on BERT. https://www.searchenginejournal.com/bert-explained-what-you-need-to-know-about-googles-new-algorithm/337247/
Regards
Tim Zimmerman
Sent from Yahoo Mail for iPhone
On Friday, March 6, 2020, 9:57 AM, Mads Marquart <[email protected]> wrote:
Hmm, I don't know what BERT is? But yeah, I do want to support the MARKETPLACE stuff, I just haven't had access to it myself, so I haven't seen the errors everyone else are getting 🙄
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Here is an example of BERT in a chatbot https://pypi.org/project/Bert-Chatbot/#data
Sent from Yahoo Mail for iPhone
On Friday, March 6, 2020, 9:57 AM, Mads Marquart <[email protected]> wrote:
Hmm, I don't know what BERT is? But yeah, I do want to support the MARKETPLACE stuff, I just haven't had access to it myself, so I haven't seen the errors everyone else are getting 🙄
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
A quick notification, I've released an alpha version But now you have something to play with, then we can better start talking how it should work in detail! |
Hi everyone, I've seen the gap between the current documentation and the code I have in my Git repository, so I investigated a bit more. I appreciate most of the changes I saw and thought I would just be installing using One thing I couldn't work with, however, which is a big issue, is the listener. The Reading this post, I realize with pleasure I was highly mistaken and this listener is going to be great and have an interesting syntax. Registering functions sounds somewhat good to me. The only thing I fear: how to persist data in this context? I mean, if you do something like: @listener.register(...)
def whatever():
... ... and if you need to store data in your callable, how are you going to do it? I don't much like using globals for that when I can help it. LAST_USER = None
@listener.register(...)
def whatever():
global LAST_USER # Haha gotcha! Storing data as an instance attribute seems much more natural and Pythonic. But it sounds like: class Storage:
@listener.register(...)
def whatever(event):
self.last_user = event.user ... might not fly since the callable hint types will be different (thanks to Also it seems the listener wasn't implemented in this way. I couldn't find an example of code, but if you do have one to share, I would appreciate. Thanks for your great work.Hi everyone, I've seen the gap between the current documentation and the code I have in my Git repository, so I investigated a bit more. I appreciate most of the changes I saw and thought I would just be installing using One thing I couldn't work with, however, which is a big issue, is the listener. The Reading this post, I realize with pleasure I was highly mistaken and this listener is going to be great and have an interesting syntax. Registering functions sounds somewhat good to me. The only thing I fear: how to persist data in this context? I mean, if you do something like: @listener.register(...)
def whatever():
... ... and if you need to store data in your callable, how are you going to do it? I don't much like using globals for that when I can help it. LAST_USER = None
@listener.register(...)
def whatever():
global LAST_USER # Haha gotcha! Storing data as an instance attribute seems much more natural and Pythonic. But it sounds like: class Storage:
@listener.register(...)
def whatever(event):
self.last_user = event.user ... might not fly since the callable hint types will be different (thanks to Also it seems the listener wasn't implemented in this way. I couldn't find an example of code, but if you do have one to share, I would appreciate. Thanks for your great work. |
Does a configurable global rate limit sound like a good idea? It can be really basic like you set the time in seconds that you can send 10 requests in and if you attempt to make any more requests just add them to a queue that'll roll out the next 10 requests after the rate limit is over. |
What you want to accomplish with it? Lower possibility to be caught as a bot by Facebook? I don't think it will help, and it will just add complexity. If you will keep sending 1 request every second, it's still gonna look suspicious. If you send 10 requests in 5 seconds but once for 2 days - it's okay. |
Hey! Its been a while since I've used this fbchat and want to use this again. Last time, there was an issue where listening didnt work and it was fixed in the branch by tulir/fbchat-asyncio. Has that issue been fixed here/v1 and is v2 been released (I dont think it has)? Thanks! Looking forward to getting into making some bots again. Mostly just listening and logging things |
@TheLastGimbus Thanks for the reply! (and sorry for the delay). I could try that out! Super dumb question, but how would I install it? Im assuming its not ready for I mostly just want to listen (when a message comes in, reacts, etc) and log it to a file. Do you think that would be doable with v2 as it stands? I dont have plans of replying/changing chat name/etc as of now Its super simple but v2 is different from v1 so ill have to get used to it lol |
Honestly, I don't know, but v2 is probably capable of doing such things already. Or, as pypi site states, you can install it from source:
I need to get back to this library and see how it looks, and commit to it a bit, but I will most probably have time at the end of the super/after it ends :/ |
quick update: I was able to get what I needed by using the V1 branch. I didn't want to go refactor everything. I think |
Just add
As far as I know, v1 branch will always be at 1.9.x, or 1.x.x, and v2 development is going on master branch. Stage at which the branch is at certain version is marked with proper tag, named like
You can watch this repo on GitHub, select "Releases only" and you will get notification/email when new version comes out |
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:
client.changeThreadColor(color, thread_id=thread_id)
->thread.set_color(color)
async
/await
, backed byasyncio
- Not yet implemented, follow asyncio fbchat #411 for moreInterracting 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 aThreadType
. This was pretty error prone, and involved a lot of extra typing. Now you simply create aGroup
/User
object (or more often, fetch it from somewhere), and call methods on that.An example:
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 anonX
method. This was pretty error prone, and made it difficult for me to add new features. Now you create aListener
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:
A few notes before we round this off:
v1
examples and the current WIP examplesThanks for your time 👍
The text was updated successfully, but these errors were encountered: