from fbchat import log, Client
from ais import abc
# Subclass fbchat.Client and override required methods
class EchoBot(Client):
def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs):
self.markAsDelivered(author_id, thread_id)
self.markAsRead(author_id)
log.info("{} from {} in {}".format(message_object, thread_id, thread_type.name))
# If you're not the author, echo
if author_id != self.uid:
abc(message_object) <-- HERE IS THE PROBLEM
client = EchoBot("email", "password")
client.listen()
The problem is that message_object instead of being the sent message itself (123123) somehow becomes <Message (id): '123123', mentions=[] emoji_size=None attachments=[]> How can i fix this to get the desired result? (123123)
Try to replace
abc(message_object)
with
abc(message_object.text)
Related
I am creating a client with python and "slixmpp" library to connect using xmpp. I have achieved to send a message to a user, but I am not able to recive a message in the program. I am testing with another client (Gajim) to run some test but in that client the message are being recived.
My client has this plugins and this event listeners
class Client(slixmpp.ClientXMPP):
"""
A client class to manage conections an functionalities
Atributes:
jid: string with the JID of the client.
password: string
is_remove: boolean to indicate if need to delete the account
"""
def __init__(self, jid, password, status, status_message):
super().__init__(jid, password)
self.name = jid.split('#')[0]
self.status = status
self.status_message = status_message
self.actual_chat = None
# # plugins
self.register_plugin('xep_0030') # Service Discovery
self.register_plugin('xep_0199') # Ping
self.register_plugin('xep_0045') # MUC
self.register_plugin('xep_0085') # Notifications
self.register_plugin('xep_0004') # Data Forms
self.register_plugin('xep_0060') # PubSub
# events
self.add_event_handler('session_start', self.start)
self.add_event_handler('disco_items', self.print_rooms)
self.add_event_handler('groupchat_message', self.chatroom_message)
self.add_event_handler('message', self.chat_recived)
And this is the function chat_recived
async def chat_recived(self, message):
await aprint('aa')
await aprint('New message', message)
if message['type'] == 'chat':
user = str(message['from']).split('#')[0]
if user == self.actual_chat:
print(f'{message["from"]}: {message["body"]}')
else:
print(f'You have a new message from {message["from"]}')
Does anyone knows why the listener is not reciving the message? This are not even been display in the console when debuger mode is on.
I want to make a "Auto-Reply" on Facebook Messenger using python but I don't know how to do it
If it's possible, can you share the code?
If you use the fbchat library, you can do something like below (the example is from the docs, and just replies back with the same message)
from fbchat import log, Client
# Subclass fbchat.Client and override required methods
class EchoBot(Client):
def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs):
self.markAsDelivered(thread_id, message_object.uid)
self.markAsRead(thread_id)
log.info("{} from {} in {}".format(message_object, thread_id, thread_type.name))
# If you're not the author, echo
if author_id != self.uid:
self.send(message_object, thread_id=thread_id, thread_type=thread_type)
client = EchoBot("<email>", "<password>")
client.listen()
I have a task to create a REST API that will be responsible for handling messages. As a part of the functionality, I should be able to write a message. This message should contain the following fields:
id
sender
receiver
message itself
subject
creation date
So, as I expected to do this is to have a route that should handle the object that I will send as an argument. But I am not sure I can do so. What would you recommend in this case?
For now, I can handle it somehow like this:
#app.route('/new_message/<string:sender>/<string:receiver>/<string:message>/', methods=['POST'])
def get_message(sender, receiver, message):
sender = sender
receiver = receiver
message = message
# Code that will add the data or to the database or to the json file
# if I decide not to implement DB for this task
return 'Sent successfully'
Thanks for your advice!
I am suggesting you to use JSON request body instead of the path parameters for the POST method.
Here is the example,
from flask import request, Flask
app = Flask(__name__)
#app.route('/new_message', methods=['POST'])
def get_message():
payload = request.json()
sender = payload['sender']
receiver = payload['receiver']
message = payload['message']
return 'Sent successfully'
if __name__ == "__main__":
app.run()
Now, If you want to add message as object then you can add it in JSON body. Not only message object you can add any number of fields if required.
I'm learning Django and I'm working in a webpage where I need to offer the user the possibility to log in to an external service. I can't simply use the traditional Django views system because otherwise, I would lose the connection with a simple refresh. For that reason, I thought about using Django Channels.
My problem now is how do I send the data to the consumer class? Using the consumers.py given in the tutorial, I would like to send data from a form submission to the connect function and then make the connection if the login to the external service is ok. Then, in that scenario, I could use the clientinstance and the methods from these external services.
So, in short, is it possible to send form data the consumer? And would this be ok, with respect to security in case of sensitive data?
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
######
## login to external service
######
#get login data from form submited when the websockted is initiated
username = ...
pass = ...
self.client = Client(username, password)
if client:
await self.accept()
# Receive message from room group
async def chat_message(self, event):
message = event['message']
self.client.send(event['message'])
Update:
To clear the explanation: I can't save the user username and pass of the external service, and that I want to offer the user the possibility to use this [sms service](https://clxcommunications.github.io/sdk-xms-python/tutorial.html) with a text field and phone number.
So the problem is that even if I create a form and the username and password to log in (in the view) with
client = clx.xms.Client('myserviceplan', 'mytoken')
then in next request, I would lose the client instance. That's why I thought about Django Channels. But I'm not really sure if it is the best solution...
This will help you.
consumers.py
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import json
class EventConsumer(WebsocketConsumer):
def connect(self):
# self.room_name = self.scope['url_route']['kwargs']['room_name']
# self.room_group_name = 'chat_%s' % self.room_name
self.room_name = 'event'
self.room_group_name = self.room_name+"_sharif"
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
print(self.room_group_name)
self.accept()
print("#######CONNECTED############")
def disconnect(self, code):
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
print("DISCONNECED CODE: ",code)
def receive(self, text_data=None, bytes_data=None):
print(" MESSAGE RECEIVED")
data = json.loads(text_data)
message = data['message']
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,{
"type": 'send_message_to_frontend',
"message": message
}
)
def send_message_to_frontend(self,event):
print("EVENT TRIGERED")
# Receive message from room group
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps({
'message': message
}))
then call the function outside/anywhere from your app like
def event_triger():
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
'event_sharif',
{
'type': 'send_message_to_frontend',
'message': "event_trigered_from_views"
}
)
# here 'event_sharif' is your room_group_name as i defined before in consumer
# 'type' is like a command, for which method you wants to trigger in your consumer
for more you may take a look Send message using Django Channels from outside Consumer class
Generally, you can call a method in the consumer from an external code in the following way:
from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
await self.channel_layer.send(
'<channel_name>',
{
'type': '<method_name>',
}
)
But as you can see, this requires that you specify the channel name which you can only get after the client has connected. In other words, you should not try to call connect but some other method in the consumer. Also, your client should first connect to the websocket before you eventually access it. I don't understand your use case completey but I hope this gives you an idea
How do you delete messages using imap4.IMAP4Client? I cannot get the "deleted" tag correctly applied for using the "expunge" method.
I keep getting the following error:
Failure: twisted.mail.imap4.IMAP4Exception: Invalid system flag \
Sample code would be appreciated. This is what I have so far:
from twisted.internet import protocol, reactor
from twisted.mail import imap4
#Variables for connection
username = 'user#host.com'
password = 'mypassword'
host = 'imap.host.com'
port = 143
class IMAP4LocalClient(imap4.IMAP4Client):
def connectionMade(self):
self.login(username,password).addCallbacks(self._getMessages, self._ebLogin)
#reports any connection errors
def connectionLost(self,reason):
reactor.stop()
#drops the connection
def _ebLogin(self,result):
print result
self.transport.loseConnection()
def _programUtility(self,result):
print result
return self.logout()
def _cbExpungeMessage(self,result):
return self.expunge().addCallback(self._programUtility)
def _cbDeleteMessage(self,result):
return self.setFlags("1:5",flags=r"\\Deleted",uid=False).addCallback(self._cbExpungeMessage)
#gets the mailbox list
def _getMessages(self,result):
return self.list("","*").addCallback(self._cbPickMailbox)
#selects the inbox desired
def _cbPickMailbox(self,result):
mbox='INBOX.Trash'
return self.select(mbox).addCallback(self._cbExamineMbox)
def _cbExamineMbox(self,result):
return self.fetchMessage("1:*",uid=False).addCallback(self._cbDeleteMessage)
class IMAP4ClientFactory(protocol.ClientFactory):
def buildProtocol(self,addr):
return IMAP4LocalClient()
def clientConnectionFailed(self,connector,reason):
print reason
reactor.stop()
reactor.connectTCP(host,port,IMAP4ClientFactory())
reactor.run()
Changed to:
def _cbDeleteMessage(self,result):
return self.setFlags("1:5",flags=['\\Deleted'],uid=False).addCallback(self._cbExpungeMessage)
thanks to Jean-Paul Calderone and it worked, setFlags requires a list, not just a string.
I think there are two problems here.
First, you're passing a string as the flags parameter to setFlags. Notice the documentation for that parameter: The flags to set (type: Any iterable of str). Try a list containing one string, instead.
Second, \\Deleted is probably not a flag the server you're interacting with supports. The standard deleted flag in IMAP4 is \Deleted.