python flask api to asp.net core api - python

and greetings.
I am currently trying to integrate a USSD service. I however am stuck with a platform-specific tutorial. the service is written in python flask, while I a developing using asp.net core API. In the tutorial there are certain requirements, I do not understand.
The overview of the connectivity is: here
Below are the explanations of the tutorial.
We have initialized a brand new Flask app. We have made sure that it’s
the main app running. Just below that, we have defined a route that
allows us to actually access our application. We have defined the
methods that we need which is the GET and POST HTTP methods. We have
defined a method/function that will be executed when we are accessing
the route. In this case, we’ve called it ussd_callback. Within the
method we receive some special parameters that we are getting from the
Africa’s Talking API:
session_id gets a unique session ID service_code gets your USSD code
phone_number gets the phone number thats currently accessing the USSD
text carries the user response as they use the USSD application
with the code
from flask import Flask, request
app = Flask(__name__)
response = ""
#app.route('/', methods=['POST', 'GET'])
def ussd_callback():
global response
session_id = request.values.get("sessionId", None)
service_code = request.values.get("serviceCode", None)
phone_number = request.values.get("phoneNumber", None)
text = request.values.get("text", "default")
under the ussd_callback function, one can return a raw string, like bellow:
if text == '':
response = "CON What would you want to check \n"
response += "1. My Account \n"
response += "2. My phone number"
and continue with
elif text == '1':
response = "CON Choose account information you want to view \n"
response += "1. Account number \n"
response += "2. Account balance"
After which, one can return response.
I have created my own solution in ASP.net core 5 API, with the following.
[HttpPost]
[Route("api/[controller]/AddNew")]
public ActionResult<string> AddNew(string venueId)
{
var answer = "";
int number = 0;
if (venueId is null)
{
answer = answer + "CON Please select venue:\n 1.Abor \n 2.Owo \n 3.Ugwueme \n 4.Oweli \n 0.Page 2 ";
return answer;
}
bool isReal = Int32.TryParse(venueId, out number);
if (isReal)
{
if (number == 0)
{
answer = answer = "CON \n 5.Umuogbo Agu \n 6.Awha Imezi \n 7.Ovoko \n 8.Opatu \n 9.Akiyi Umulokpa";
return answer;
}
else if (number > 9)
{
answer = answer + "CON Invalid input, Please select venue:\n 1.Abor \n 2.Owo \n 3.Ugwueme \n 4.Oweli \n 0.Page 2 ";
return answer;
}
}
else
{
answer = answer + "CON Invalid input, Please select venue:\n 1.Abor \n 2.Owo \n 3.Ugwueme \n 4.Oweli \n 0.Page 2 ";
return answer;
}
var data_venue = _db.Venues.Where(m => m.Id == number).FirstOrDefault();
if (data_venue is null)
{
return NotFound();
}
ApiReport data = new ApiReport()
{
DateReported = DateTime.Now,
VenueId = number,
};
var data_report = ReportMapping.ApiReport_To_DataReport(data);
data_report.DateReported = DateTime.Now;
data_report.PhoneNumber = "000";
_db.Reports.Add(data_report);
_db.SaveChanges();
return $"END \n Thank you for informing us about the new case in {data_venue.Name}. \n ";
}
The USSD initially runs fine and shows the base menu, but it will not work if it tries to respond. it is like I am still sending null values into the code. I would love to debug and see the input data myself but this service works with hosted applications.
I feel that I might have the input parameters wrong, or that I am not using proper headers.
Please fam, where have I gone wrong?

Related

Django + React axios POST cant access Json properties

