Twilio: Create two outgoing calls and join the conference using Python - python

I am trying to create a conferencing app with max 2 speakers using Twilio using Python/Django. However, in the docs I found out that you can do this by having inbound calls. but, my business model doesnt work like that. Is there a way for this to work like:
My Twilio number calls number 1
My Twilio number calls number 2
Twilio brings two channels to a new conference
I've tried this solution:
Twilio how to make two outbound calls and join(conference) them using node js
but it didn't help me much..
Here's my code:
#csrf_exempt
def conference(request):
print("success")
response = VoiceResponse()
dial = Dial()
dial.conference('Rooxm 1234')
response.append(dial)
print(response)
return HttpResponse('')
def call(number):
client = Client(TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN)
call = client.calls.create(
url='https://<blahblah_removed_purposefully>.ngrok.io/conf/',
to='+' + str(number),
from_='<removed_my_twilio_num>'
)
print(call.sid)
def index(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CallForm(request.POST)
# check whether it's valid:
if form.is_valid():
#print(dir(form.data.values))
call(form.cleaned_data['inline'])
call(form.cleaned_data['outline'])
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = CallForm()
return render(request, 'CallForm.html', {'form': form})
This gave me an error message during the call which is:
"An application error has occurred. Goodbye"
And I also get this in the debugger:
"Error on line 1 of document : Premature end of file. "
Any idea?

Okay so, I figured this out. The only thing that was needed to make that setup work is I had to modify the response, add the xml string there and then set the content_type of the returned object.
return HttpResponse(str(response),content_type='application/xml')

Related

Check if endpoint was called in python function

I'm writing behave tests for some python functions and in one test im trying to check
if a specific api endpoint was called properly.
The simplified Scenario would be:
Scenario: Order was created properly
When I order a product
Then the order is forwarded to the tracker service
And the order was placed successfully
And the steps file looks like this:
#when("I order a product")
def ordering_product(context):
context.order_id = order_product()
#then("the order is forwarded to the tracker service")
def forwarded_to_tracker(context):
#need help here
pass
#then("the order was placed successfully")
def successful_order(context):
r = requests.get(f"http://order-api/orderstatus/{context.order_id}")
data = r.json()
assert data['status'] == 'SUCCESS'
and the order_product function:
def order_product():
my_order = create_order_body()
requests.post("http://tracking-service/addorder", data=my_order)
return requests.post("http://order-api/createorder", data=my_order)
My question is how can I check that the request to http://tracking-service was made without returning the response in addition to the order-api response from order_product.

Is this a correct class-based-django-view?

In my project i have a page that displays a form where the User inputs some irrelevant(for the moment project name) and a host/ip-address. When he hits the scan button he makes a post request.
In the current moment i get that ip address and im trying to 'banner-grab' the running services on that ip/host and render the results to the page. In the code below i got that working but as im litteraly using django for the first time i think that my aproach is really bad cause all of my code( for grabbing the banner etc ) is in the POST function in my class-based-view.So question is can i do this in a better way? Maybe write that bannerGrab() function somewere else and, if form is valid just call the function in the POST method...
class NewProject(View):
# Reusable across functions
form_class = ProjectData
template_name = 'projectRelated/create_project.html'
ports = [20, 21, 22, 23, 80, 3306]
def get(self, request):
# redundant to use it like this
# form = ProjectData()
form = self.form_class
context = {
'form': form
# this is a context variable that i can use in my html page. like this <h3> {{ context.var }} </h3>
# context = {
# 'context.var': 'This will render in the html'
# }
}
print('Get method accessed!')
return render(request, self.template_name, context)
# TODO: Find a better way to show and store ports
# Store the results in JSON
# TODO: Store to JSON by choice. Not all code in POST method!!!
def post(self, request):
list_of_services = []
form = self.form_class(request.POST)
if form.is_valid():
_target = form.cleaned_data['target']
host_to_ip = ''
# project_from_input = form.cleaned_data['project_name']
print(_target)
for port in self.ports:
try:
error_message = 'Couldn\'t connect. Try another subnet!'
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# if connection is established result is 0.
# 0.5 seconds timeout. If subnet isn't reachable
socket_obj.settimeout(2)
if _target.isalpha():
# if user's input was alphanumeric convert to an ip address
host_to_ip = socket.gethostbyname(_target)
result = socket_obj.connect_ex((host_to_ip, port))
else:
# user's input was an IP address.
result = socket_obj.connect_ex((_target, port))
# If port is HTTP we need to make a request to get data!
if port == 80 and result == 0:
# in order to get an answer from the server we need to make a legitimate request to him.
bytes_to_send = str.encode("HEAD / HTTP/1.1\r\n\r\n")
# send our request FIRST.
socket_obj.send(bytes_to_send)
# grab the banner after server answers
banner = socket_obj.recv(1024).decode('utf-8')
for service in banner.split('\n'):
if 'Server:' in service:
list_of_services.append(service + ' running at port : ' + str(port))
socket_obj.close()
# an established connection returns 0 !
if result == 0:
banner = socket_obj.recv(1024).decode('utf-8')
banner_with_port = banner + ' running at port : ' + port
list_of_services.append(banner_with_port)
socket_obj.close()
except Exception as ex:
print('Exception -> ' + str(ex))
finally:
socket_obj.close()
# After button Run-Scan is pressed clear the form without reloading the page.
form = self.form_class
context = {
'form': form,
'list_of_services': list_of_services,
'error_message': error_message,
'target_input': _target,
}
print('POST METHOD ACCESSED!')
return render(request, self.template_name, context)```
Yes sure, moving all that logic into another method will make the code much cleaner. The post method should usually be concerned with parsing the form data, validating it and returning the response.
You could just make another method inside the NewProject class. Or you can create a new class called BannerManager and move the logic there. But I don't see a point in creating a new class unless you have more place where you are working with sockets, banners etc.

Return multiple times from one api call in Flask Restful

I want to call a generate() function and send a user a message, but then continue executing a function.
#application.route("/api/v1.0/gen", methods=['POST'])
def generate():
return "Your id for getting the generated data is 'hgF8_dh4kdsRjdr'"
main() #generate a data
return "Successfully generated something. Use your id to get the data"
I understand that this is not a correct way of returning, but I hope you get the idea of what I am trying to accomplish. Maybe Flask has some build-in method to return multiple times from one api call?
Basically, what are you describing is called Server-Sent Events (aka SSE)
The difference of this format, that they returned an 'eventstream' Response type instead of usual JSON/plaintext
And if you want to use it with python/flask, you need generators.
Small code example (with GET request):
#application.route("/api/v1.0/gen", methods=['GET'])
def stream():
def eventStream():
text = "Your id for getting the generated data is 'hgF8_dh4kdsRjdr'"
yield str(Message(data = text, type="message"))
main()
text = "Successfully generated something. Use your id to get the data"
yield str(Message(data = text, type="message"))
resp.headers['Content-Type'] = 'text/event-stream'
resp.headers['Cache-Control'] = 'no-cache'
resp.headers['Connection'] = 'keep-alive'
return resp
Message class you can find here: https://gist.github.com/Alveona/b79c6583561a1d8c260de7ba944757a7
And of course, you need specific client that can properly read such responses.
postwoman.io supports SSE at Real-Time tab

Returning error indication when flask POST Request fails

I'm trying to create a simple flask application that takes a string from an iOS application and stores it in a local data base. I'm a bit confused whats happening in the return portion of the submitPost() function. I'm trying to return a dictionary that contains a BOOL that indicates whether the Post request executed fully. However, i'm not sure how to variate between returning a 0 or a 1.
//Function that handles the Post request
#app.route('/submitPost/', methods=['POST'])
def submitPost():
post = Post.from_json(request.json)
db.session.add(post)
db.session.commit()
return jsonify(post.to_json), {'Success': 1}
Try the below. This way if an exception is thrown when trying to insert data it will be caught and the transaction will be rolled back as well as a response being send back.
you could also replace the zero and one with True & False depending on your preference
Below code hasn't been tested
#app.route('/submitPost/', methods=['POST'])
def submitPost():
try:
post = Post.from_json(request.json)
db.session.add(post)
db.session.commit()
return jsonify({'Success': 1})
except Exception: # replace with a more meaningful exception
db.session.rollback()
return jsonify{'Failure': 0}

How do I return the Instagram Realtime subscription challenge?

I'm trying to subscribe to a tag. It appears that the callback URL is being called correctly with a hub.challenge and hub.mode, and I figured out how to access the challenge using self.request.get('hub.challenge'). I thought I was just supposed to echo the challenge, but that doesn't appear to work since I receive the following errors in the GAE logs:
InstagramAPIError: (400) APISubscriptionError-Challenge verification failed. Sent "647bf6dbed31465093ee970577ce1b72", received "
647bf6dbed31465093ee970577ce1b72
".
Here is the full handler:
class InstagramHandler(BaseHandler):
def get(self):
def process_tag_update(update):
update = update
mode = self.request.get('hub.mode')
challenge = self.request.get('hub.challenge')
verify_token = self.request.get('hub.verify_token')
if challenge:
template_values = {'challenge':challenge}
path = os.path.join(os.path.dirname(__file__), '../templates/instagram.html')
html = template.render(path, template_values)
self.response.out.write(html)
else:
reactor = subscriptions.SubscriptionsReactor()
reactor.register_callback(subscriptions.SubscriptionType.TAG, process_tag_update)
x_hub_signature = self.request.headers.get('X-Hub-Signature')
raw_response = self.request.data
try:
reactor.process('INSTAGRAM_SECRET', raw_response, x_hub_signature)
except subscriptions.SubscriptionVerifyError:
logging.error('Instagram signature mismatch')
So returning it as a string worked. I should have payed closer attention to the error message, but it took a helpful person on the Python IRC to point out the extra line breaks in the message. Once I put the template files on one line, it seemed to work. I can now confirm that my app is authorized via Instagram's list subscription URL.

Categories

Resources