Slack bot running python functions - python

I am creating a Slack Bot, I have successfully installed it, although I am not 100% sure what does ngrok do to run it when I have node server running locally. I have followed this guide.
I have a python script that:
Connects to a database
Downloads the entire table and creates a pandas dataframe
In the script, I have declared many variables which takes specific information from the dataframe.
For example:
monday_sales = sum((df['sale_event_time']>=week) & (df['sale_event_time']<=today_real) & ((df['sale_event_time'].apply(lambda x:x.isoweekday()))==1))
Which simply returns how many sales I had on Monday from the dataframe.
My goal is to connect slack bot to my python script, basically being able to run /monday_sales in slack which would print the number that monday_sales variable holds.
I haven't used much of node or js, so linking everything together I find a bit difficult.
First I run ngrok like so:
./ngrok http 4390
Then I run node server locally(?)
var http = require('http');
const PORT=4390;
function handleRequest(request, response){
response.end('My bot is ALIIIIIIVEEEEE');
}
var server = http.createServer(handleRequest);
server.listen(PORT, function(){
console.log("Server listening on: http://localhost:%s", PORT);
});
And when I run /ngrok in slack it prints out 'My bot is ALIIIIIIVEEEEE, although only visible to me.
So the question could be split in to few:
Why do I need ngrok and node.js server running locally?
How can I trigger python functions / variables from slack bot.
Is there a better way of having slack bot only ran by python without node, ngrok?
Thank you very much for your suggestions.

I think your best bet is to ditch this tutorial and Node, as it seems you're only using it as a ngrok wrapper. Instead, since the rest of your bot is in Python, just use pyngrok (full disclosure, I am the developer), which is a Python wrapper for ngrok. It gives you programmatic access to the tunnels and everything else.
If this solves your use case, you can check out the docs here.

Related

A http proxy same as Fiddler AutoResponder

Hey I'm trying to create something like fiddler autoresponder.
I want replace specific url content to other example:
I researched everything but can't found I tried create proxy server, nodejs script, python script. Nothing.
https://randomdomain.com content replace with https://cliqqi.ml
ps I'm doing this because I want intercept electron app getting main game file from site and then just intercept they game file site to my site.
If you're looking for a way to do this programmatically in Node.js, I've written a library you can use to do exactly that, called Mockttp.
You can use Mockttp to create a HTTPS-intercepting & rewriting proxy, which will allow you to send mock responses directly, redirect traffic from one address to another, rewrite anything including the headers & body of existing traffic, or just log everything that's sent & received. There's a full guide here: https://httptoolkit.tech/blog/javascript-mitm-proxy-mockttp/

How do I save/load Bot Framework session information to/from the local disk?