I created two abjects that need to be treated separated in the backend, and sent it to backend with:
const order = {
order_id: 1,
customer: {
name: "Jonas Illver"
age: 18
}
}
const car = {
model: 'XHL'
brand: 'Toyota'
}
const postData = {
order: order,
car: car
}
const res = await axios.post("orders/shipping/create", JSON.stringify(postData));
console.log(res);
And here I return the response: views.py
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def shipping_create_order(request):
if request.method == 'POST':
return JsonResponse(request.POST)
Here's what the console.log prints:
res.data // {"order:"{"order_id": 1, "customer": {"name": "Jonas Illver", "age": 18}}, "car": **car object content**}
The problem is that if I try to access those data in my django view, I always got a 500 error
I tried accessing it via:
order = request.POST['order']
# and also
data = json.loads(request.POST)
order = data['order']
# also
order = request.POST.get('order')
None os the above approaches worked, the only one that doesn't occurs an 500 error is the last one, using the POST.get, but as soon as I add the if not order: return HttpResponse("No order") line, it always return "No order"
How can I access specific info from the request.POST? Am I doing something wrong with the axios request?
Try using request.data to get the data passed in the body. Have a look at the rest-framework docs.
Or another way to get the data is using json.loads(request.body). But using request.data is a bit shorter as it does the json.loads job for you.

Twilio: how to get the subaccount of a phone number?

Is it possible that using the phone number I can get the sub account number that this phone number belongs to in Twilio?
I am using the following in python:
import os
from twilio.rest import Client
os.environ['account_sid'] = 'Master_account_SID'
os.environ['auth_token'] = 'Master_account_token'
account_sid = os.environ['account_sid']
auth_token = os.environ['auth_token']
client = Client(account_sid, auth_token)
incoming_phone_num = client.incoming_phone_numbers.list(phone_number='+1XXXXXXXXXX', limit=10)
print(incoming_phone_num.account_sid)
The above returns error "object has no attribute 'account_sid'"
Thanks.
Here is JavaScript but you will get the general idea from the explanation below.
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken);
const phoneNumberToSearch = '+1484xxxxxx';
let subAccount;
client.api.accounts.list({status: 'active', limit: 1000})
.then(accounts => {
accounts.forEach(a => {
subAccount = require('twilio')(accountSid, authToken, { accountSid: a.sid });
subAccount.incomingPhoneNumbers
.list({phoneNumber: phoneNumberToSearch, limit: 1})
.then(incomingPhoneNumbers => {
incomingPhoneNumbers.forEach(i => console.log(i.accountSid))
});
})
});
API being used:
REST API: Accounts
To list all the subaccounts
Code Example: List All Active Accounts
IncomingPhoneNumber resource
To iterate through each subaccount looking for the number
Code Example: Filter IncomingPhoneNumbers with exact match
Making a phone call with a Subaccount
The structure to use the main project credentials for the sub-account
Code Example: Make a call from a subaccount (to see how to call the client)
Following the same idea as Alan's answer but since you were writing python:
from twilio.rest import Client
client = Client()
phoneNumber = '+1xxxxxxxxxx'
subaccounts = client.api.accounts.list(status='active', limit=1000)
for subaccount in subaccounts:
subclient = Client(account_sid=subaccount.sid)
numbers = subclient.incoming_phone_numbers.list(phone_number=phoneNumber, limit=1)
if len(numbers) > 0:
print(subaccount.sid, subaccount.friendly_name)
The key takeaway is that the phone numbers are only available in each subaccount so you need to loop through them to find the number you want.
Note that Twilio's python API will take credentials from environment variables itself so you didn't need to do that.

How to send JSON payload to create buttons with pymessenger Facebook chatbot

