Send a Facebook Message with XMPP using Access Tokens in Python - python

This is a very specific question, but I cannot find any documentation on how I can do it. The Facebook Documentation is pretty vague with some horrible and useless PHP examples (really, it's code like the Facebook PHP Sample Code that make people think PHP sucks) but I cannot find anything around for Python.
I can't even work out how to apply the same principles from the PHP sample code into a Python world. The xmpppy and SleekXMPP docs are a bit bare (or broken) and Google only shows examples of people using passwords.
I have the access tokens coming from the database, I have no interest in spawning a browser to find stuff, or doing anything else to find a token. I have them, consider it a hardcoded string. I want to pass that string to XMPP and send a message, that is the whole scope of things.
Any suggestions?

The below code worked, but only after some modifications mentioned in this thread

I answered this with a link to a blog I wrote because it described the solution perfectly, but apparently that annoyed some moderators.
While that's clearly ridiculous, here is the answer reposted.
import sleekxmpp
import logging
logging.basicConfig(level=logging.DEBUG)
class SendMsgBot(sleekxmpp.ClientXMPP):
def init(self, jid, recipient, message):
sleekxmpp.ClientXMPP.__init__(self, jid, 'ignore')
# The message we wish to send, and the JID that
# will receive it.
self.recipient = recipient
self.msg = message
# The session_start event will be triggered when
# the bot establishes its connection with the server
# and the XML streams are ready for use. We want to
# listen for this event so that we we can initialize
# our roster.
self.add_event_handler("session_start", self.start, threaded=True)
def start(self, event):
self.send_presence()
self.get_roster()
self.send_message(mto=self.recipient, mbody=self.msg, mtype='chat')
# Using wait=True ensures that the send queue will be
#emptied before ending the session.
self.disconnect(wait=True)
I shoved that in a file called fbxmpp.py, then in another file (your worker, your command line app, your Flask controller, whatever) you'll need something like the following:
from fbxmpp import SendMsgBot
# The "From" Facebook ID
jid = '511501255#chat.facebook.com'
# The "Recipient" Facebook ID, with a hyphen for some reason
to = '-1000023894758#chat.facebook.com'
# Whatever you're sending
msg = 'Hey Other Phil, how is it going?'
xmpp = SendMsgBot(jid, to, unicode(msg))
xmpp.credentials['api_key'] = '123456'
xmpp.credentials['access_token'] = 'your-access-token'
if xmpp.connect(('chat.facebook.com', 5222)):
xmpp.process(block=True)
print("Done")
else:
print("Unable to connect.")

Related

Flask: Some clients don't like responses

I have a Flask app that generates video stream links. It connects to a server using login credentials and grabs a one time use link (that expires when a new link is generated using the same credentials). Using a list of credentials I am able to stream to as many devices as I like, so long as I have enough accounts.
The issue I am having is that one of the clients doesn't like the way the stream is returned.
#app.route("/play", methods=["GET"])
def play():
def streamData():
try:
useAccount(<credentials>)
with requests.get(link, stream=True) as r:
for chunk in r.iter_content(chunk_size=1024):
yield chunk
except:
pass
finally:
freeAccount(<credentials>)
...
# return redirect(link)
return Response(streamData())
If I return a redirect then there are no playback issues at all. The problem with a redirect is I don't have a way of marking the credentials as in use, then freeing them after.
The problem client is TVHeadend. I am able to get it to work by enabling the additional avlib inside of TVHeadend... But I shouldn't have to do that. I don't have to when I return a redirect.
What could be the cause of this?
Is it possible to make my app respond in the same way as the links server does?
My guess is that TVHeadend is very strict on if something complies to whatever standards... and I am guessing my app doesn't?

SlackClient Python RTM not capturing messages

I want to write a simple slack bot, which responds a given string to # mentions, however I am not able to make the official documentation code to work.
I gave all OAuth permission to the bot and have the following code:
from slack import RTMClient
#RTMClient.run_on(event="message")
def gravity_bot(**payload):
data = payload['data']
print(data.get('text'))
try:
rtm_client = RTMClient(
token="my_token_auth_code",
connect_method='rtm.start'
)
print("Bot is up and running!")
rtm_client.start()
except Exception as err:
print(err)
I think the connection is established, as the "Bot is up and running" message appears, however on the slack channel to bot seems to be offline, also I am not able to get any response in the terminal, not for direct messages, not for channel messages even after inviting the bot to given channels.
Sorry couldn't let this one go.. I figured it out and here are the steps:
Create a "Classic" app in Slack (this is the only way to get the appropriate scopes), just click this link: https://api.slack.com/apps?new_classic_app=1
From the "Add features and functionality" tab click on "bots":
Click the "Add Legacy Bot User" button (this will add the "rtm.stream" scope that you need, but that you cannot add manually)
From the basic information page, install your app in a workspace
From the OAuth & Permissions page, copy the "Bot User OAuth Access Token" (the bottom one)
Run the following code (slightly modified version of the code in the docs)
from slack_sdk.rtm import RTMClient
# This event runs when the connection is established and shows some connection info
#RTMClient.run_on(event="open")
def show_start(**payload):
print(payload)
#RTMClient.run_on(event="message")
def say_hello(**payload):
print(payload)
data = payload['data']
web_client = payload['web_client']
if 'Hello' in data['text']:
channel_id = data['channel']
thread_ts = data['ts']
user = data['user']
web_client.chat_postMessage(
channel=channel_id,
text=f"Hi <#{user}>!",
thread_ts=thread_ts
)
if __name__ == "__main__":
slack_token = "<YOUR TOKEN HERE>"
rtm_client = RTMClient(token=slack_token)
rtm_client.start()
Previous answer:
Hmm, this is tricky one... According to the docs this only works for "classic" Slack apps, so that might be the first pointer. It explicitly says that you should not upgrade your app. Furthermore, you'll need to set the right permissions (god knows which ones) by selecting the "bot" scope.
Honestly, I haven't been able to get this running. Looks like Slack is getting rid of this connection method, so you might have more luck looking into the "Events API". I know it's not the ideal solution because its not as real-time, but it looks better documented and it will stay around for a while. Another approach could be polling. Its not sexy but it works...
My guess is that your problem is that there is not a valid connection, but there is no proper error handling in the Slack library. The message is printed before you actually connect, so that doesn't indicate anything.

as you write in a queue and waiting for your response on another using service bus azure

I'm using the sdk of the service bus to send to a queue and listen for the answer in another, but I can not find valid examples of how to make that flow. My biggest difficulty is being able to set reply_to and reply_to_group_id, as I did in the old versions directly in the MessageProperties, now in the class Message I am in doubt with what to inform in the index 'message' to achieve this objective
The Message class has a property called properties which is an instance of uamqp.message.MessageProperties which has the reply_to (and reply_to_group_id) property that you are looking for.
from azure.servicebus import Message
message = Message(
body="Hello World!"
)
message.properties.reply_to="replyTo"
message.properties.reply_to_group_id="replyGroupId"
You can read more about AMQP Request-Response Operations with Service Bus in the docs.
to add to #pramodValavala's answer, here's how you do it with the v7.0 https://pypi.org/project/azure-servicebus/7.0.0/
from azure.servicebus import ServiceBusMessage
message = ServiceBusMessage("hello world")
# set using application_properties
message.application_properties = {'reply_to': 'abc'}

Private chat with flask-socketio

I'm developing a webapp for a personal assistant. While a user is connected to the site, I want them to be able to subscribe to their personal notifications while they're online. I went about doing this with socketio and flask socketio and I thought that I could just use multithreading, like so:
def update_loop():
while my_update_condition:
if my_update_exists:
socketio.emit("update", my_update)
#socketio.on("get_updates")
def get_updates(data):
'''Websocket thread for getting updates'''
socketio.emit("debug", {"value": "Starting update loop"})
update_thread = threading.Thread(target=update_loop)
update_thread.start()
But my code using this strategy gives any update to all users online. Using flask socketio, how can I securely implement a private chat? The data in the updates isn't ultra-sensitive, but, since it's notifications that the user sets, it's usually personal. Thanks.
Note: In my research on this I came upon something using a socketid to send a message just to a specific sender, but I couldn't find an example implementation of this using flask-socketio.
The socketio.emit() function broadcasts to all users by default. To address a message to a single user, you have to set the room to the desired user's room, which is named after the session id of the user. Here is an example:
def update_loop(sid):
while my_update_condition:
if my_update_exists:
socketio.emit("update", my_update, room=sid)
#socketio.on("get_updates")
def get_updates(data):
'''Websocket thread for getting updates'''
socketio.emit("debug", {"value": "Starting update loop"})
update_thread = threading.Thread(target=update_loop, args=(request.sid,))
update_thread.start()

Creating Slack Bot to Answer Request

I would like to create a Slack bot to answer some simple question or perform some task on the server. Here is what I have tried
token = "i-put-my-bot-token-here" # found at https://api.slack.com/#auth)
sc = SlackClient(token)
sc.api_call("chat.postMessage", channel="magic", text="Hello World!")
It was posted as the Slackbot and not the bot account that I created?
Also if I were to listen the message, according to the python library it says
if sc.rtm_connect():
while True:
print sc.rtm_read()
time.sleep(1)
else:
print "Connection Failed, invalid token?"
Or should I use incoming webhook instead?
As you can see here this call accepts an argument 'as_user' which can be true. If you set it as true, messages will be posted as the bot you created.
I'm in the middle of creating a bot right now as well. I found that if you specified as_user='true', it would post as you, the authed user. If you want it to be your bot, pass in the name of our bot and other options like emoji's like so:
sc.api_call(
'chat.postMessage',
username='new_slack_bot',
icon_emoji=':ghost:',
as_user='false',
channel='magic',
text='Hello World!'
)
Check emoji cheat sheet for more.
Then, if you want to listen to events, like questions or commands, try intercepting the messages that are sent in. Example found on this post:
while True:
new_evts = sc.rtm_read()
for evt in new_evts:
print(evt)
if "type" in evt:
if evt["type"] == "message" and "text" in evt:
message=evt["text"]
# write operations below to receive commands and respond as you like

Categories