I have a question about a Microsoft Teams Python bot. If the bot has been added to some personal chats and group chats and I restart the bot, sometimes the bot needs to be added to the chats again. So I want to make bot sessions.
Is it possible to make a bot session in Microsoft Teams? I want to store session information on the local disk, and then have the bot load that data when it starts.
My bot code is very similar to this sample.
Thank you for your help.
Updated:
Like I said my bot code is very similar to this sample, but a bit different. Because of this I created an example for this question. First of all I create a bot in Azure and set up it.
After this, in my bot's config.py file I set up the port and Microsoft app ID and password (generated by clicking the "Manage" button).
import os
""" Bot Configuration """
class DefaultConfig:
""" Bot Configuration """
PORT = 3978
APP_ID = os.environ.get("MicrosoftAppId", "sadsadsadasd")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "asdasdasdasdasd")
After this I execute the command ngrok http 3978 and put the generated endpoint in the Azure bot configuration. To register the bot as an application, I use App Studio in Teams. After I do that, I just to need run the bot in CMD so I run a command like python run.py
After I run the bot, I can add it in the channel and run commands and functions that I created in the code.
This is just an example of how I set up the bot. The main bot is on a Linux server.
Here is why I want to make the bot keep session information and load it after the server or bot was restarted. Sometimes after I restart the bot or server it is no longer in the chat or team. In the future I want make some kind of commands and execute them using a cron job or something like that.
If the bot disappears from a chat then I can't use bot commands in that chat. For example, I add two bots in a chat. After I restart one of them I can't get any response from it like in the picture below.
And with # I can't see the bot.
I have an idea. After I add the bot in the chat I get this in the console:
Adding new conversation to the list: {'additional_properties': {}, 'activity_id': '123215513', 'user': <botbuilder.schema._models_py3.ChannelAccount object at 0x0000027C0ED60>, 'bot': <botbuilder.schema._models_py3.ChannelAccount object at 0x0000027Cs2FD0>, 'conversation': <botbuilder.schema._models_py3.ConversationAccount object at 0x0000027C0400>, 'channel_id': 'msteams', 'locale': 'en-US', 'service_url': 'https://smba.trafficmanager.net/emea/'}
Formatted:
{
"additional_properties": {},
"activity_id": "123215513",
"user": <botbuilder.schema._models_py3.ChannelAccount object at 0x0000027C0ED60>,
"bot": <botbuilder.schema._models_py3.ChannelAccount object at 0x0000027Cs2FD0>,
"conversation": <botbuilder.schema._models_py3.ConversationAccount object at 0x0000027C0400>,
"channel_id": "msteams",
"locale": "en-US",
"service_url": "https://smba.trafficmanager.net/emea/"
}
So if I store this information and then load it when I start the bot, maybe it will work?
There is an option inside a bot to save a transcript of the conversation, but that's kind of unrelated. Basically, the important thing to know is that you don't need to store anything your side - from the user perspective, the entire conversation history is preserved in the Teams client, and from the perspective of your bot, storing the entire conversation history doesn't really gain you anything - user state is more relevant than conversation history. This would be storing an object in a persistence you choose (e.g. database, nosql store, azure blobs, whatever), but it would be state you choose to store for the user (basically whatever properties make sense to store for your app, in a kind of "User" collection). This is definitely a possible and often necessary concept, and this link will be useful for you: https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-concept-state?view=azure-bot-service-4.0
It's important to know though that this is a separate idea from sending a message on a defined schedule (e.g. Cron) to a user. For this to work, you need to read up on a concept called "Proactive Messaging". I have a sample on the Teams PnP gallery specifically dealing with it (code only in Node and Dotnet - no python I'm afraid, but hopefully it's useful for you). See here for that. Note that at the bottom of this link is a list of further reading on the topic as well.
Where the two above ideas come together is that you need to store certain state about the user to be able to send the proactive message later. In the sample I link to, I show how to get the settings you need to send the proactive message, but I've not included the concept of saving them to a data store - that's up to your own implementation inside your bot (e.g. SQL Azure, MongoDb, blob, whatever).
Also important to note (and I think part of the confusion and in fact part of why I wrote the sample) - your proactive code does not need to live in the same set of code as your bot! Your bot could be a web service running somewhere, and your proactive code an Azure Function/Lambda/similar.
Like Hilton said, it's a bad idea to try and save bot state to the local disk. Also, there's no need for that. Both Hilton and I have linked to documentation that should help you understand how bot state is meant to be saved.
I cannot reproduce the problem you're encountering where the bot gets removed from Teams chats. The problem sounds impossible anyway, based on how Teams works and how bots work. Teams should have no way of knowing whether your bot is started or stopped. It's possible that your server is set up to manually uninstall the bot from Teams conversations based on when the bot starts and stops, but that would still be very strange. I'm willing to continue troubleshooting this with you, but I thought I'd post an answer now in case you'd like to award your bounty to someone before it expires.

Twilio Taskrouter: How do I configure my JS client (Worker) to receive voice calls after a reservation has been accepted?

I am referring to the example code here.
I am able to get the client running, task is assigned and reservation created and accepted as well. But then the call is not connected and the client keeps listening the default waiting tune.
I have tried reservation.dequeue() and reservation.call() but to no avail.
I am using Python-flask and twilio library 6.3.0.
Any help would be great.
Twilio developer evangelist here.
From the comments, you are looking to answer this call within the browser.
You do need to include the Twilio Client JS for this, alongside the TaskRouter JS. Check out the quick start on using Twilio Client to get familiar with it.
In order to connect up TaskRouter and Twilio Client you don't need to combine the tokens. What you do need to do is set your worker's contact_uri attribute to "client:" + YOUR_CLIENTS_NAME (for example { "contact_uri": "client:Bob" }).
Then when your worker dequeues the assignment, Twilio will look at the worker's contact_uri address and route the call there.
Let me know if this helps at all.

How to accept a JSON POST?

