Sirclesam
Posted on September 24, 2019
I will browse through imgur when I have some time to kill, and often that means seeing pictures of things I know my ladyface will like, it's usually puppies.
For a while I'd just right-click copy the URL, then open android SMS web app messages.google.com, find the lady, paste and DONE. However, after a particularly cute day I found my self doing this several times in a row and it's not very efficient, so one lazy morning I got ambitious and got something cobbled together that worked...but wasn't ideal.
My first version worked by sending the URL to my node server that's running one of my personal projects with some special query strings and using that to fire off an SMS using the Twilio module. While this worked, it is less than ideal since it meant I have this code on my server that has nothing to do with its main purpose, but for something I cooked up in a few hours one morning, it will do.
I finally got around to getting this to work the way I wanted, and that seems much more suited to the task, which is using AWS Lambda functions, and that's what I'm going to walk through here.
I'll touch on the outline, then we'll step through the individual steps for getting it up and running.
We'll be using a chrome extension to hit an AWS API Gateway, that's tied to a Lambda function that uses AWS SNS to send an SMS. Let's get started working backwards.
Note: You'll need an AWS account with a credit card tied to it, everything I use is very cheap (0.00645 per SMS) but amazon still needs to be able to charge you.
SNS
1) Go to the SNS home page
2) create a new topic, named anything you like.
3) Give your topic a display name. Note the first 10 characters of this will show up on every SMS you send. So for mine being PupperSMS texts look like this:
PupperSMS>http://i.imgur.com/cRF0KoB.jpg
4) Create an SMS subscription for this topic.
- Click create subscription, select the ARN for the topic you just created.
- Put the phone number you intend to send things to in the endpoint, I use the full +11234567890 style
- I advise using your number at first so your intended audience doesn't have to get your test messages.
- You can include multiple subscriptions here if you want to send to multiple numbers.
5) Test it.
You can test that it works by clicking 'Publish Message' enter something in the body and click 'Publish Message' at the bottom. You should get an SMS from a 5 digit number at the number you put in with your display name at the beginning.
6) Keep track of the ARN, we'll need that for later.
Lambda
Now for the fun stuff.
1) Go to the AWS lambda homepage
2) Click 'create a function', choose 'author from scratch' and runtime as 'python 2.7'
- it will take a bit, AWS also creates an IAM role for your lambda func
- Note: I had errors with the default role creation, so I used one I created in IAM. You can create one here choose lambda for services and AdministratorAccess for permissions. It's probably overkill for what we're doing but will work for now.
3) Add in the lambda python code:
from __future__ import print_function
import json
import urllib
import boto3
import os
print('Loading message function...')
def lambda_handler(event, context):
if event["queryStringParameters"]["key"] == os.environ["KEY"]:
send_to_sns(event["queryStringParameters"]["url"], context)
message = "Message Sent!"
else:
message = "Invalid Key - try again"
return {
"statusCode": 200,
"body": json.dumps(message)
}
def send_to_sns(smsMessage,context):
sns = boto3.client('sns')
sns.publish(
TopicArn={YOUR SNS ARN HERE},
Message=smsMessage
)
return ('Sent a message to an Amazon SNS topic.')
Before this will work you need to grab the ARN from your SNS and set it to the TopicArn above. Like this:
TopicArn="arn:aws:sns:us-west-2:1234567890:mySMS",
You can test this by changing the lambda handler to lambda_function.send_to_sns and a test event to just a string. Once you hit test, it should send an SMS with that string to your phone.
Change the handler back to lambda_function.lambda_handler and I'll briefly go over what's going on in the other function.
We're going to use AWS API gateway to activate this function, which will give us a URL we can hit, and using something called Lambda Proxy which will allow us to take query strings from a URL and pass them to the lambda function in the event object.
These are stored in the 'queryStringParameters' object. The 'url' is the data we're interested in, but you'll notice there's also a 'key' parameter. This is to add a bit of security to our api so that not anyone in the world can trigger this, but only when the api is hit with the correct key value.
This can probably be done with AWS security features, but I haven't gotten that far yet - if you have a better method please let me know!
Pick something that you'll use as your security key. I use a UUID string, you can generate one here: https://www.uuidgenerator.net/
Right under the code on your lambda function, there's a section for environment variables - place your KEY / UUID here. It doesn't need to be long, but it should be long enough that brute force is out of the question. You could even correct horse battery staple it: https://www.xkcd.com/936/.
API Gateway
Time to expose our lambda to the world!
2) Click 'get started' to create a new API
3)Select New API, give it a name and description, leave endpoint as regional, click 'create API'
4) Click 'actions' --> 'create method', select GET from the dropdown and click the checkmark.
5) Select integration type: Lambda Function
6) Check 'use lambda proxy integration'
7) select your lambda function by name in the lambda function field.
- Select ok to allow the API access.
8) We'll need to enable query strings so we can pass data to our api and our lambda function. Click method request
8) Test your API by clicking the Test with the lightning icon.
- Enter url=canYouHearMeNow&key=YOURKEY in the query string field and hit test
- You should see 'message sent' and get a sms on your phone!
- Almost there, home stretch!
9)Deploy your API. Click 'actions' and select deploy API
- Create a new stage name
- TADA! you now have a url you can hit to trigger your lambda function.
- Remember you'll need the query string ?url=YOURURL&key=YOURKEY at the end of it to work as expected.
Chrome Extention
This will be pretty simple, only 2 files. However, it does involve putting your chrome extension in developer mode which does have some security implications, so be warned.
1) Download the repo at https://github.com/sselfridge/send-it
2) Put the unzipped files somewhere they can live going forward, they will be executed from here.
3) You only need to edit script.js, but you can modify manifest.json if you'd like to name it something else besides 'send it!'
4) In script.js add in your key and AWS endpoint
const AWS_API_ENPOINT = "https://123456789.execute-api.us-west-2.amazonaws.com/PuppyStage";
const KEY = "correcthorsebatterystaple";
5) Open Chrome and go to the 'manage extensions' page. You can get to it by right-clicking on any extension icons you have and click 'manage extensions' there.
6) click the 'developer mode' toggle in the top right
7) click 'load unpacked' in the new menu on the top left
8) select your folder
You're done! Go to any image in chrome and right-click on it, you should see the 'send it' option there and clicking it will send that URL to your number.
Remember you'll have to change/add more subscriptions in the AWS SNS console depending on which numbers you want to send it to.
Further Work
This does leave some things to be desired.
- There's no feedback if things stop working at any point.
- No icons for chrome extension
- Chrome warnings about dev mode on startup. Could be fixed by publishing to the chrome store, which I've done personally, but the AWS API endpoint is hardcoded since I didn't add the UI elements to prompt for it.
Cheers and happy puppy-ing!
Posted on September 24, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.