I am creating a Facebook messenger chatbot with pymessenger, flask and wit.at. I want to add buttons as options in my chatbot conversation.
For example
"πŸŽ€ Generic Offer 1"+"\n"+"πŸŽ€ Generic Offer 2"+"\n"+"πŸŽ€ Generic Offer 3"
is what I want to show up as a button to user instead of just text. So the user can select one offer. Facebook has the option to add buttons https://developers.facebook.com/docs/messenger-platform/send-messages/template/button/ via JSON.
I want to do the similar thing. But I don't know how to do it. I can do simple text thing but now this, because I don't know JSON. As of now, my chatbot is replying via bot.send_text_message(sender_id, response).
def webhook():
data = request.get_json()
log(data)
if data['object'] == 'page':
for entry in data['entry']:
for messaging_event in entry['messaging']:
sender_id = messaging_event['sender']['id']
recipient_id = messaging_event['recipient']['id']
if messaging_event.get('message'):
if 'text' in messaging_event['message']:
messaging_text = messaging_event['message']['text']
else:
messaging_text = 'no text'
response = None
entity, value = wit_response(messaging_text)
if entity == 'newstype':
response = "OK. I will send you {} news".format(str(value))
elif entity == 'cust_greet':
response = get_message()
elif entity == 'cust_greet2':
response = get_message2()
elif entity == 'cust_offer':
#response = offer_response
response = "πŸŽ€ Generic Offer 1"+"\n"+"πŸŽ€ Generic Offer 2"+"\n"+"πŸŽ€ Generic Offer 3"+"\n"+" 🏷️ for more offer enter your cust id"
#val_off = test.val_off
bot.send_text_message(sender_id, response)
I think instead of bot.send_text_message, the correct way to send the JSON payload is via bot.send_raw. So using the example from your link you can test if it's working with something similar to:
payload = """{
"recipient":{
"id":"<PSID>"
},
"message":{
"attachment":{
"type":"template",
"payload":{
"template_type":"button",
"text":"What do you want to do next?",
"buttons":[
{
"type":"web_url",
"url":"https://www.example1.com",
"title":"Visit Example 1"
},
{
"type":"web_url",
"url":"https://www.example2.com",
"title":"Visit Example 2"
}
]
}
}
}
}"""
bot.send_raw(payload)
Don't forget to replace <PSID>.

Is There Any Way To Check if a Twitch Stream Is Live Using Python?

