Published © GPL3+

Destiny 2 Countdown

This skill helps you keep track of important Destiny 2 dates, and even includes a template so that you can create your own skill.

BeginnerFull instructions provided1 hour466
Destiny 2 Countdown

Things used in this project

Hardware components

Amazon Echo
Amazon Alexa Amazon Echo
Any Alexa enabled device will work.
×1

Software apps and online services

AWS Lambda
Amazon Web Services AWS Lambda
Alexa Skills Kit
Amazon Alexa Alexa Skills Kit

Story

Read more

Schematics

VUI Diagram

This demonstrates the basic interaction flow of a countdown skill. If the stream is open it means Alexa is waiting for a response from the user. If it is closed it means any further response will not be passed to the skill until it is reopened.

Code

Lambda Function for Destiny 2 Countdown

Python
This is the production Lambda code for the Destiny 2 Countdown Skill
from datetime import datetime
import math
# --------------- Helpers that build all of the responses ----------------------

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': title,
            'content': output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }


def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }


# --------------- Functions that control the skill's behavior ------------------

def beta():
    session_attributes = {}
    card_title = "Countdown"
    now = datetime.today()
    target = datetime.strptime('Jul 18 2017  4:00AM', '%b %d %Y %I:%M%p')
    difference = target - now
    days = difference.days
    hours = math.floor(difference.seconds / 3600) % 24
    seconds = difference.seconds % 60
    minutes = math.floor(difference.seconds / 60) % 60
    totalDays = difference.days
    speech_output = "There are " + str(days) + " days, " + str(hours) + " hours, " + str(minutes) + " minutes, and " + str(seconds) + " seconds left until the Early Access Beta will be available on Playstation. 24 Hours later it will be avaiable on Xbox and 48 hours later after Xbox the beta will be open on both consoles. The PC beta date is still unknown."
    reprompt_text = "There are about " + str(totalDays) + " days left.Just ask if you want to know anything more."
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))
        
def release_countdown():
    session_attributes = {}
    card_title = "Countdown"
    now = datetime.today()
    target = datetime.strptime('Sep 6 2017  4:00AM', '%b %d %Y %I:%M%p')
    difference = target - now
    days = difference.days
    hours = math.floor(difference.seconds / 3600) % 24
    seconds = difference.seconds % 60
    minutes = math.floor(difference.seconds / 60) % 60
    totalDays = difference.days
    speech_output = "There are " + str(days) + " days, " + str(hours) + " hours, " + str(minutes) + " minutes, and " + str(seconds) + " seconds left until Destiny 2 will be released on console. PC will come out 48 days afterwards."
    reprompt_text = "There are about " + str(totalDays) + " days left. Just ask if you want to know anything more."
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))


def handle_session_end_request():
    card_title = "Thanks for using this skill."
    speech_output = "Thanks for using this skill. For news on new Destiny skills follow @randomrumblegen on Twitter."
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))

def help():
    card_title = "Help"
    speech_output = "This skill provides a countdown until important Destiny 2 events. You can ask how long is left until the release or the beta."
    should_end_session = False
    return build_response({}, build_speechlet_response(
        card_title, speech_output, speech_output, should_end_session))
        



# --------------- Events ------------------

def on_session_started():
    session_attributes = {}

def on_launch(launch_request, session):
    print(release_countdown())
    return release_countdown()

def on_intent(intent_request, session):
    intent = intent_request['request']['intent']
    intent_name = intent_request['request']['intent']['name']

    if intent_name == "ReleaseCountdownIntent":
        return release_countdown()
    elif intent_name == "BetaCountdownIntent":
        return beta()
    elif intent_name == "AMAZON.HelpIntent":
        return help()
    elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        return handle_session_end_request()
    else:
        raise ValueError("Invalid intent")


def on_session_ended(session_ended_request, session):
    return  handle_session_end_request()
    print("on_session_ended requestId=" + session_ended_request['requestId'] +
          ", sessionId=" + session['sessionId'])


# --------------- Main handler ------------------

def lambda_handler(event, context):
    if event['request']['type'] == "IntentRequest":
        return on_intent(event, event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])
    else:
        return release_countdown()

Skill Builder Code for Destiny 2 Countdown Skill

JSON
This code is pasted into the new skill builder portal under the code section.
{
  "intents": [
    {
      "name": "AMAZON.CancelIntent",
      "samples": []
    },
    {
      "name": "AMAZON.HelpIntent",
      "samples": [
        "What can you do",
        "Help me",
        "What are your commands",
        "What functions do you have",
        "What can you tell me"
      ]
    },
    {
      "name": "AMAZON.StopIntent",
      "samples": [
        "Don't do that",
        "That's wrong"
      ]
    },
    {
      "name": "BetaCountdownIntent",
      "samples": [
        "How long until the beta",
        "how long until the destiny two beta",
        "when is the beta",
        "time until the beta",
        "how long is left on the beta",
        "beta",
        "How many days until the beta"
      ],
      "slots": []
    },
    {
      "name": "ReleaseCountdownIntent",
      "samples": [
        "How long is left",
        "How long",
        "Time left",
        "Countdown",
        "How long until Destiny two",
        "Destiny two countdown",
        "Destiny two",
        "Destiny two release",
        "Countdown for Destiny two release",
        "Time until release",
        "Release countdown"
      ],
      "slots": []
    }
  ]
}

