Simple App on Google Cloud Functions from scratch
Tags: googlecloudfunctions, telegram, learn, tutorial
Published: 2019-03-07 15:40:06

---
title: Simple App on Google Cloud Functions from scratch
published: true
description: I wanted to see how easy it would be to write and deploy an app on Google Cloud with zero experience.
tags: google cloud functions,telegram,learn,tutorial
---

## Requirements
- Software required: python 3.7.x, pip3, git, ssh-keygen
- Time: 30 mins
- Accounts: 
  - Telegram for messaging
  - Google Cloud free tier, credit card required :(
- Cost: 0.00

## Why?
I wanted to learn how to use Google Cloud Functions by building a simple but useful app.
## Steps
### 1. Create a Google Cloud a/c
So unfortunately, like with AWS, you need a credit card to signup. At the moment Google are offering $300 credit for first year, but we don't want to spend any of that credit.
### 2. Create New Project
Create a new project and give it a name, this project will contain all the cloud components used.

![new project](https://thepracticaldev.s3.amazonaws.com/i/kpg0yjyb0xwpbm60znsk.png 'New project dialog')
![new project](https://thepracticaldev.s3.amazonaws.com/i/5oi7t0w5b8ryaqvhndlf.png 'Project Created')
### 3. Cloud Function
This is the serverless function that will execute periodically. Cloud Functions support various languages, we will be using python 3.7 which is currently in beta but isn't everything in Google? ;)

![](https://thepracticaldev.s3.amazonaws.com/i/dvmugngaene6300pptxi.png 'Create Cloud Function dialog')
Use the settings in screenshot below...

![](https://thepracticaldev.s3.amazonaws.com/i/c7t5bfr35g2uul623ohf.png 'New Cloud Function settings')
Use the settings in screenshot below, some you may wish to change:
- Repository Name: use the name of the repository you created
- Function to execute: the name of the python function to execute
- Region: pick whichever region is most appropriate for your use case
- Environment Variables: Add as many env variables as you wish, choose appropriate variables to store here. 
Note: in this example 2 secrets are stored as environment variables to remove them from source code, much better practice is to use Googles KMS to encrypt secrets and store them in Cloud storage, but this is outside the scope of this post.

![](https://thepracticaldev.s3.amazonaws.com/i/djzp1rxbrr7byus8plli.png 'New Cloud Function settings p2')

Choose *Create* and the function will be created, this can take a few mins as the repository is resolved and verified to match the configuration, any problems will be displayed and must be resolved before function is active.

### 4. Source Repo
Navigate to *Source Repositories* under Tools section of left menu.
Choose *Add repository*
Chose *Create new repository* and give it an appropriate name.
![](https://thepracticaldev.s3.amazonaws.com/i/54parroianjizjzxjw0y.png 'New repository dialog')
Now you need to clone the repository locally so you can modify it and push changes back. 
If you have an ssh key already skip the next step, otherwise...
Linux: type `ssh-keygen` and fill in required details

![](https://thepracticaldev.s3.amazonaws.com/i/iidkrd5b9hu5ed1av17n.png 'ssh-keygan screenshot')

Your new key pair will be in the directory you specified, the `.pub` file will be uploaded to Google.

Time to register the key, choose the *Register the SSH key* option and make sure to use your public key, usually found here: `~/.ssh/id_rsa.pub`

Now clone the repo using the command shown: `git clone ....`

### 5. Simple source code
The code is pretty simple, it does the following on execution:
1. Download rss and parse
2. Send new bargains via telegram

```python
import os, json, base64
from calendar import timegm
from datetime import datetime
import requests
import feedparser 

MINS_DIFF = 5
SLICKDEALS = 'https://slickdeals.net/newsearch.php?mode=frontpage&searcharea=deals&searchin=first&rss=1'

def go(event, context):
    num_deals_found = check_slick_deals()
    print(f'Found {num_deals_found} deals')
        
def check_slick_deals():
    items_found = 0
    try:
        NewsFeed = feedparser.parse(SLICKDEALS)
        for entry in NewsFeed.entries:
            publish_date = entry['published_parsed']
            # use appropriate timezone here 
            dt = datetime.fromtimestamp(timegm(publish_date)) 
            nownow = datetime.utcnow()
            mins_diff = abs((nownow - dt).total_seconds()) / 60
            if mins_diff < MINS_DIFF:
                items_found = items_found + 1
                send_message(f"{entry['title']} {entry['link']}")
    except Exception as e:
        print(f'Error parsing newsfeed: {e}')
    return items_found

def send_message(message):
    api_hash = os.environ.get('API_HASH', None)
    chat_id = os.environ.get('CHAT_ID', None)
    if api_hash is None or chat_id is None:
        print('Please set API_HASH and CHAT_ID env variables')
        return        
    api_url = f'https://api.telegram.org/bot{api_hash}'
    payload = {}
    payload['chat_id'] = chat_id
    payload['text'] = message
    r = requests.post(f'{api_url}/sendMessage', data=payload)

if __name__== "__main__":
    go(None, None)
```
Make sure you call the file `main.py` and add a corresponding `requirements.txt`, push them both to git repo with the following commands:
```
git add main.py requirements.txt
git commit -m 'adding initial files'
git push
```

Now the code is sitting in the repo, ready to be executed by the Cloud Function.

### 6. Cloud Schedule 
We now have:
- Source code sitting in cloud repo, ready to be cloned by function
- Cloud Function to execute source when triggered
- Pubsub topic that will trigger source when message received

We just need something to add a message and kick off the function, Cloud Scheduler is perfect for that.

First decide on what schedule you want the function to execute. I chose every 5 minutes, the cron for this is `*/5 * * * *` https://crontab.guru/ is a great website that can help create an accurate cron configuration.

When you are finished, it should look something like this:

![](https://thepracticaldev.s3.amazonaws.com/i/ihnyd6b8p9bur9n1bfka.png 'cron job')

### 7. Done!
Congratulations, your new app is living in the cloud, laying dormant until a schedule wakens it from it's slumber.

Once you have created your first serverless app, it's exciting to think what else is possible, please let me know what you create and I will do the same :)