|
from flask import Flask |
|
from flask import request |
|
from flask import send_file |
|
from flask_sqlalchemy import SQLAlchemy |
|
from uuid import uuid1 |
|
from random import randint |
|
from twilio.rest import TwilioRestClient |
|
import json |
|
import os |
|
from twilio import twiml |
|
|
|
app = Flask(__name__) |
|
basedir = os.path.abspath(os.path.dirname(__file__)) |
|
database_uri = 'sqlite:///' + os.path.join(basedir, 'dev.sqlite') |
|
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri |
|
db = SQLAlchemy(app) |
|
|
|
# Get these credentials from http://twilio.com/user/account |
|
TWILIO_ACCOUNT_SID = 'my-account-sid' |
|
TWILIO_AUTH_TOKEN = 'my-auth-token' |
|
TWILIO_PHONE_NUMBER = 'my-phone-number' |
|
|
|
# Your URL should be accessible through the web. |
|
# If you are testing locally, you can use 'ngrok' to expose it. |
|
# Remember to append the /twiml/ suffix. |
|
TWIML_URL = 'https://www.example.org/twiml/' |
|
|
|
|
|
class Number(db.Model): |
|
id = db.Column(db.String(36), primary_key=True) |
|
phone_number = db.Column(db.String(20), unique=True) |
|
verification_code = db.Column(db.String(6)) |
|
verified = db.Column(db.Boolean) |
|
|
|
def __init__(self, phone_number, verification_code): |
|
self.id = str(uuid1()) |
|
self.phone_number = phone_number |
|
self.verification_code = verification_code |
|
self.verified = False |
|
|
|
def __repr__(self): |
|
return '<Number %r>' % self.id |
|
|
|
|
|
@app.route('/', methods=['GET']) |
|
def index_route(): |
|
return send_file('index.html') |
|
|
|
|
|
@app.route('/call/', methods=['POST']) |
|
def call_route(): |
|
verification_code = randint(100000, 999999) |
|
phone_number = request.form['phone_number'] |
|
|
|
Number.query.delete() |
|
number = Number(phone_number, verification_code) |
|
db.session.add(number) |
|
db.session.commit() |
|
|
|
client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN) |
|
client.calls.create(to=phone_number, url=TWIML_URL, |
|
from_=TWILIO_PHONE_NUMBER) |
|
|
|
return json.dumps({'verification_code': verification_code}) |
|
|
|
|
|
@app.route('/twiml/', methods=['POST']) |
|
def twiml_route(): |
|
code = request.form.get('Digits', None) |
|
r = twiml.Response() |
|
|
|
if not code: |
|
with r.gather(numDigits=6) as g: |
|
g.say('Please enter your verification code.') |
|
else: |
|
phone_number = request.form['Called'] |
|
number = Number.query.filter_by(phone_number=phone_number, |
|
verification_code=code).first() |
|
if not number: |
|
with r.gather(numDigits=6) as g: |
|
g.say('Verification code incorrect, please try again.') |
|
else: |
|
number.verified = True |
|
db.session.add(number) |
|
db.session.commit() |
|
r.say('Thank you! Your phone number has been verified.') |
|
|
|
return str(r) |
|
|
|
|
|
@app.route('/status/', methods=['POST']) |
|
def status_route(): |
|
number = Number.query.filter_by( |
|
phone_number=request.form['phone_number'], verified=True).first() |
|
return json.dumps({'status': 'verified' if number else 'unverified'}) |
|
|
|
if __name__ == '__main__': |
|
db.create_all() |
@mosampaio, could you remove the trailing slashes from the routes in the route decorators?
e.g. https://gist.github.com/mosampaio/2ce95ddec134c976ad77a94d2ba9feae/#file-app-py-L50