# Create Telegram Alerts with Cloudflare Workers and ScheduledEvent

# Introduction

## Motivations

Creating notifications on real events in the world is a very common scenario for developers.

[Telegram Bot](https://core.telegram.org/bots) provides a convenient API for sending messages, enabling users to program cron jobs to monitor events of their interest and trigger push notifications without the knowledge of iOS or Android development.

There are many ways to host such cron jobs:

### Running on a Raspberry Pi (or other forms of home server)

Home internet can face some stability issues such as internet connection. As recently as last Friday, [Rogers experienced a Canada-wide outage affecting mobile and broadband users](https://blog.cloudflare.com/cloudflares-view-of-the-rogers-communications-outage-in-canada/).

Electricity bills, or even a friend tripping over power cables (this happened to me), can also prevent you from building a reliable service.

 ### Running on a cloud provider

Virtual machines from cloud providers can incur a non-trivial cost. The cheapest VPS hosting services can cost from $2.50 to $5.00 monthly. The CPUs on these machines could be almost idle since most cron jobs wait for network responses, which is wasteful.

In addition, using a static IP address for web scraping will likely trigger a CAPTCHA.

## What makes Cloudflare Workers special

Cloudflare has a serverless edge computing platform called [Workers](https://workers.cloudflare.com/).

It chose the V8 JavaScript engine built by the Google Chrome team instead of traditional virtualization and containerization technologies like Kubernetes and Docker to power a sandboxed multi-tenant execution environment.

The V8 engine introduced the concept of [Isolates](https://v8.dev/docs/embed) in [2011](https://v8.dev/blog/10-years). An isolate is a VM instance with its own heap. A single process can run hundreds or thousands of Isolates. This saves tremendous overhead compared to containerized applications that occupy one process each.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1657557088216/LnF3MaRAt.png)

As a result, Cloudflare is able to offer a free plan for Workers, where the first 100,000 requests per day are free.

What is even more incredible, [Cron Triggers](https://developers.cloudflare.com/workers/platform/cron-triggers/), which allows developers to run Workers on a schedule, are provided at **no additional cost**. This is because cron jobs are less sensitive to latency as no users are waiting for them to finish. This gives Cloudflare more flexibility on where and when to schedule the Cron Triggers.

Cloudflare is not the only company that utilizes V8 isolates for serverless computing. [Deno Deploy](https://deno.com/deploy) and [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions) offer similar services, with minor differences in their runtime APIs.

# Get Started

## Create a Telegram bot

Creating a Telegram bot is as simple as sending `/newbot` to [@BotFather](https://t.me/botfather).

You will get an authentication token by doing so. It is the only information you need to talk to the Telegram Bot API.

## Find out your Telegram user ID

This blog post assumes that you only need to send notifications to yourself or a list of known users. If you want more complex interactions, check out these [examples](https://core.telegram.org/bots/samples).

Your bot needs your user ID to send a message to you. This information can be retrieved by sending `/start` to [@userinfobot](https://t.me/userinfobot).

## Create a Cron Trigger

1. Create a new Worker project called `cron` in the Cloudflare dashboard
2. Under the Triggers tab, configure the interval that you want your Worker to execute, or use the [cron syntax](https://crontab.guru/)
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1657917329180/3Z_dmQCMY.png align="left")

## Configure credentials

Under Settings -> Variables, save your Telegram Bot token as `TELEGRAM_BOT_TOKEN` and your user id as `TELEGRAM_CHAT_ID `.

Hit `Encrypt` when you enter these values, they will no longer be viewable once saved.
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1657917672155/APNfXY93R.png align="left")

## Write the code

1. Click `Quick Edit` to open an online IDE to edit your Worker script
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1657915082421/kUKhEShsH.png align="left")

2. Create a `sendMessage` function. Your credentials can be accessed via global variables in the Worker script
```JavaScript
   async function sendMessage(message) {
       const response = await fetch('https://api.telegram.org/bot' + TELEGRAM_BOT_TOKEN + '/sendMessage', {
           method: 'POST',
           headers: {  'Content-Type': 'application/json' },
           body: JSON.stringify({
               chat_id: TELEGRAM_CHAT_ID,
               text: message.toString().substring(0, 4096)
           })
       })
       return response
   }
```

3. Use `addEventListener` to subscribe to the `scheduled` event. It will be invoked by the Workers runtime at a schedule you configured
```JavaScript
   addEventListener('scheduled', event => {
       event.waitUntil(sendMessage("Hello, World!"))
   })
```

4. You can trigger a scheduled event within the web editor. Your bot will send you a `Hello, World!` if everything is configured correctly
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1657918168165/YzzKXzbb2.png align="left")

Once you click `Save and Deploy`, the Worker will run on the schedule behind the scene.

Use the [Fetch API](https://developers.cloudflare.com/workers/runtime-apis/fetch/) from the Workers runtime to monitor interesting things on the internet. You can set up a stock alert, or send daily weather every day in the morning. The possibility is unlimited.

# Notes

1. Cron only has a 1-minute granularity. In other words, a Worker can only be triggered every minute at most.

 A workaround to this is to use `setTimeout` to schedule multiple events within a minute.

 For example, if you want to schedule a Worker to send a message every 30 seconds, start the Worker by sending a message, and do `setTimeout(sendMessage, 30000)` immediately after.

2. If a Worker is managed with [Wrangler](https://developers.cloudflare.com/workers/wrangler/get-started/), Cron Triggers should be exclusively managed through the [wrangler.toml](https://developers.cloudflare.com/workers/wrangler/configuration/) file.