Lambda Template

Python
Edit this template to make the Lambda function for your own skill.
from datetime import datetime
import math
# --------------- Helpers that build all of the responses ----------------------

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': title,
            'content': output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }


def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }


# --------------- Functions that control the skill's behavior ------------------

#when adding more secondary events just copy this function and change the name to have the next letter each time. Make sure to also change the date so that it isn't counting down to the same thing!

def secondary_a():
    session_attributes = {}
    card_title = "Countdown"
    now = datetime.today()
    
    #Change the date below
    target = datetime.strptime('Jul 18 2017  4:00AM', '%b %d %Y %I:%M%p')
    
    difference = target - now
    days = difference.days
    hours = math.floor(difference.seconds / 3600) % 24
    seconds = difference.seconds % 60
    minutes = math.floor(difference.seconds / 60) % 60
    totalDays = difference.days
    speech_output = "There are " + str(days) + " days, " + str(hours) + " hours, " + str(minutes) + " minutes, and " + str(seconds) + " seconds left until the event."
    reprompt_text = "There are about " + str(totalDays) + " days left. Just ask if you want to know about any of the other dates."
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))
        
def primary():
    session_attributes = {}
    card_title = "Countdown"
    now = datetime.today()
    
    #change the date in the line below
    target = datetime.strptime('Sep 6 2017  4:00AM', '%b %d %Y %I:%M%p')
    
    difference = target - now
    days = difference.days
    hours = math.floor(difference.seconds / 3600) % 24
    seconds = difference.seconds % 60
    minutes = math.floor(difference.seconds / 60) % 60
    totalDays = difference.days
    speech_output = "There are " + str(days) + " days, " + str(hours) + " hours, " + str(minutes) + " minutes, and " + str(seconds) + " seconds left until the event."
    reprompt_text = "There are about " + str(totalDays) + " days left. Just ask if you want to know about any of the other dates."
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))


def handle_session_end_request():
    card_title = "Thanks for using this skill."
    
    #Fill in the fields that are in ALL CAPS
    speech_output = "Thanks for using this skill. Follow " + "YOURUSERNAME on PLATFORM" + "for updates"
    
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))

def help():
    card_title = "Help"
    speech_output = "This skill provides a countdown until important events. You can ask how long is left."
    repromt_text = "Try asking how long is left."
    should_end_session = False
    return build_response({}, build_speechlet_response(
        card_title, speech_output, repromt_text, should_end_session))
        



# --------------- Events ------------------

def on_session_started():
    session_attributes = {}

def on_launch(launch_request, session):
    return primary()

def on_intent(intent_request, session):
    intent = intent_request['request']['intent']
    intent_name = intent_request['request']['intent']['name']

    if intent_name == "PrimaryIntent":
        return primary()
    elif intent_name == "SecondaryAIntent":
        return secondary_a()
        
    #If adding another secondary just copy the two lines above, changing A to B and so on each time you copy. Make sure to also copy the function code up higher in the file as instructed
    
    elif intent_name == "AMAZON.HelpIntent":
        return help()
    elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        return handle_session_end_request()
    else:
        raise ValueError("Invalid intent")


def on_session_ended(session_ended_request, session):

    return  handle_session_end_request()
    print("on_session_ended requestId=" + session_ended_request['requestId'] +
          ", sessionId=" + session['sessionId'])


# --------------- Main handler ------------------

def lambda_handler(event, context):
    if event['request']['type'] == "IntentRequest":
        return on_intent(event, event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])
    else:
        return primary()

Skill Builder Template

JSON
Edit and then paste into the skill builder code field. Copy the SecondaryAIntent as needed to add more secondary intents changing the letter and phrases each time. Change it where it says "EVENT" to match your event name.
{
  "intents": [
    {
      "name": "AMAZON.CancelIntent",
      "samples": []
    },
    {
      "name": "AMAZON.HelpIntent",
      "samples": [
        "What can you do",
        "Help me",
        "What are your commands",
        "What functions do you have",
        "What can you tell me"
      ]
    },
    {
      "name": "AMAZON.StopIntent",
      "samples": [
        "Don't do that",
        "That's wrong"
      ]
    },
    {
      "name": "SecondaryAIntent",
      "samples": [
        "How long until the EVENT",
        "when is the EVENT",
        "time until the EVENT",
        "how long is left on the EVENT",
        "EVENT",
        "How many days until the EVENT"
      ],
      "slots": []
    },
    {
      "name": "ReleaseCountdownIntent",
      "samples": [
        "How long is left",
        "How long",
        "Time left",
        "Countdown",
        "How long until EVENT",
        "EVENT countdown",
        "EVENT",
        "EVENT start",
        "Countdown for EVENT release",
        "Time until start",
        "Start countdown"
      ],
      "slots": []
    }
  ]
}

Credits

Comments