First time here, it says to be specific... So here goes.
I'm doing a small project to connect Salesforce to my Raspberry Pi. The goal is to make a light (Think a beacon, siren-like light) flash when a high priority case comes in from a client in Salesforce. At the moment, clients usually send an email to a certain address, and this creates a case. It goes to the 'Unassigned Queue' and emails the team that this case is there waiting to be assigned.
Salesforce uses REST, so I need to be able to get the Pi to accept JSON so it can easily understand what Salesforce wants it to do.
Currently, I guess I have won half of the battle. I have a web server (Lighttpd) running on the Pi, which hosts an index page and a Python script. I am also using a Python wrapper, which allows me to easily run a command from a Telldus program I have installed. This program controls a USB RF Transmitter that I have connected, it is paired to a RF Socket, which is connected to the mains power supply with a light connected to it.
So the Python script is called power.py, and can be controlled with URL variables, so if I go to power.py?device=1&power=on&time=10&password=hunter2 that turns on device 1 for 10 seconds. I also created a POST form on the index page, which just POSTS to the python script, and runs it in the same way as using the URL variables. That all works great.
So all I need to do, is connect it to Salesforce. I would like to use REST and JSON, so that if I ever move away from Salesforce to another CRM program, it will easily be able to adapt and receive instructions from new places.
I have posted the Python script I am using here:
https://github.com/7ewis/RemotePiControl/blob/master/power.py
The Pi isn't currently allowed out of the local network, so I will need to somehow develop a way to send JSON commands, and the recieve and convert them to work using the correct variables etc. I'm not a programmer, I've just exposure to languages from hacking things and exploring. Hence why I need some guidance with this.
I have never used REST or JSON before, so what would I need to do to achieve this?
Seems like adding Flask http://flask.pocoo.org to your Raspberry Pi Webserver would be a good move. It allows server-side python to be run in response to JQuery ajax (and regular) requests. Check out a couple of examples here:
http://flask.pocoo.org/docs/patterns/jquery/
and this stack overflow question: how can I use data posted from ajax in flask?
Flask is pretty straightforward to get up and running, and is happy working with a number of servers, including Lighttpd. Writing RESTful flask is also a perfectly reasonable proposition, see: http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask
Additionally, lots of people have used flask on the raspberry pi already-- so that could help get you up and running smoothly: http://mattrichardson.com/Raspberry-Pi-Flask/
Good luck!
Firstly don't use a Python script that prints out result directly to CGI. You will be forever debugging it.
Use a light weight framework like Flask. You can do something as simple as
from flask import Flask
application = Flask(__name__)
#application.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# use Flask's build in json decoder
the_data = request.get_json()
# then do something with the data
return "This was a POST request, how interesting..."
else:
# request was GET rather than POST, so do something with else
return "Hello World!"
See how to configure Flask to run with Lighttpd here http://flask.pocoo.org/docs/deploying/fastcgi/
If you want to test this you can either write another Python script to send JSON data to your server (I recommend looking at the Python Requests library for this http://www.python-requests.org/en/latest/), or you can do this manually using a HTTP request builder, such as HTTPRequester for Firefox (https://addons.mozilla.org/en-US/firefox/addon/httprequester/)

How to call a web-service using JavaEE?

I've been using rpclib to auto-generate a WSDL and implement it in Python.
Then I wanted to call a web-service* that has this WSDL using JavaEE, so I simply used the Web Service from WSDL option in the creation wizard in Eclipse (Indigo 3.7.1 with OEPE), but then the Ant build failed with the exception (in short):
weblogic.wsee.tools.WsBuildException Error running JAX-WS wsdlc
Caused by java.lang.NoSuchMethodException: javax.xml.bind.annotation.XmlElementRef.required()
What should I do? How can I call the web-service using JavaEE?
* The web service is configured with: Apache HTTP Server 2.2.2 + mod_wsgi 3.3 + Python 2.6.5 + rpclib 2.6.1.
Ok, stumbled upon your post the second time, so I'll elaborate my comment given before :).
First I recapitulate your set-up:
You have a working webservice and an URL pointing to the corresponding WSDL
You'll try to invoke the WS methods from a different Java EE project on a different machine
General options for invoking a WS:
Use Dependency Injection to inject the WS reference
Create your own WS stubs
The first option won't work in your set-up because DI will only work in an container-managed-environment (see my comment). That means that the WS class and the executing class have to be in the same container (e.g. the same server).
So what is left is to generate your WS stubs manually. Therefore you can use the wsimport tool mentioned in your own answer. There are several different ways to use this tool. Lets have a look in the CLI use:
navigate in your projekt folder of the WS client used by your IDE : %IDE_WORKSPACE%/your project/src
crate a new folder, e.g. stub
open a command window in this directory
execute the follwing command : wsimport -keep <http://yourwsdl?wsdl>
After a refresh you should see several created files
Back in your IDE:
Now you're able to use your generated stub-files to connect to the WS by getting a port from the generated service-file
public class WsClient {
public static void main(String[] args) {
//Create Service
'GeneratedFile'Service service = new 'GeneratedFile'Service();
//create proxy
'GeneratedFile' proxy = service.get'GeneratedFile'Port();
//invoke
System.out.println(proxy.yourMethod(yourParam));
}
}
Last hints:
For portabilty purpose check the generated files. In their annotations sometimes the WSDL file is linked to a local copy. Just change this back to your WSDL-URL.
AFAIK there is an option in the wsimport tool to set this directly in the import routine.
There is a plugin for Eclipse called soapUI which allows you to use the wsimport tool in a GUI out of Eclipse. Once set up it should accelerate your work.
I've also found a quick start guide in developing WS clients with eclipse.
Hope this helped, have Fun!
EDIT: Just to clarify:
After you used the wsimport tool you should have a directory containing files like shown in the image. To make this example clear you'll need to get a Service from the RequestFileService (this is my WS operation) like RequestFileService service = new RequestFileService(); and after this you'll need a Port on this service like RequestFile proxy = service.getRequestFilePort();.
After this you can invoke your method calls by using the port proxy.yourMethod(yourParam);

Categories

Resources