Headlines Function - Alexa Skills w/ Python and Flask-Ask Part 2





Welcome to the second Alexa Skills tutorial for Python programmers. In this tutorial, we're going to build the Python function that actually does something. We've configured out how Skill will work with the Alexa device, but we don't yet have anything for our Skill to do.

For now, our Alexa Skill will remain very simple and just simply read off headlines from Reddit's World News subreddit. You can feel free to change the subreddit in the code if you like, or you can even make a function that returns something else entirely! To begin:

def get_headlines():
    user_pass_dict = {'user': **username**,
              'passwd': **password**,
              'api_type': 'json'}

Where I have **username** and **password**, you need to fill in a valid username and password for a reddit account. If you do not have a Reddit account, you can make one in a matter of seconds. It's free, there's no email verification either, if you just want to make a quick throwaway account. Next, we need to actually login to this account.

Assuming you've already done the imports from the previous tutorial, we're ready to start a session, login, then visit the World News subreddit:

    sess = requests.Session()
    sess.headers.update({'User-Agent' : 'I am testing Alexa:sentdex'})
    sess.post(r'https://www.reddit.com/api/login', data=user_pass_dict)
    time.sleep(1)

With the code above, we've logged in. Now to go to the subreddit:

    url = "https://www.reddit.com/r/worldnews/.json?limit=10"
    html = sess.get(url)

Now to get the data:

    data = json.loads(html.content.decode('utf-8'))

Now to just get the titles:

    titles = [unidecode.unidecode(listing['data']['title']) for listing in data['data']['children']]
    titles = '... '.join([i for i in titles])
    return titles

If the one-liner for loop (list comprehension) is confusing, the following is the same logic:

    titles = []
    for listing in data['data']['children']:
        title = unidecode.unidecode(listing['data']['title'])
        titles.append(title)

Also, for more information on the the join, see string concatenation

Alright, so we have a function that returns headlines:

def get_headlines():
    user_pass_dict = {'user': '',
                      'passwd': '',
                      'api_type': 'json'}
    sess = requests.Session()
    sess.headers.update({'User-Agent': 'I am testing Alexa: Sentdex'})
    sess.post('https://www.reddit.com/api/login', data = user_pass_dict)
    time.sleep(1)
    url = 'https://reddit.com/r/worldnews/.json?limit=10'
    html = sess.get(url)
    data = json.loads(html.content.decode('utf-8'))
    titles = [unidecode.unidecode(listing['data']['title']) for listing in data['data']['children']]
    titles = '... '.join([i for i in titles])
    return titles  

Our full Python code up to this point:

from flask import Flask
from flask_ask import Ask, statement, question, session
import json
import requests
import time
import unidecode

app = Flask(__name__)
ask = Ask(app, "/reddit_reader")

def get_headlines():
    user_pass_dict = {'user': '',
                      'passwd': '',
                      'api_type': 'json'}
    sess = requests.Session()
    sess.headers.update({'User-Agent': 'I am testing Alexa: Sentdex'})
    sess.post('https://www.reddit.com/api/login', data = user_pass_dict)
    time.sleep(1)
    url = 'https://reddit.com/r/worldnews/.json?limit=10'
    html = sess.get(url)
    data = json.loads(html.content.decode('utf-8'))
    titles = [unidecode.unidecode(listing['data']['title']) for listing in data['data']['children']]
    titles = '... '.join([i for i in titles])
    return titles  

@app.route('/')
def homepage():
    return "hi there, how ya doin?"

@ask.launch
def start_skill():
    welcome_message = 'Hello there, would you like the news?'
    return question(welcome_message)

@ask.intent("YesIntent")
def share_headlines():
    headlines = get_headlines()
    headline_msg = 'The current world news headlines are {}'.format(headlines)
    return statement(headline_msg)

@ask.intent("NoIntent")
def no_intent():
    bye_text = 'I am not sure why you asked me to run then, but okay... bye'
    return statement(bye_text)
    
if __name__ == '__main__':
    app.run(debug=True)

Now, assuming we fill in the username and password information, we're ready to test the code on our Alexa device, which is what we'll be doing in the next tutorial!

The next tutorial:






  • Intro and Skill Logic - Alexa Skills w/ Python and Flask-Ask Part 1
  • Headlines Function - Alexa Skills w/ Python and Flask-Ask Part 2
  • Testing our Skill - Alexa Skills w/ Python and Flask-Ask Part 3