I'm just wondering if there is any way to write a python script to check to see if a twitch.tv stream is live?
I'm not sure why my app engine tag was removed, but this would be using app engine.
Since all answers are actually outdated as of 2020-05-02, i'll give it a shot. You now are required to register a developer application (I believe), and now you must use an endpoint that requires a user-id instead of a username (as they can change).
See https://dev.twitch.tv/docs/v5/reference/users
and https://dev.twitch.tv/docs/v5/reference/streams
First you'll need to Register an application
From that you'll need to get your Client-ID.
The one in this example is not a real
TWITCH_STREAM_API_ENDPOINT_V5 = "https://api.twitch.tv/kraken/streams/{}"
API_HEADERS = {
'Client-ID' : 'tqanfnani3tygk9a9esl8conhnaz6wj',
'Accept' : 'application/vnd.twitchtv.v5+json',
}
reqSession = requests.Session()
def checkUser(userID): #returns true if online, false if not
url = TWITCH_STREAM_API_ENDPOINT_V5.format(userID)
try:
req = reqSession.get(url, headers=API_HEADERS)
jsondata = req.json()
if 'stream' in jsondata:
if jsondata['stream'] is not None: #stream is online
return True
else:
return False
except Exception as e:
print("Error checking user: ", e)
return False
I hated having to go through the process of making an api key and all those things just to check if a channel was live, so i tried to find a workaround:
As of june 2021 if you send a http get request to a url like https://www.twitch.tv/CHANNEL_NAME, in the response there will be a "isLiveBroadcast": true if the stream is live, and if the stream is not live, there will be nothing like that.
So i wrote this code as an example in nodejs:
const fetch = require('node-fetch');
const channelName = '39daph';
async function main(){
let a = await fetch(`https://www.twitch.tv/${channelName}`);
if( (await a.text()).includes('isLiveBroadcast') )
console.log(`${channelName} is live`);
else
console.log(`${channelName} is not live`);
}
main();
here is also an example in python:
import requests
channelName = '39daph'
contents = requests.get('https://www.twitch.tv/' +channelName).content.decode('utf-8')
if 'isLiveBroadcast' in contents:
print(channelName + ' is live')
else:
print(channelName + ' is not live')
It looks like Twitch provides an API (documentation here) that provides a way to get that info. A very simple example of getting the feed would be:
import urllib2
url = 'http://api.justin.tv/api/stream/list.json?channel=FollowGrubby'
contents = urllib2.urlopen(url)
print contents.read()
This will dump all of the info, which you can then parse with a JSON library (XML looks to be available too). Looks like the value returns empty if the stream isn't live (haven't tested this much at all, nor have I read anything :) ). Hope this helps!
RocketDonkey's fine answer seems to be outdated by now, so I'm posting an updated answer for people like me who stumble across this SO-question with google.
You can check the status of the user EXAMPLEUSER by parsing
https://api.twitch.tv/kraken/streams/EXAMPLEUSER
The entry "stream":null will tell you that the user if offline, if that user exists.
Here is a small Python script which you can use on the commandline that will print 0 for user online, 1 for user offline and 2 for user not found.
#!/usr/bin/env python3
# checks whether a twitch.tv userstream is live
import argparse
from urllib.request import urlopen
from urllib.error import URLError
import json
def parse_args():
""" parses commandline, returns args namespace object """
desc = ('Check online status of twitch.tv user.\n'
'Exit prints are 0: online, 1: offline, 2: not found, 3: error.')
parser = argparse.ArgumentParser(description = desc,
formatter_class = argparse.RawTextHelpFormatter)
parser.add_argument('USER', nargs = 1, help = 'twitch.tv username')
args = parser.parse_args()
return args
def check_user(user):
""" returns 0: online, 1: offline, 2: not found, 3: error """
url = 'https://api.twitch.tv/kraken/streams/' + user
try:
info = json.loads(urlopen(url, timeout = 15).read().decode('utf-8'))
if info['stream'] == None:
status = 1
else:
status = 0
except URLError as e:
if e.reason == 'Not Found' or e.reason == 'Unprocessable Entity':
status = 2
else:
status = 3
return status
# main
try:
user = parse_args().USER[0]
print(check_user(user))
except KeyboardInterrupt:
pass
Here is a more up to date answer using the latest version of the Twitch API (helix). (kraken is deprecated and you shouldn't use GQL since it's not documented for third party use).
It works but you should store the token and reuse the token rather than generate a new token every time you run the script.
import requests
client_id = ''
client_secret = ''
streamer_name = ''
body = {
'client_id': client_id,
'client_secret': client_secret,
"grant_type": 'client_credentials'
}
r = requests.post('https://id.twitch.tv/oauth2/token', body)
#data output
keys = r.json();
print(keys)
headers = {
'Client-ID': client_id,
'Authorization': 'Bearer ' + keys['access_token']
}
print(headers)
stream = requests.get('https://api.twitch.tv/helix/streams?user_login=' + streamer_name, headers=headers)
stream_data = stream.json();
print(stream_data);
if len(stream_data['data']) == 1:
print(streamer_name + ' is live: ' + stream_data['data'][0]['title'] + ' playing ' + stream_data['data'][0]['game_name']);
else:
print(streamer_name + ' is not live');
πŸ“š Explanation
Now, the Twitch API v5 is deprecated. The helix API is in place, where an OAuth Authorization Bearer AND client-id is needed. This is pretty annoying, so I went on a search for a viable workaround, and found one.
🌎 GraphQL
When inspecting Twitch's network requests, while not being logged in, I found out the anonymous API relies on GraphQL. GraphQL is a query language for APIs.
query {
user(login: "USERNAME") {
stream {
id
}
}
}
In the graphql query above, we are querying a user by their login name. If they are streaming, the stream's id will be given. If not, None will be returned.
🐍 The Final Code
The finished python code, in a function, is below. The client-id is taken from Twitch's website. Twitch uses the client-id to fetch information for anonymous users. It will always work, without the need of getting your own client-id.
import requests
# ...
def checkIfUserIsStreaming(username):
url = "https://gql.twitch.tv/gql"
query = "query {\n user(login: \""+username+"\") {\n stream {\n id\n }\n }\n}"
return True if requests.request("POST", url, json={"query": query, "variables": {}}, headers={"client-id": "kimne78kx3ncx6brgo4mv6wki5h1ko"}).json()["data"]["user"]["stream"] else False
I've created a website where you can play with Twitch's GraphQL API. Refer to the GraphQL Docs for help on GraphQL syntax! There's also Twitch GraphQL API documentation on my playground.
Use the twitch api with your client_id as a parameter, then parse the json:
https://api.twitch.tv/kraken/streams/massansc?client_id=XXXXXXX
Twitch Client Id is explained here: https://dev.twitch.tv/docs#client-id,
you need to register a developer application: https://www.twitch.tv/kraken/oauth2/clients/new
Example:
import requests
import json
def is_live_stream(streamer_name, client_id):
twitch_api_stream_url = "https://api.twitch.tv/kraken/streams/" \
+ streamer_name + "?client_id=" + client_id
streamer_html = requests.get(twitch_api_stream_url)
streamer = json.loads(streamer_html.content)
return streamer["stream"] is not None
I'll try to shoot my shot, just in case someone still needs an answer to this, so here it goes
import requests
import time
from twitchAPI.twitch import Twitch
client_id = ""
client_secret = ""
twitch = Twitch(client_id, client_secret)
twitch.authenticate_app([])
TWITCH_STREAM_API_ENDPOINT_V5 = "https://api.twitch.tv/kraken/streams/{}"
API_HEADERS = {
'Client-ID' : client_id,
'Accept' : 'application/vnd.twitchtv.v5+json',
}
def checkUser(user): #returns true if online, false if not
userid = twitch.get_users(logins=[user])['data'][0]['id']
url = TWITCH_STREAM_API_ENDPOINT_V5.format(userid)
try:
req = requests.Session().get(url, headers=API_HEADERS)
jsondata = req.json()
if 'stream' in jsondata:
if jsondata['stream'] is not None:
return True
else:
return False
except Exception as e:
print("Error checking user: ", e)
return False
print(checkUser('michaelreeves'))
https://dev.twitch.tv/docs/api/reference#get-streams
import requests
# ================================================================
# your twitch client id
client_id = ''
# your twitch secret
client_secret = ''
# twitch username you want to check if it is streaming online
twitch_user = ''
# ================================================================
#getting auth token
url = 'https://id.twitch.tv/oauth2/token'
params = {
'client_id':client_id,
'client_secret':client_secret,
'grant_type':'client_credentials'}
req = requests.post(url=url,params=params)
token = req.json()['access_token']
print(f'{token=}')
# ================================================================
#getting user data (user id for example)
url = f'https://api.twitch.tv/helix/users?login={twitch_user}'
headers = {
'Authorization':f'Bearer {token}',
'Client-Id':f'{client_id}'}
req = requests.get(url=url,headers=headers)
userdata = req.json()
userid = userdata['data'][0]['id']
print(f'{userid=}')
# ================================================================
#getting stream info (by user id for example)
url = f'https://api.twitch.tv/helix/streams?user_id={userid}'
headers = {
'Authorization':f'Bearer {token}',
'Client-Id':f'{client_id}'}
req = requests.get(url=url,headers=headers)
streaminfo = req.json()
print(f'{streaminfo=}')
# ================================================================
This solution doesn't require registering an application
import requests
HEADERS = { 'client-id' : 'kimne78kx3ncx6brgo4mv6wki5h1ko' }
GQL_QUERY = """
query($login: String) {
user(login: $login) {
stream {
id
}
}
}
"""
def isLive(username):
QUERY = {
'query': GQL_QUERY,
'variables': {
'login': username
}
}
response = requests.post('https://gql.twitch.tv/gql',
json=QUERY, headers=HEADERS)
dict_response = response.json()
return True if dict_response['data']['user']['stream'] is not None else False
if __name__ == '__main__':
USERS = ['forsen', 'offineandy', 'dyrus']
for user in USERS:
IS_LIVE = isLive(user)
print(f'User {user} live: {IS_LIVE}')
Yes.
You can use Twitch API call https://api.twitch.tv/kraken/streams/YOUR_CHANNEL_NAME and parse result to check if it's live.
The below function returns a streamID if the channel is live, else returns -1.
import urllib2, json, sys
TwitchChannel = 'A_Channel_Name'
def IsTwitchLive(): # return the stream Id is streaming else returns -1
url = str('https://api.twitch.tv/kraken/streams/'+TwitchChannel)
streamID = -1
respose = urllib2.urlopen(url)
html = respose.read()
data = json.loads(html)
try:
streamID = data['stream']['_id']
except:
streamID = -1
return int(streamID)

