To replace the current long polling technique
just subscribe to the topic stream changed and notify when data.length > 0
(from notify request payload) and the date saved on some sort of storage file is not the same as data.started_at
(since there is no way to filter only stream goes online event)
This will increase notification reliability, introduces realtime capabilities and decrease the usage of GitHub Actions quota
But GH Actions as storage can no longer be used due to webhook callback constraint (Vercel Now, Netlify, MongoDB Stitch, Supabase Function & storage. And keeping state between serveless function invocations will be a problem. To solve this we can use the free tier of Upstash (Redis-as-a-service), or a Database-as-a-service like: mLab, FaunaDB cloud, Railway, PlanetScale, or even the free tier of Qovery to host the entire Nodejs app + using Redis as the main database.
Maybe we can use External events: repository_dispatch
(via GitHub API) to trigger the workflow run that will use an artifact to keep the state. See Async workflows with repository dispatch - GitHub Satellite 2020
GH Actions could be used to renew the webhook subscriptions since "All subscriptions have an expiration time, which cannot exceed 10 days."
Besides that, we'll can implement a notification for multiple Twitch channels and update the message sent by the bot as well 😃
Note that we're looking for a more dependecy-free and slim solution here to reduce the serverless cold start latency -- https://moiva.io to rescue!
The happy path workflow will be somewhat like this:
- Client: our temporary HTTP client just send a subscription request (besides the fact that subscriptions should be renew due to its expiration time)
- Helix API:
https://api.twitch.tv/helix
endpoint
- Twitch: the twitch webhook server
- Server: our serverless function that will be used as webhook (
hub.callback
X
value in 1, following this spec)
TODO to close this issue
Example of incoming request from Twitch (step 5):
req url = '/'
req method = 'POST'
req headers = {
host: 'c56b8fe5.ngrok.io',
'user-agent': 'Go-http-client/1.1',
connection: 'close',
'content-length': '559',
'content-type': 'application/json; charset=utf-8',
link: '<https://api.twitch.tv/helix/webhooks/hub>; rel="hub", <https://api.twitch.tv/helix/streams?user_id=433615460>; rel="self"',
'twitch-notification-id': '88429811-567d-4cfa-85a3-b37b88abe65f',
'twitch-notification-retry': '0',
'twitch-notification-timestamp': '2020-05-02T20:03:23Z',
'x-hub-signature': 'sha256=XYZABC',
'accept-encoding': 'gzip',
'x-forwarded-for': '34.218.218.240'
}
{
data: [
{
game_id: '509670',
id: '1438466417',
language: 'pt',
started_at: '2020-05-02T20:00:06Z',
tag_ids: [Array],
thumbnail_url: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_codigofalado-{width}x{height}.jpg',
title: '[BR] Criando um Timer com Vue.js + Novos MEMEs no Canal',
type: 'live',
user_id: '433615460',
user_name: 'CodigoFalado',
viewer_count: 57
}
]
}