A to Z Guide
How this project works, from data collection to GitHub Pages.
This page documents the project architecture, scripts, workflows, data files, testing helpers, and deployment path so anyone opening the repository can understand the full system quickly.
Overview
What this project does
The project tracks free game promotions from Epic Games and Steam, stores structured JSON snapshots, sends notifications through email, Telegram, Discord, and WhatsApp when new offers appear, updates the README automatically, and exposes the latest offers through this GitHub Pages site.
System Flow
End-to-end flow
`epic.PY` calls Epic's promotion endpoint and `steam.py` gathers Steam deals from web/API sources.
Each script converts the results into predictable JSON records with title, link, image, type, and timing fields.
A signature is built from the offer list, then the scripts check whether any fetched offer is new compared with the saved JSON state.
The latest state is saved into `free.json` and `free-steam.json`; expired or removed offers update state silently without sending notifications.
The scripts deliver channel-specific messages for email, Telegram, Discord, and WhatsApp, including image-based WhatsApp updates when artwork is available.
`generate_readme.py` refreshes the README while GitHub Pages serves the JSON-backed website, `start.py` runs normal local checks, and `test_runner.py` runs a clean-state test.
Repository
Main files
Data
JSON structure
The site expects these repository files:
free.json
{
"signature": "...",
"updated_at": "...",
"current_games": [{ "title": "", "link": "", "image": "", "start": "", "end": "" }],
"upcoming_games": [{ "title": "", "link": "", "image": "", "start": "", "end": "" }]
}
free-steam.json
{
"signature": "...",
"updated_at": "...",
"games": [{ "type": "", "title": "", "link": "", "image": "", "time": "" }]
}
If an offer expires or disappears, the notifier saves the new JSON state without sending alerts. Alerts are sent only when at least one fetched offer is new compared with the saved snapshot.
Delivery
Notification channels
The project can notify through email, Telegram, Discord, and WhatsApp. Each channel can be enabled or disabled
independently inside config.json.
{
"secrets": {
"use_hardcoded_secrets": true,
"secrets_file": "secrets.json"
},
"notifications": {
"email": false,
"telegram": false,
"discord": false,
"whatsapp": true
}
}
Email, Telegram, Discord, and WhatsApp all support multiple targets separated by commas. Email supports up to
30 recipients per run, for example first@example.com,second@example.com. Telegram and
Discord support comma-separated chat or channel IDs like -1003918180986,1845799450 and
123456789012345678,987654321098765432. WhatsApp recipients use international numbers such as
919989148967,14155552671.
{
"email": {
"email": "you@gmail.com",
"password": "your-app-password",
"to_email": "first@example.com,second@example.com,third@example.com"
},
"telegram": {
"bot_token": "123456:telegram-bot-token",
"chat_id": "-1003918180986,1845799450"
},
"discord": {
"bot_token": "YOUR_DISCORD_BOT_TOKEN",
"channel_id": "123456789012345678,987654321098765432"
},
"whatsapp": {
"access_token": "EAAG...",
"phone_number_id": "9123242999999",
"to": "919999999999,919999999999",
"api_version": "v25.0"
}
}
WhatsApp currently sends one summary text followed by one message per game. If a game includes artwork, the notifier sends an image message with a caption and store link. If no image is available, it falls back to plain text with a tappable URL preview.
GitHub Actions may block or interfere with WhatsApp API requests in some environments, so WhatsApp notifications are best run locally or from a VPS.
Automation
GitHub Actions
The main workflow runs every 6 hours and can also be triggered manually. It installs dependencies, runs both fetcher scripts, regenerates the README, and commits updated JSON snapshots.
The tester workflow is manual only. It runs delete_state_json.py first, then runs the Epic and Steam notifiers. Use it when you intentionally want to test behavior from a clean JSON state.
GitHub Actions remains useful for scraping, state updates, and publishing docs, but WhatsApp delivery is more reliable when run locally or on a VPS.
Deployment
GitHub Pages setup
The public entry lives at the repository root in index.html, while shared site assets and
the documentation page live in the SITE/ folder. This keeps GitHub Pages happy while still
grouping the website files cleanly.
Setup
How to run locally
pip install requests beautifulsoup4
$env:WHATSAPP_ACCESS_TOKEN="EAAG..."
$env:WHATSAPP_PHONE_NUMBER_ID="1126873913833051"
$env:WHATSAPP_TO="919999999999"
$env:WHATSAPP_API_VERSION="v25.0"
python start.py
python test_runner.py
python generate_readme.py
For local runs, you can either set environment variables like the example above or keep
use_hardcoded_secrets enabled and place the same values in secrets.json.
Use start.py for a normal run and test_runner.py only when you want to delete saved JSON state first.
Extend
How to grow the project
You can add more storefronts by following the same pattern: fetch data, normalize it into JSON, generate a signature, save a state file, and teach the site how to render the new data source.