Facebook "Login" (OAuth2) on AppEngine Python

I have the following Handlers
First the user calls this Handler and gets redirected to Facebook:
class LoginFacebookHandler(BasicHandler):
def get(self):
user = self.auth.get_user_by_session()
if not user:
h = hashlib.new('sha512')
h.update(str(datetime.now())+"abc")
nonce = h.hexdigest()
logging.info("hash "+str(nonce))
memcache.set(str(nonce), True, 8600)
#facebook_uri = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s&state=%s&scope=%s" % ("20773", "http://upstrackapp.appspot.com/f", str(nonce), "email")
data = {"client_id": 20773, "redirect_uri": "http://***.appspot.com/f", "state": str(nonce), "scope": "email"}
facebook_uri = "https://www.facebook.com/dialog/oauth?%s" % (urllib.urlencode(data))
self.redirect(facebook_uri)
After he authorized my app facebook redirects to the redirect URI (Handler):
class CreateUserFacebookHandler(BasicHandler):
def get(self):
state = self.request.get('state')
code = self.request.get('code')
logging.info("state "+state)
logging.info("code "+code)
if len(code) > 3 and len(state) > 3:
cached_state = memcache.get(str(state))
logging.info("cached_state "+str(cached_state))
if cached_state:
#memcache.delete(str(state))
data = { "client_id": 20773, "redirect_uri": "http://***.appspot.com/f", "client_secret": "7f587", "code": str(code)}
graph_url = "https://graph.facebook.com/oauth/access_token?%s" % (urllib.urlencode(data))
logging.info("grph url "+graph_url)
result = urlfetch.fetch(url=graph_url, method=urlfetch.GET)
if result.status_code == 200:
fb_response = urlparse.parse_qs(result.content)
access_token = fb_response["access_token"][0]
token_expires = fb_response["expires"][0]
logging.info("access token "+str(access_token))
logging.info("token expires "+str(token_expires))
if access_token:
api_data = { "access_token": str(access_token)}
api_url = "https://graph.facebook.com/me?%s" % (urllib.urlencode(api_data))
logging.info("api url "+api_url)
api_result = urlfetch.fetch(url=api_url, method=urlfetch.GET)
if api_result.status_code == 200:
api_content = json.loads(api_result.content)
user_id = str(api_content["id"])
email = str(api_content["email"])
logging.info("user id "+str(user_id))
logging.info("email "+str(email))
h = hashlib.new('sha512')
h.update(str(user_id)+"abc")
password = h.hexdigest()
expire_data = datetime.now() + timedelta(seconds=int(token_expires))
user = self.auth.store.user_model.create_user(email, password_raw=password, access_token=access_token, token_expires=expire_data, fb_id=user_id)
else:
self.response.write.out.write("error contacting the graph api")
else:
self.response.out.write("access token not long enough")
else:
self.response.out.write("error while contacting facebook server")
else:
self.response.out.write("error no cached state")
else:
self.response.out.write("error too short")
Mostly this works until the code tries to retrieve an access_token and I end up getting "error while contacting....".
The funny thing is, that I log all URLs, states etc. so I go into my Logs, copy&paste the URL that urlfetch tried to open (fb api->access_token) paste it into my browser and voilΓ  I get my access_token + expires.
The same thing happens sometimes when the code tries to fetch the user information from the graph (graph/me).
The key problem is not facebook.
It is the AppEngine deployment process.
I always tested changes in the code live, not local, since the OAuth wouldn't properly work.
So the deployment -> flush casche -> flush database process seemed to have a certain delay causing artifacts to remain, which confused the code.
So if you have to test such things like OAuth live, I'd recommend deploying the changes as a new version of the app and after deployment you shall delete all data that could act as artifacts in the new version.

Categories

Resources