From 9c9db344df1b4c4f8bef199a7053041812b7649d Mon Sep 17 00:00:00 2001 From: MisterSoandSo Date: Sun, 12 Apr 2026 21:29:33 -0700 Subject: [PATCH] Clean up README.md and requirements.txt --- README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | Bin 0 -> 92 bytes 2 files changed, 115 insertions(+) create mode 100644 requirements.txt diff --git a/README.md b/README.md index dd167cd..0237609 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,117 @@ # Voter-Uptime-Bot + +A Discord bot that monitors the availability of web services and reports uptime statistics directly in your server. Built with `discord.py`, `aiohttp`, and `pydantic-settings`, it goes beyond simple HTTP checks — detecting Cloudflare intercept pages and validating real page content so you know your sites are genuinely reachable, not just returning a 200. + +--- + +## Features + +- **Periodic polling** — checks all configured sites every 15 minutes +- **Cloudflare intercept detection** — identifies challenge/block pages that return HTTP 200 but serve no real content +- **Keyword content validation** — confirms expected strings are present on the loaded page +- **Retry logic** — re-attempts checks on transient CF intercepts before marking a site degraded +- **Uptime history** — stores all check results in a local SQLite database +- **Discord slash commands** — view live status, 24-hour bars, and monthly summaries per site + +--- + +## Commands + +| Command | Description | +|---|---| +| `/uptime now` | Current status of all monitored sites | +| `/uptime day ` | 24-hour bar chart (🟩🟨🟥) with uptime % | +| `/uptime month ` | Current month summary, one square per day | +| `/uptime summarize` | Monthly uptime % for all sites at once | + +--- + +## Project Structure + +``` +app/ +├── __init__.py +├── bot.py # Discord client, slash commands, polling task +├── checker.py # SiteChecker — HTTP, CF detection, keyword validation +├── config.py # Pydantic Settings — loads all config from .env +├── db.py # SQLite init, insert, and fetch helpers +└── utils.py # check_site wrapper, bar rendering, uptime maths +``` + +--- + +## Configuration + +All configuration is managed via a `.env` file using `pydantic-settings`. Copy `.env.example` to `.env` and fill in your values. + +```env +DISCORD_SECRET_KEY=your-bot-token-here +DISCORD_CLIENT_ID=123456789 +DATABASE_PATH=uptime.db + +MONITORED_SITES='[ + { + "name": "MySite", + "url": "https://example.com", + "timeout_seconds": 10, + "expected_keywords": ["Login", "Vote"], + "max_retries": 1 + } +]' +``` + +### Site config fields + +| Field | Required | Default | Description | +|---|---|---|---| +| `name` | ✅ | — | Display name used in Discord | +| `url` | ✅ | — | Full URL to check | +| `timeout_seconds` | | `10` | Request timeout | +| `expected_status` | | `200` | Expected HTTP status code | +| `expected_keywords` | | `[]` | Strings that must appear in the page body | +| `max_retries` | | `1` | Extra attempts on CF intercept before marking degraded | + +--- + +## How Checks Work + +Each poll goes through three layers: + +1. **HTTP status** — non-2xx/3xx responses are marked degraded or down +2. **Cloudflare detection** — response body is scanned for CF challenge fingerprints; a match is marked `degraded` even if status was 200 +3. **Keyword validation** — any `expected_keywords` that are missing from the body mark the site `degraded` + +Results are stored with a `detection_reason` (`cf_intercept`, `missing_keywords`, `http_503`, `timeout`, etc.) so you can query historical failure causes. + +--- + +## Result States + +| State | Emoji | Meaning | +|---|---|---| +| `up` | 🟩 | HTTP OK, no CF intercept, all keywords present, latency < 3s | +| `degraded` | 🟨 | Reachable but CF intercept, missing content, slow, or 5xx | +| `down` | 🟥 | Timeout, connection failure, SSL error, or unexpected status | + +--- + +## Installation + +```bash +pip install -r requirements.txt +``` + +Run the bot: + +```bash +python -m app.bot +``` + +--- + +## Requirements + +- Python 3.11+ +- A Discord bot token with the `applications.commands` scope and `bot` scope enabled +- The bot must be invited to your server with slash command permissions \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..a656118a2378c275907bcdec30a9821a79e2858b GIT binary patch literal 92 zcmezWFOeaWA)g_Gp#%sE7D#SF