The Useless Idea Behind It:
Me and my two roommates live in an apartment where we have a cook who comes in daily to prepare delicious meals for us. All is well and good until he comes in asks 'What to make for dinner?' . All of us dread this question because it requires checking the pantry and finding out what is available and consulting among us what to have for dinner.Leaving out the 'I don't wanna have eggs today, I had it in the morning' type shenanigans. What can we do to make our lives simpler with a bit of tech?
The Trivial Solution:
Set up a Google calendar and add our cook to it. We schedule our meals taking into account everyone's preferences. Calendar would send him a notification and he would know. Simple right? But lets add some more tech to it.
The Dev way to do it:
Recently I got a Free IBM cloud account and wanted to try IBM Cloud Functions. Another useless idea incoming: Let's make a serverless app which picks up events(containing the menu for the day) from Google Calendar and daily send it to a Telegram group consisting of me, my roommates and the cook.
Steps to achieve this:
First you have a create a free tier account in cloud.ibm.com and follow these steps to setup your ibmcloud cli
Cloud Functions should be containerized and the implementation should do one simple job, the more time and resources you save for each job the more free requests per month you get. More on planning here
For this particular project we need a action that can be invoked from a URL. More on actions
I am using python-3.7 environment for this and a couple of Google api client packages.
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
Create a directory with your project name
mkdir cook_ko_bolde && cd cook_ko_bolde
virtualenv virtualenv
Make sure you name you virtualenv as virtualenv. We will come to this later. Create a file called main.py and helper,py in the same directory.
#__main__.py
from helper import helper
def main(args):
return helper(args)
#__helper__.py
from urllib.request import urlopen
from urllib.parse import urlencode
import datetime
import httplib2
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
def get_google_calendar_service():
credentials = ServiceAccountCredentials.from_json_keyfile_name(
filename='./creds.json',
scopes=['https://www.googleapis.com/auth/calendar']
)
http = credentials.authorize(httplib2.Http())
service = build('calendar', 'v3', http=http)
return service
def get_events():
service = get_google_calendar_service()
now = datetime.datetime.utcnow().isoformat() + 'Z'
events_result = service.events().list(calendarId='YOUR_CALENDAR_ID',
timeMin=now, maxResults=1, singleEvents=True, orderBy='startTime').execute()
events = events_result.get('items', [])
event = events[0]
if not event:
return {'text': 'No food for today! Happy dieting'}
text = 'Menu for today \nMenu : {} \nItems: {}'.format(event['summary'], event['description'])
return {'text': text}
def helper(data):
text = get_events()['text']
api_key = data['TGRAM_API_KEY']
chat_id = data['TGRAM_CHAT_ID']
message = {
'chat_id': '-' + chat_id,
'text': text
}
url_text = urlencode(message)
url = 'https://api.telegram.org/' \
'bot{}/sendMessage?{}'.format(api_key, url_text)
f = urlopen(url)
return {
'message': f.read().decode('utf-8')
}
How to get Google API Service Account Credentials
Add your downloaded creds.json
file to the same directory.
Follow this How to create a Telegram bot, and send messages with Python to get your TGRAM_API_KEY
& TGRAM_CHAT_ID
To get your YOUR_CALENDAR_ID
go Settings and search for your calendar.
Copy the Calendar ID as here
Now that we done with the code, lets deploy. Create a zip file containing your project files and virtualenv directory as well. Make sure the name of the directory is virtualenv
otherwise ibmcloud cli will not be able to detect it while build the image .
cd cook_ko_bolde
zip -r target.zip __main__.py helper.py virtualenv creds.json
Lets create the action with parameters.
ibmcloud fn action create cook_ko_bolde --kind python:3 target.zip --param TGRAM_API_KEY <your-tgram-api-key> TGRAM_CHAT_ID <your-tgram-chat/group-id>
Login in to cloud.ibm.com and head over to Cloud Function. You should be seeing something like this.
Head over and click on Invoke . If you have no errors you should have received a message from your Telegram Bot telling you the contents of today's meal.
But we don't wanna invoke manually every time do we? We need to get an HTTP API endpoint which invokes the action.
Head over to Endpoints and tick off Enable as Web Action
optionally you can also enable Raw HTTP handling
.
Copy the URL and open it in a browser. If everything is proper you should get the similar message from your Telegram Bot as before.
But someone has to hit the URL in order for it to work. Lets try scheduling this using Web based Cron scheduler.
Head over to Easy Cron and get a free account.
Create a new Cron Job and add the copied URL to the
URL to call
field, change the interval as you like it.
That's it , we did it. We managed to create a serverless app to notify our cook of our daily menu. An 'useless idea' but nonetheless great fun to make.
P.S - cook_ko_bolde
means Tell the cook in Hindi