diff --git a/.env.example b/.env.example index 7190076..473ebbe 100644 --- a/.env.example +++ b/.env.example @@ -11,26 +11,29 @@ REDDIT_USERNAME=YOUR_USERNAME_HERE REDDIT_PASSWORD=YOUR_PASSWORD_HERE # Which subreddit to post to -SUBREDDIT=YOUR_SUBREDDIT_HERE +REDDIT_SUBREDDIT=YOUR_SUBREDDIT_HERE # Optional: customize the user agent # REDDIT_USER_AGENT=MinecraftUpdateBot/1.0 # Optional: what types of releases to check for # Options: release, snapshot, old_beta, old_alpha -# Multiple: RELEASE_TYPES=release,snapshot -RELEASE_TYPES=release +# Multiple: REDDIT_RELEASE_TYPES=release,snapshot +REDDIT_RELEASE_TYPES=release,snapshot -# Optional: Check for Bedrock Edition releases (Windows) +# Optional: Check for Bedrock Edition releases # true to enable, false to disable -CHECK_BEDROCK=false +REDDIT_CHECK_BEDROCK=true # Optional: how often to check for updates (in seconds) # Default: 3600 (1 hour) # For testing: 600 (10 minutes) -CHECK_INTERVAL=3600 +REDDIT_CHECK_INTERVAL=3600 # Wiki Configuration -# Post titles and bodies are loaded from the subreddit wiki page "minecraft_update_bot" -# Format: YAML with release_type sections containing title and body +# Name of the wiki page to load post templates from +# Default: minecraft_update_bot +REDDIT_WIKI_PAGE_NAME=minecraft_update_bot + +# Wiki Format: YAML with release_type sections containing title and body # Example: See WIKI_CONFIG.md for complete documentation diff --git a/DOCKER.md b/DOCKER.md index 5dc5633..f31ad66 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -1,6 +1,4 @@ -# Running with Docker Compose - -This project includes Docker and Docker Compose configuration for easy deployment. +# Docker Deployment Guide ## Prerequisites @@ -9,145 +7,244 @@ This project includes Docker and Docker Compose configuration for easy deploymen ## Quick Start -### 1. Copy Environment File +1. Copy environment template: + ```bash + copy .env.example .env + ``` -```bash -copy .env.example .env -``` +2. Edit `.env` with your Reddit credentials: + ```env + REDDIT_CLIENT_ID=your_client_id + REDDIT_CLIENT_SECRET=your_client_secret + REDDIT_USERNAME=your_username + REDDIT_PASSWORD=your_password + SUBREDDIT=your_subreddit + ``` -### 2. Edit .env +3. Start the bot: + ```bash + docker-compose up -d + ``` -Open `.env` and fill in your Reddit credentials: +4. Verify it's running: + ```bash + docker-compose ps + ``` + +5. View logs: + ```bash + docker-compose logs -f + ``` + +## Environment Variables + +Required variables (in `.env`): +- REDDIT_CLIENT_ID - OAuth client ID from Reddit app +- REDDIT_CLIENT_SECRET - OAuth client secret +- REDDIT_USERNAME - Your Reddit account username +- REDDIT_PASSWORD - Your Reddit account password +- SUBREDDIT - Target subreddit name + +Optional variables: +- REDDIT_RELEASE_TYPES - Comma-separated types (default: release) + - Examples: "release", "release,snapshot" +- REDDIT_CHECK_BEDROCK - Enable Bedrock Edition detection (default: false) + - Set to "true" or "false" +- REDDIT_CHECK_INTERVAL - Seconds between checks (default: 3600) + - Example: 600 for 10-minute checks +- REDDIT_WIKI_PAGE_NAME - Post template wiki page name (default: minecraft_update_bot) +- REDDIT_USER_AGENT - API user agent (default: MinecraftUpdateBot/1.0) + +## Configuration File + +Edit `.env` to control all behavior. Example with all options: ```env -REDDIT_CLIENT_ID=your_client_id -REDDIT_CLIENT_SECRET=your_client_secret -REDDIT_USERNAME=your_username -REDDIT_PASSWORD=your_password -SUBREDDIT=your_subreddit +REDDIT_CLIENT_ID=abc123 +REDDIT_CLIENT_SECRET=xyz789 +REDDIT_USERNAME=mybot +REDDIT_PASSWORD=botpass +SUBREDDIT=mysubreddit +REDDIT_RELEASE_TYPES=release,snapshot +REDDIT_CHECK_BEDROCK=true +REDDIT_CHECK_INTERVAL=3600 +REDDIT_WIKI_PAGE_NAME=minecraft_update_bot +REDDIT_USER_AGENT=MinecraftUpdateBot/1.0 ``` -### 3. (Optional) Set Up Wiki Configuration - -Create a wiki page on your subreddit named `minecraft_update_bot` with your post templates in YAML format. This allows different posts for releases, snapshots, etc. - -See [WIKI_CONFIG.md](WIKI_CONFIG.md) for detailed instructions and examples. - -### 4. Start the Bot +## Container Management +Start the bot: ```bash docker-compose up -d ``` -This will: -- Build the Docker image -- Start the bot in a container -- Persist data in a Docker volume named `minecraft-bot-db` -- Auto-restart the container if it crashes - -### 5. View Logs - -```bash -# Watch logs in real-time -docker-compose logs -f - -# Or check status -docker-compose ps -``` - -### 5. Stop the Bot - +Stop the bot: ```bash docker-compose down ``` -## Configuration - -All configuration is done via the `.env` file. The following variables are available: - -| Variable | Required | Default | Description | -|----------|----------|---------|-------------| -| `REDDIT_CLIENT_ID` | ✓ | - | Your Reddit app client ID | -| `REDDIT_CLIENT_SECRET` | ✓ | - | Your Reddit app secret | -| `REDDIT_USERNAME` | ✓ | - | Your Reddit username | -| `REDDIT_PASSWORD` | ✓ | - | Your Reddit password | -| `SUBREDDIT` | ✓ | - | Subreddit to post to | -| `RELEASE_TYPES` | | `release` | Comma-separated: `release,snapshot` | -| `CHECK_BEDROCK` | | `false` | Enable Bedrock Edition detection: `true` or `false` | -| `CHECK_INTERVAL` | | `3600` | Seconds between checks | -| `REDDIT_USER_AGENT` | | `MinecraftUpdateBot/1.0` | API user agent | - -### Examples - -**Check for both releases and snapshots:** -```env -RELEASE_TYPES=release,snapshot -``` - -**Check every 10 minutes (for testing):** -```env -CHECK_INTERVAL=600 -``` - -## Data Persistence - -The bot's database (list of posted versions) is stored in a Docker volume called `minecraft-bot-db`. This persists between container restarts. - -To view the data: +Restart the bot: ```bash -docker volume inspect minecraft-bot-db +docker-compose restart ``` -To reset the database (post all versions again): -```bash -docker volume rm minecraft-bot-db -``` - -## Building - -To rebuild the image after code changes: - +Rebuild after code changes: ```bash docker-compose build --no-cache docker-compose up -d ``` +View logs: +```bash +docker-compose logs -f minecraftupdatebot +``` + +View specific log entries: +```bash +docker-compose logs minecraftupdatebot | grep "[BOT]" +``` + +## Data Persistence + +The bot's version database persists in a Docker volume named `minecraft-bot-db`. + +View volume details: +```bash +docker volume inspect minecraft-bot-db +``` + +The database file is located at `/app/DB/posted_versions.json` inside the container. + +Reset the database (allows reposting all versions): +```bash +docker-compose down +docker volume rm minecraft-bot-db +docker-compose up -d +``` + +Check database contents from host: +```bash +docker run --rm -v minecraft-bot-db:/data alpine cat /data/posted_versions.json +``` + +## Wiki Configuration + +The bot loads post templates from a subreddit wiki page (default name: minecraft_update_bot). + +Create the wiki page on your subreddit with YAML configuration: + +```yaml +release: + title: "Minecraft {version} Released" + body: | + New version available! + Version: {version} + Released: {release_date} + +snapshot: + title: "Minecraft {version} Snapshot" + body: | + Test build available + Released: {release_date} + +bedrock-windows: + title: "Bedrock Edition {version} Available" + body: | + Bedrock update available + Released: {release_date} +``` + +See WIKI_CONFIG.md for complete documentation. + +## Monitoring + +Check bot status: +```bash +docker-compose ps +``` + +Monitor logs in real-time: +```bash +docker-compose logs -f +``` + +Look for these status messages: +- [BOT] Successfully connected to Reddit +- [BOT] Started update checker +- [BOT] New Java release found +- [BOT] New Bedrock release found +- [BOT] Posted Minecraft + +For errors, look for: +- [BOT] Error messages +- [BEDROCK_CHECKER] Error messages +- [CHAT] Error messages + ## Troubleshooting -### Container won't start - +Container won't start: ```bash docker-compose logs ``` +Check for missing credentials or configuration errors. -Check for configuration errors or missing credentials. +Reddit authentication fails: +- Verify credentials in .env are correct +- Check Reddit app still exists at https://www.reddit.com/prefs/apps +- Ensure the bot account has permission to post to the subreddit -### Reddit authentication error +No posts being made: +1. Check logs: `docker-compose logs -f` +2. Verify subreddit name in REDDIT_SUBREDDIT env var +3. Check database: `docker run --rm -v minecraft-bot-db:/data alpine cat /data/posted_versions.json` +4. Verify wiki configuration loaded: Look for "[WIKI_CONFIG] Loaded" in logs -- Verify your credentials in `.env` -- Check that your Reddit app still exists at https://www.reddit.com/prefs/apps -- Make sure your account can post to the subreddit +Bedrock detection not working: +- Ensure REDDIT_CHECK_BEDROCK is set to "true" in .env +- Check logs for minecraft.wiki scraping errors +- Bedrock detection requires internet access to minecraft.wiki -### No posts being made +Chat commands not working: +- Only subreddit moderators can send commands +- Send messages containing "reload-config" or "repost-latest" +- Check logs for [CHAT] messages -- Check the logs: `docker-compose logs -f` -- Verify the subreddit name in `.env` -- Check `docker exec minecraft-bot cat /app/DB/posted_versions.json` to see what's been posted +## Network Access -## Advanced Options +The bot requires: +- Reddit API connectivity (PRAW library) +- Minecraft launcher manifest (launchermeta.mojang.com) +- minecraft.wiki (for Bedrock detection if enabled) +- Update server (updts.slfhstd.uk for bot version checking) -### Custom Post Template +If behind a proxy, configure Docker networking accordingly. -Mount your config file to customize the post format: +## Performance -Edit `docker-compose.yml`: -```yaml -volumes: - - minecraft-bot-db:/app/DB - - ./config.py:/app/config.py # Uncomment this line +Default settings: +- Checks every 3600 seconds (1 hour) +- Allows 86400 seconds (24 hours) between update notifications +- Wiki config refreshes on each check (cached for 5 minutes) + +For testing with faster checks: +```env +REDDIT_CHECK_INTERVAL=300 ``` -Then edit `config.py` locally to customize `POST_TEMPLATE`. +For production (less frequent): +```env +REDDIT_CHECK_INTERVAL=7200 +``` + +## Security + +Best practices: +- Never commit .env file with real credentials to version control +- .env is listed in .gitignore by default +- Use Reddit app credentials, not your personal account password if possible +- Restrict subreddit moderator permissions for bot accounts +- Review logs regularly for unauthorized access attempts ### Resource Limits diff --git a/Dockerfile b/Dockerfile index bebeeff..938484a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.11-slim WORKDIR /app -# Install dependencies +# Install Python dependencies COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt @@ -11,6 +11,6 @@ COPY . . # Create DB directory RUN mkdir -p DB - +ENV PYTHONUNBUFFERED=1 # Run the bot CMD ["python", "main.py"] diff --git a/QUICKSTART.md b/QUICKSTART.md index 3c5c0e1..e36937a 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,65 +1,175 @@ # Quick Start Guide -## 1️⃣ Installation +## Installation + +### Docker (Recommended) + +1. Copy environment template: + ```bash + copy .env.example .env + ``` + +2. Edit `.env` with credentials: + ``` + REDDIT_CLIENT_ID=your_client_id + REDDIT_CLIENT_SECRET=your_client_secret + REDDIT_USERNAME=your_username + REDDIT_PASSWORD=your_password + SUBREDDIT=your_subreddit + ``` + +3. Start the bot: + ```bash + docker-compose up -d + ``` + +4. Check logs: + ```bash + docker-compose logs -f + ``` + +### Manual Installation + +1. Install dependencies: + ```bash + pip install -r requirements.txt + ``` + +2. Create Reddit app at https://www.reddit.com/prefs/apps (select "Script" type) + +3. Set environment variables: + ```bash + set REDDIT_CLIENT_ID=your_client_id + set REDDIT_CLIENT_SECRET=your_client_secret + set REDDIT_USERNAME=your_username + set REDDIT_PASSWORD=your_password + set SUBREDDIT=your_subreddit + ``` + +4. Run the bot: + ```bash + python main.py + ``` + +## Configuration + +Required env vars: +- REDDIT_CLIENT_ID +- REDDIT_CLIENT_SECRET +- REDDIT_USERNAME +- REDDIT_PASSWORD +- SUBREDDIT + +Optional env vars: +- REDDIT_RELEASE_TYPES (default: release) + - Examples: "release", "release,snapshot" +- REDDIT_CHECK_BEDROCK (default: false) + - Set to "true" to enable Bedrock Edition detection +- REDDIT_CHECK_INTERVAL (default: 3600) + - Number of seconds between version checks +- REDDIT_WIKI_PAGE_NAME (default: minecraft_update_bot) + - Wiki page name for post templates + +## Wiki Configuration + +Create a wiki page named minecraft_update_bot on your subreddit with YAML content: + +```yaml +release: + title: "Minecraft {version} Released" + body: | + New version available! + **Version:** {version} + **Released:** {release_date} + +snapshot: + title: "Minecraft {version} Snapshot" + body: | + New snapshot available for testing! + **Version:** {version} + **Released:** {release_date} +``` + +Placeholders: {version}, {release_date}, {type} + +See WIKI_CONFIG.md for complete examples. + +## Testing + +### Manual Version Checker Test + ```bash -cd d:\Git Repos\MinecraftUpdates -pip install -r requirements.txt +python -c "from minecraft_checker import get_latest_releases; import json; print(json.dumps(get_latest_releases(['release']), indent=2))" ``` -## 2️⃣ Reddit Setup -1. Go to https://www.reddit.com/prefs/apps -2. Click "Create an app" (type: Script) -3. Get your credentials: Client ID, Client Secret +### Bedrock Checker Test -## 3️⃣ Configure -Edit `config.py`: -```python -REDDIT_CLIENT_ID = "your_client_id" -REDDIT_CLIENT_SECRET = "your_client_secret" -REDDIT_USERNAME = "your_username" -REDDIT_PASSWORD = "your_password" -SUBREDDIT = "your_subreddit" +```bash +python -c "from bedrock_checker import get_latest_bedrock_release; import json; result = get_latest_bedrock_release(); print(json.dumps(result, indent=2))" ``` -## 4️⃣ Test +### Full Configuration Test + ```bash python test_setup.py ``` -Should show: -- ✓ Configuration checked -- ✓ Minecraft API working -- ✓ Reddit connection working +Expected output: +- Configuration loaded successfully +- Minecraft API reachable +- Reddit connection working +- Wiki configuration loaded -## 5️⃣ Run +## Moderator Commands + +Send these messages via Reddit chat to control the bot: + +**reload-config** +- Reloads wiki configuration without restarting +- Usage: Send a chat message containing "reload-config" + +**repost-latest** +- Manually repost latest versions (bypasses duplicate check) +- Usage: Send a chat message containing "repost-latest" + +Note: Only subreddit moderators can use these commands. + +## File Overview + +- main.py - Bot orchestration and command handler +- config.py - Configuration loader +- minecraft_checker.py - Java Edition version checker +- bedrock_checker.py - Bedrock Edition version checker +- wiki_config.py - Wiki configuration manager +- update_checker.py - Bot update checker +- requirements.txt - Python dependencies +- Dockerfile - Container image +- docker-compose.yml - Docker composition +- DB/ - Version tracking database + +## Logs + +Docker: ```bash -python main.py +docker-compose logs -f ``` -See posts appear in your subreddit automatically! - ---- - -## Optional Config Changes - -### Check for Snapshots Too -```python -RELEASE_TYPES = ["release", "snapshot"] +Manual: +``` +Watch console output for [BOT], [CHAT], [BEDROCK_CHECKER] messages ``` -### Check More Frequently (testing) -```python -CHECK_INTERVAL = 600 # 10 minutes instead of 1 hour -``` +## Common Issues -### Customize Post Format -Edit the `POST_TEMPLATE` in `config.py` - it uses `{version}` and `{release_date}` placeholders. +No posts appearing: +- Check logs for errors +- Verify subreddit name in REDDIT_SUBREDDIT +- Check DB/posted_versions.json for version tracking ---- +Bot not detecting Bedrock: +- Ensure REDDIT_CHECK_BEDROCK is set to true +- Check bedrock_checker logs for wiki scraping errors -## Files Overview -- `main.py` - The bot itself -- `config.py` - Settings (edit this!) -- `minecraft_checker.py` - Fetches Minecraft version data -- `test_setup.py` - Tests your configuration -- `DB/` - Stores tracking of posted versions (auto-created) +Wiki config not loading: +- Verify wiki page name is exactly "minecraft_update_bot" +- Ensure YAML syntax is valid diff --git a/README.md b/README.md index 060f2dd..2e0d98c 100644 --- a/README.md +++ b/README.md @@ -1,152 +1,195 @@ -# Minecraft Update Bot 🎮 +# Minecraft Update Bot -Automatically detects new Minecraft releases and posts them to a subreddit. +Version 1.0.0 - Automatically detects new Minecraft releases (Java and Bedrock editions) and posts announcements to a subreddit. ## Features -- ✅ Checks Minecraft launcher manifest for new releases -- ✅ Posts to Reddit whenever a new version is detected -- ✅ Tracks posted versions to avoid duplicates -- ✅ Runs continuously with configurable check interval -- ✅ Supports multiple release types (releases, snapshots, etc.) -- ✅ **Bedrock Edition support** - Detects Windows Bedrock releases -- ✅ Docker & Docker Compose ready -- ✅ **Customizable post templates via subreddit wiki** -- ✅ **Different post formats for different release types** -- ✅ **Auto-update notifications** - Gets alerted when new bot versions are available +Core functionality: +- Polls the official Minecraft launcher manifest for new Java Edition releases +- Detects Minecraft Bedrock Edition updates via minecraft.wiki scraping +- Posts new releases to a configured subreddit automatically +- Maintains a database of posted versions to prevent duplicate posts +- Supports multiple release types (releases, snapshots, beta versions) +- Configurable check interval for polling -## Quick Start - Docker (Recommended) +Advanced features: +- Customizable post templates via subreddit wiki configuration +- Different post formats for different release types +- Moderator chat commands for config reload and manual reposting +- Automatic bot update notifications via modmail +- Docker and Docker Compose deployment ready +- Persistent version tracking across container restarts -```bash -# Copy and edit environment file -copy .env.example .env -# Edit .env with your Reddit credentials +## Quick Start -# Start the bot -docker-compose up -d +### Docker (Recommended) -# View logs -docker-compose logs -f -``` +1. Copy the environment template: + ```bash + copy .env.example .env + ``` + +2. Edit `.env` with your Reddit credentials: + ``` + REDDIT_CLIENT_ID=your_id + REDDIT_CLIENT_SECRET=your_secret + REDDIT_USERNAME=your_username + REDDIT_PASSWORD=your_password + SUBREDDIT=your_subreddit + ``` + +3. Start the bot: + ```bash + docker-compose up -d + ``` + +4. View logs: + ```bash + docker-compose logs -f + ``` See [DOCKER.md](DOCKER.md) for detailed Docker setup instructions. -## Customizing Posts with Wiki Configuration +### Manual Setup -The bot loads post templates from your subreddit's wiki page `minecraft_update_bot`. This allows you to: -- Create different post formats for releases vs. snapshots -- Customize titles and bodies without restarting -- Support legacy version types with custom messages +1. Install dependencies: + ```bash + pip install -r requirements.txt + ``` -**Quick Setup:** -1. Create a wiki page named `minecraft_update_bot` on your subreddit -2. Add YAML configuration with your templates (see example below) -3. Bot auto-loads every 30 minutes +2. Create a Reddit application at https://www.reddit.com/prefs/apps (select "Script" type) + +3. Configure environment variables or edit config.py: + ```bash + set REDDIT_CLIENT_ID=your_client_id + set REDDIT_CLIENT_SECRET=your_client_secret + set REDDIT_USERNAME=your_username + set REDDIT_PASSWORD=your_password + set SUBREDDIT=your_subreddit + python main.py + ``` + +## Configuration + +### Environment Variables + +Required variables: +- REDDIT_CLIENT_ID - Your Reddit OAuth app client ID +- REDDIT_CLIENT_SECRET - Your Reddit OAuth app secret +- REDDIT_USERNAME - Reddit account username +- REDDIT_PASSWORD - Reddit account password +- SUBREDDIT - Target subreddit name + +Optional variables: +- REDDIT_RELEASE_TYPES - Comma-separated types: release,snapshot (default: release) +- REDDIT_CHECK_BEDROCK - Enable Bedrock detection: true or false (default: false) +- REDDIT_CHECK_INTERVAL - Seconds between checks (default: 3600) +- REDDIT_WIKI_PAGE_NAME - Wiki page for post templates (default: minecraft_update_bot) +- REDDIT_USER_AGENT - API user agent string (default: MinecraftUpdateBot/1.0) + +### Wiki Configuration + +Post templates are defined in a subreddit wiki page (default name: minecraft_update_bot). + +Create entries for each release type with title and body templates: -**Simple Example:** ```yaml release: - title: "Minecraft {version} Released!" + title: "Minecraft {version} Released" body: | - # Minecraft {version} - Available now! Get it at [minecraft.net](https://minecraft.net) - **Released:** {release_date} + New version available at minecraft.net + Released: {release_date} snapshot: title: "Minecraft {version} Snapshot" body: | - # New Snapshot Available - Test {version} before the official release! + Test build available in launcher + Released: {release_date} + +bedrock-windows: + title: "Bedrock Edition {version} Available" + body: | + Download from Microsoft Store + Released: {release_date} ``` -👉 See [WIKI_CONFIG.md](WIKI_CONFIG.md) for complete setup and examples. +Available placeholders: {version}, {release_date}, {type} + +See [WIKI_CONFIG.md](WIKI_CONFIG.md) for complete wiki configuration details. + +## Moderator Chat Commands + +Moderators can control the bot via Reddit chat messages: + +**reload-config** +- Reloads wiki configuration without restarting the bot +- Usage: Send a chat message containing "reload-config" +- Response: Bot replies with success or failure status + +**repost-latest** +- Reposts the latest releases (bypasses duplicate check) +- Usage: Send a chat message containing "repost-latest" +- Response: Bot replies with number of versions reposted ## Bedrock Edition Support -The bot can track **Minecraft Bedrock Edition (Windows)** releases in addition to Java Edition. +The bot can track Minecraft Bedrock Edition (Windows) releases by scraping the official minecraft.wiki version history page. -**To enable Bedrock tracking:** - -1. **With Docker:** Add to your `.env` file: - ``` - CHECK_BEDROCK=true - ``` - -2. **Manual:** Set environment variable before running: - ```bash - set CHECK_BEDROCK=true - python main.py - ``` - -3. **Configure Bedrock posts** in your wiki page (optional): - ```yaml - bedrock-windows: - title: "Minecraft Bedrock {version} Available (Windows)" - body: | - # Bedrock Edition {version} - Download from the Microsoft Store - **Released:** {release_date} - ``` - -The bot will now check for both Java and Bedrock releases every cycle, posting about each separately. - -## Manual Setup - -### 1. Install Dependencies - -```bash -pip install -r requirements.txt +Enable with Docker: +```env +REDDIT_CHECK_BEDROCK=true ``` -### 2. Create Reddit Application - -1. Go to [https://www.reddit.com/prefs/apps](https://www.reddit.com/prefs/apps) -2. Click "Create an app" or "Create another app" -3. Fill in the form: - - **Name:** MinecraftUpdateBot - - **App type:** Script - - **Redirect URI:** http://localhost:8080 -4. Copy the credentials - -### 3. Configure the Bot - -Edit `config.py` and fill in your credentials: - -```python -REDDIT_CLIENT_ID = "YOUR_CLIENT_ID" # From app page -REDDIT_CLIENT_SECRET = "YOUR_CLIENT_SECRET" # From app page -REDDIT_USERNAME = "YOUR_USERNAME" # Your Reddit username -REDDIT_PASSWORD = "YOUR_PASSWORD" # Your Reddit password -SUBREDDIT = "YOUR_SUBREDDIT" # Subreddit to post to -``` - -Or use environment variables (Docker-friendly): - +Or environment variable: ```bash -set REDDIT_CLIENT_ID=your_client_id -set REDDIT_CLIENT_SECRET=your_client_secret -set REDDIT_USERNAME=your_username -set REDDIT_PASSWORD=your_password -set SUBREDDIT=your_subreddit +set REDDIT_CHECK_BEDROCK=true python main.py ``` -### 4. Customize (Optional) +Note: Bedrock versions use the new format (26.x, 27.x, etc.) and are detected from the wiki page. Java Edition will eventually use the same versioning scheme. -In `config.py`: -- **RELEASE_TYPES:** Change `["release"]` to include snapshots or other types - - Options: `"release"`, `"snapshot"`, `"old_beta"`, `"old_alpha"` -- **CHECK_INTERVAL:** How often to check for updates (in seconds) - - Default: 3600 (1 hour) -- **POST_TEMPLATE:** Customize the post format +## Release Types -Examples: -```python -# Check for both releases and snapshots -RELEASE_TYPES = ["release", "snapshot"] +Supported Java Edition release types: +- release - Final Java Edition releases +- snapshot - Development snapshots +- old_beta - Legacy beta versions +- old_alpha - Legacy alpha versions -# Check every 30 minutes -CHECK_INTERVAL = 1800 +Supported Bedrock Edition types: +- bedrock-windows - Windows Bedrock releases + +## Database and Persistence + +Posted versions are tracked in DB/posted_versions.json. This prevents duplicate posts when the bot restarts. + +With Docker, data persists in a named volume (minecraft-bot-db). + +To reset the database and repost all versions: +- Docker: `docker volume rm minecraft-bot-db` then restart +- Manual: Delete DB/posted_versions.json + +## Logs + +Docker logs: +```bash +docker-compose logs -f +``` + +Watch for status messages with [BOT], [CHAT], [BEDROCK_CHECKER] prefixes. + +## Files Overview + +- main.py - Bot orchestration and update checking +- config.py - Configuration loader +- minecraft_checker.py - Java Edition version checker +- bedrock_checker.py - Bedrock Edition version checker via wiki scraping +- wiki_config.py - Wiki page configuration manager +- update_checker.py - Bot update notifications +- requirements.txt - Python dependencies +- Dockerfile - Container image definition +- docker-compose.yml - Docker Compose configuration +- DB/ - Version tracking database (auto-created) # Check every 10 minutes (for testing) CHECK_INTERVAL = 600 diff --git a/WIKI_CONFIG.md b/WIKI_CONFIG.md index cb8c6be..170600d 100644 --- a/WIKI_CONFIG.md +++ b/WIKI_CONFIG.md @@ -1,202 +1,296 @@ -# Wiki Configuration Setup +# Wiki Configuration Guide -The Minecraft Update Bot uses a subreddit wiki page to store customizable post templates. This allows you to configure different post formats for different release types (releases, snapshots, etc.) without restarting the bot. +The Minecraft Update Bot uses a subreddit wiki page to manage customizable post templates. This allows different post formats for different release types without restarting the bot. ## Quick Setup -1. **Create the wiki page on your subreddit** - - Go to your subreddit settings - - Navigate to "Edit wiki page" - - Create a new page named `minecraft_update_bot` +1. Go to your subreddit settings and edit wiki pages +2. Create a new page named "minecraft_update_bot" +3. Add YAML configuration for your post templates +4. Bot loads the configuration automatically -2. **Add the configuration in YAML format** +The wiki page name can be customized via the REDDIT_WIKI_PAGE_NAME environment variable. -Copy and paste the following into your wiki page: +## Configuration Format + +The wiki page must contain valid YAML with this structure: + +```yaml +release_type: + title: "Post title with placeholders" + body: | + Post body content + with {placeholders} +``` + +## Available Placeholders + +Both title and body can use these placeholders: +- {version} - The release version number (e.g., "1.21", "26.3") +- {release_date} - Formatted release date (e.g., "June 13, 2024") +- {type} - The release type (e.g., "release", "snapshot") + +## Release Types + +Create configuration sections for these release types: + +Java Edition: +- release - Final Java Edition releases +- snapshot - Development snapshots +- old_beta - Legacy beta versions +- old_alpha - Legacy alpha versions + +Bedrock Edition: +- bedrock-windows - Bedrock Edition + +Special: +- default - Fallback for unconfigured types + +## Example Configurations + +### Basic Setup (Releases Only) ```yaml release: - title: "Minecraft {version} Released!" + title: "Minecraft {version} is Available" body: | - # Minecraft {version} Released + A new version of Minecraft Java Edition is available! - A new version of Minecraft Java Edition is now available! + Version: {version} + Released: {release_date} - **Version:** {version} - **Released:** {release_date} + Download from minecraft.net or use the Minecraft launcher. +``` + +### Multiple Release Types + +```yaml +release: + title: "Minecraft {version} Released" + body: | + # Minecraft {version} - Download it from [minecraft.net](https://minecraft.net) or use the Minecraft launcher. + A new release is available! + + Version: {version} + Released: {release_date} + + Download: https://minecraft.net snapshot: - title: "Minecraft {version} Snapshot Available" + title: "Minecraft {version} Snapshot" body: | # Minecraft {version} Snapshot - A new snapshot is available for testing! + A new development snapshot is available for testing. - **Version:** {version} - **Released:** {release_date} + Version: {version} + Released: {release_date} - Try it in the launcher with the development profiles. + Enable snapshots in your launcher preferences. bedrock-windows: - title: "Minecraft Bedrock Edition {version} Available (Windows)" + title: "Bedrock Edition {version} Available" body: | # Minecraft Bedrock Edition {version} - A new version is available for Windows! + A new Bedrock Edition update is available for Windows. - **Version:** {version} - **Released:** {release_date} + Version: {version} + Released: {release_date} - Download from the Microsoft Store or via the Minecraft Launcher. + Download from the Microsoft Store or through the Minecraft Launcher. + +old_beta: + title: "Minecraft Beta {version} Archive" + body: | + Version {version} is now archived. + Released: {release_date} + +old_alpha: + title: "Minecraft Alpha {version} Archive" + body: | + Version {version} is now archived. + Released: {release_date} default: title: "Minecraft {version} ({type})" body: | - # Minecraft {version} - - A new {type} build has been released! - - **Version:** {version} - **Released:** {release_date} -``` - -3. **Save the wiki page** - - The bot will automatically load this config on startup - - Changes to the wiki are refreshed every 30 minutes - -## Configuration Format - -The wiki page must be valid YAML with this structure: - -```yaml -release_type: - title: "Post title with {placeholders}" - body: | - Multi-line post body - with {placeholders} -``` - -### Available Placeholders - -In both title and body, you can use: -- `{version}` - The Minecraft version (e.g., "1.21") -- `{release_date}` - The formatted release date (e.g., "June 13, 2024") -- `{type}` - The release type (e.g., "release", "snapshot") - -### Release Types - -Create sections for each release type you want custom posts for: -- `release` - Java Edition final releases -- `snapshot` - Java Edition snapshots -- `old_beta` - Java Edition old beta versions -- `old_alpha` - Java Edition old alpha versions -- `bedrock-windows` - Bedrock Edition (Windows) -- `default` - Fallback for any unconfigured type - -## Examples - -### Example 1: Simple Setup (Releases Only) - -```yaml -release: - title: "Minecraft {version} is Out!" - body: | - {version} is available now! - Get it at minecraft.net -``` - -### Example 2: Different Templates per Type - -```yaml -release: - title: "🎉 Minecraft {version} Released" - body: | - # Minecraft {version} - - The full release is here! - - **Download:** [minecraft.net](https://minecraft.net) - **Date:** {release_date} - -snapshot: - title: "📸 Minecraft {version} Snapshot" - body: | - # Snapshot Available - - Test drive {version} before the official release! - - **Date:** {release_date} - -old_beta: - title: "[LEGACY] Minecraft {version} Beta" - body: | - Archive: Minecraft {version} beta + New {type} build: {version} Released: {release_date} ``` -### Example 3: Minimal Setup with Default +### Minimal Setup with Defaults ```yaml default: title: "Minecraft {version}" body: | - New {type}: {version} - {release_date} + # New {type} Available + + Version: {version} + Released: {release_date} ``` -## Features +## Loading and Caching -- **Multiple Configurations:** Different posts for releases, snapshots, legacy versions, etc. -- **Auto-Refresh:** Wiki changes are loaded every 30 minutes automatically -- **Fallback:** If a release type isn't configured, it uses the `default` config -- **No Restart Required:** Changes take effect on the next check cycle -- **Flexible:** Use any text, formatting, and placeholders you want +The wiki configuration: +- Loads on bot startup +- Refreshes automatically during version checks +- Is cached for 5 minutes to avoid excessive wiki requests +- Falls back to embedded defaults if the wiki page is missing or invalid + +Warning messages in logs: +- "Error fetching YAML config from wiki" - Cannot read the page +- "Wiki config missing required 'triggers' key" - Invalid YAML format +- An error YAML parse message - Syntax error in configuration + +## Formatting Guidelines + +YAML syntax rules: +- Use correct indentation (2 spaces recommended) +- Start multi-line strings with | or |- +- Values in double quotes: "string with special characters" +- No tab characters (spaces only) + +Text formatting in posts: +- Standard Reddit Markdown supported +- Headers: # Title (single hash for main title) +- Bold: **text** +- Italic: *text* +- Links: [text](url) +- Line breaks: Use actual newlines in the YAML body + +## Fallback Behavior + +If a release type is not configured: +1. Bot looks for a "default" section +2. If no default exists, uses embedded defaults +3. Embedded default format: + ``` + Title: Minecraft {version} ({type}) + Body: New {type}: {version}. Released: {release_date} + ``` + +## YAML Validation + +Test your YAML before adding to wiki: +- Use an online YAML validator at https://www.yamllint.com/ +- Check for correct indentation and quotes +- Verify all colons have spaces after them + +Common mistakes: +- Indentation with tabs (must be spaces) +- Missing quotes around values with special characters +- Unbalanced quotes +- Trailing colons without values + +## Testing Configuration + +After updating the wiki page: + +1. Send a "reload-config" chat message to the bot (moderators only) +2. Check bot logs for these messages: + - "[WIKI_CONFIG] Successfully fetched wiki page" + - "[WIKI_CONFIG] Loaded X configuration(s)" +3. Look for error messages with parsing details + +Command for moderators: +``` +Send a Reddit chat message to the bot containing: reload-config +``` + +The bot will reply with success or failure status. ## Troubleshooting -### Configuration Not Loading +Wiki configuration not loading: +1. Check page name is exactly "minecraft_update_bot" (or your custom name) +2. Verify the bot can read the wiki (check subreddit permissions) +3. Use YAML validator to find syntax errors +4. Check bot logs for error messages -1. Check the bot logs: - ```bash - docker-compose logs minecraft-bot - ``` +Posts not formatting correctly: +- Verify placeholder names: {version}, {release_date}, {type} +- Check YAML indentation is consistent +- Use | for multi-line bodies (not single quotes) +- Test problematic sections in a YAML validator -2. Verify the wiki page name is exactly `minecraft_update_bot` +Configuration not updating after wiki change: +- Wait up to 5 minutes (cache timeout) +- Or send "reload-config" chat command (moderators) +- Check bot logs to confirm reload was successful -3. Ensure the YAML is valid (use a YAML validator if needed) +Fallback config triggering: +- Check for YAML parse errors in logs +- Verify the wiki page is readable +- Ensure "release" configuration exists or "default" is defined -4. Check that the bot has permissions to read the wiki +## Examples with Real-World Scenarios -### Posts Not Formatting Correctly +### Example 1: Simple Release Announcements -- Verify placeholder names are correct: `{version}`, `{release_date}`, `{type}` -- Check that the YAML syntax is correct (indentation matters!) -- Use the pipe `|` for multi-line bodies - -### Reverting to Default - -If the wiki page is empty or invalid, the bot will use embedded defaults: +For a subreddit that only posts final releases: ```yaml release: - title: "Minecraft {version} Released!" - body: "# Minecraft {version}\n\nA new version is available!\n\n**Version:** {version}\n**Released:** {release_date}\n\nGet it at [minecraft.net](https://minecraft.net)" + title: "Minecraft {version} - Out Now!" + body: | + The official release of Minecraft {version} is now available! + + Released: {release_date} ``` -## Advanced: Testing Your Configuration +### Example 2: Community-Focused Posts -To test without posting to your subreddit: +```yaml +release: + title: "What's New in Minecraft {version}?" + body: | + # Minecraft {version} Released + + We have a new version! + + **Version:** {version} + **Release Date:** {release_date} + + What are you most excited to try? -1. View the bot logs: - ```bash - docker-compose logs -f - ``` +snapshot: + title: "Snapshot: Try the Latest Features" + body: | + # {version} Snapshot Available + + Want to test upcoming features? This is your chance! + + Released: {release_date} + + Remember: Snapshots can be unstable. Use separate worlds for testing! +``` -2. Watch for the line: - ``` - [WIKI_CONFIG] ✓ Loaded X configuration(s) - ``` +### Example 3: Structured with Emojis (if preferred) + +```yaml +release: + title: "[RELEASE] Minecraft {version}" + body: | + Minecraft {version} is now available! + Released: {release_date} + +snapshot: + title: "[SNAPSHOT] Minecraft {version}" + body: | + New snapshot available! + Released: {release_date} +``` + +## Wiki Markup + +Reddit wiki pages support: +- Standard Markdown +- Escape special characters with backslash: \{text\} +- HTML not processed in wiki pages +- Some Reddit-specific formatting may have limitations 3. This confirms your configs were loaded successfully diff --git a/bedrock_checker.py b/bedrock_checker.py index 18f4af3..81c8e4c 100644 --- a/bedrock_checker.py +++ b/bedrock_checker.py @@ -1,99 +1,97 @@ -""" -Minecraft Bedrock Edition version checker - tracks Windows releases -""" - import requests -import json +from bs4 import BeautifulSoup +import re from datetime import datetime -# Bedrock version tracking endpoints -# Using third-party services that track Bedrock version history -BEDROCK_VERSIONS_URL = "https://raw.githubusercontent.com/pmmp/PocketMine-MP/master/src/VersionInfo.php" - -# Alternative: Direct launcher check (if available) -BEDROCK_LAUNCHER_API = "https://launcher.mojang.com/v1/products/bedrock-launcher/latest" - -TIMEOUT = 10 - - -def get_bedrock_versions(): - """ - Fetch Bedrock version information. - Attempts multiple sources for reliability. - - Returns: - Dict with version info or None - """ - # Try the launcher API first - try: - response = requests.get(BEDROCK_LAUNCHER_API, timeout=TIMEOUT) - if response.status_code == 200: - data = response.json() - if data: - return data - except Exception as e: - print(f"[BEDROCK_CHECKER] Launcher API error: {e}") - - # Fallback: try Windows version manifest - try: - # Query Microsoft's update service for Bedrock - response = requests.get( - "https://launcher.mojang.com/v1/products/bedrock-launcher/16/latest", - headers={"Accept": "application/json"}, - timeout=TIMEOUT - ) - if response.status_code == 200: - return response.json() - except Exception as e: - print(f"[BEDROCK_CHECKER] Manifest error: {e}") - - return None - - -def parse_bedrock_version(response_data): - """ - Parse response data into standardized version format. - - Args: - response_data: JSON response from version endpoint - - Returns: - Dict with keys: id, version, type, releaseTime - """ - if not response_data: - return None - - try: - # Extract version information from different possible response formats - version = response_data.get('version') or response_data.get('latest') - - if not version: - return None - - return { - "id": version, - "version": version, - "type": "bedrock-windows", - "releaseTime": response_data.get('releaseTime', datetime.utcnow().isoformat() + "+00:00"), - "platform": "windows" - } - except Exception as e: - print(f"[BEDROCK_CHECKER] Parse error: {e}") - return None - def get_latest_bedrock_release(): - """ - Get the latest Bedrock Windows release. + """Get the latest Bedrock edition version by scraping minecraft.wiki. - Returns: - Dict with version info or None + Parses the version history page to find the latest release. + Returns dict with id, version, type, releaseTime, or None if scraping fails. """ + print("[BEDROCK_CHECKER] Fetching bedrock version from minecraft.wiki...") + try: - version_data = get_bedrock_versions() - return parse_bedrock_version(version_data) + url = "https://minecraft.wiki/w/Bedrock_Edition_version_history" + response = requests.get(url, timeout=10, headers={'User-Agent': 'MinecraftUpdateBot/1.0'}) + + if response.status_code != 200: + print(f"[BEDROCK_CHECKER] Failed to fetch wiki: {response.status_code}") + return None + + soup = BeautifulSoup(response.content, 'html.parser') + + # Find the first version number mentioned in the actual content + # Look for patterns like "26.3", "1.21.132", etc. + page_text = soup.get_text() + + # The page structure has version numbers in tables + # Let's look for the section with "26.x" or "1.21" which are current + + # Try to get version from table data + tables = soup.find_all('table', {"class": "wikitable"}) + + if tables: + for table in tables: + rows = table.find_all('tr') + if len(rows) > 1: + # Second row (first data row) has the latest version + cells = rows[1].find_all('td') + if cells: + version_text = cells[0].get_text(strip=True) + # Clean up the version text + if version_text and not version_text.lower().startswith('version'): + # Extract just the version number + version_match = re.match(r'^([\d.]+)', version_text) + if version_match: + version = version_match.group(1) + print(f"[BEDROCK_CHECKER] ✓ Found version from wiki table: {version}") + return { + "id": version, + "version": version, + "type": "bedrock-windows", + "source": "minecraft_wiki", + "releaseTime": datetime.now().isoformat() + } + + # Fallback: parse page text for version patterns + # Look for the new versioning format (26.x, 27.x, etc.) - not old 1.21.x format + # New format is major.minor (e.g., 26.3, 27.0) + version_pattern = r'\b(2[6-9]|[3-9]\d)\.(\d{1,2})\b' + matches = re.findall(version_pattern, page_text) + + if matches: + # Get the first match (oldest format would be 26.x, newest would be higher) + for major_str, minor_str in matches: + try: + major = int(major_str) + minor = int(minor_str) + # Accept versions 26.x and above + if major >= 26 and minor >= 0: + version = f"{major}.{minor}" + print(f"[BEDROCK_CHECKER] ✓ Found version from wiki: {version}") + return { + "id": version, + "version": version, + "type": "bedrock-windows", + "source": "minecraft_wiki", + "releaseTime": datetime.now().isoformat() + } + except ValueError: + continue + + print("[BEDROCK_CHECKER] ✗ Could not find version number in wiki page") + return None + + except requests.exceptions.Timeout: + print("[BEDROCK_CHECKER] ✗ Timeout fetching wiki page") + return None + except requests.exceptions.RequestException as e: + print(f"[BEDROCK_CHECKER] ✗ Request error: {e}") + return None except Exception as e: - print(f"[BEDROCK_CHECKER] Error getting latest release: {e}") + print(f"[BEDROCK_CHECKER] ✗ Error scraping wiki: {e}") return None diff --git a/config.py b/config.py index 2b95aa5..c9d47d9 100644 --- a/config.py +++ b/config.py @@ -9,17 +9,17 @@ REDDIT_USERNAME = os.getenv("REDDIT_USERNAME", "YOUR_USERNAME") REDDIT_PASSWORD = os.getenv("REDDIT_PASSWORD", "YOUR_PASSWORD") # Subreddit to post to -SUBREDDIT = os.getenv("SUBREDDIT", "YOUR_SUBREDDIT") +SUBREDDIT = os.getenv("REDDIT_SUBREDDIT", "YOUR_SUBREDDIT") # Minecraft release types to check for # Options: "release", "snapshot", "old_beta", "old_alpha" -# Can set via env as comma-separated: RELEASE_TYPES=release,snapshot -release_types_env = os.getenv("RELEASE_TYPES", "release") +# Can set via env as comma-separated: REDDIT_RELEASE_TYPES=release,snapshot +release_types_env = os.getenv("REDDIT_RELEASE_TYPES", "release") RELEASE_TYPES = [t.strip() for t in release_types_env.split(",")] # Check for Bedrock Edition releases (Windows) # Set to true to detect and post Bedrock releases -CHECK_BEDROCK = os.getenv("CHECK_BEDROCK", "false").lower() in ("true", "1", "yes") +CHECK_BEDROCK = os.getenv("REDDIT_CHECK_BEDROCK", "false").lower() in ("true", "1", "yes") # Post templates # NOTE: Post titles and bodies are now fetched from the subreddit wiki page "minecraft_update_bot" @@ -46,5 +46,9 @@ CHECK_BEDROCK = os.getenv("CHECK_BEDROCK", "false").lower() in ("true", "1", "ye # Check interval in seconds (default: 3600 = 1 hour) -# Can be set via environment variable: CHECK_INTERVAL=3600 -CHECK_INTERVAL = int(os.getenv("CHECK_INTERVAL", "3600")) +# Can be set via environment variable: REDDIT_CHECK_INTERVAL=3600 +CHECK_INTERVAL = int(os.getenv("REDDIT_CHECK_INTERVAL", "3600")) + +# Wiki page name for post templates +# Can be set via environment variable: REDDIT_WIKI_PAGE_NAME=mods/minecraft-update-bot +WIKI_PAGE_NAME = os.getenv("REDDIT_WIKI_PAGE_NAME", "minecraft_update_bot") diff --git a/docker-compose.yml b/docker-compose.yml index 67aa5c6..bac5269 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,22 +1,23 @@ services: - minecraft-bot: + minecraftupdatebot: build: . - image: minecraft-update-bot:latest - container_name: minecraft-bot + image: slfhstd.uk/slfhstd/minecraftupdatebot:latest + container_name: minecraftupdatebot + env_file: .env environment: - # Reddit Configuration REDDIT_CLIENT_ID: ${REDDIT_CLIENT_ID} REDDIT_CLIENT_SECRET: ${REDDIT_CLIENT_SECRET} - REDDIT_USER_AGENT: ${REDDIT_USER_AGENT:-MinecraftUpdateBot/1.0} + REDDIT_USER_AGENT: ${REDDIT_USER_AGENT} REDDIT_USERNAME: ${REDDIT_USERNAME} REDDIT_PASSWORD: ${REDDIT_PASSWORD} - # Bot Configuration - SUBREDDIT: ${SUBREDDIT} - RELEASE_TYPES: ${RELEASE_TYPES:-release} - CHECK_INTERVAL: ${CHECK_INTERVAL:-3600} + REDDIT_SUBREDDIT: ${REDDIT_SUBREDDIT} + REDDIT_RELEASE_TYPES: ${REDDIT_RELEASE_TYPES} + REDDIT_CHECK_INTERVAL: ${REDDIT_CHECK_INTERVAL} + REDDIT_CHECK_BEDROCK: ${REDDIT_CHECK_BEDROCK} + REDDIT_WIKI_PAGE_NAME: ${REDDIT_WIKI_PAGE_NAME} volumes: # Persist the database of posted versions - - minecraft-bot-db:/app/DB + - ./DB:/app/DB # Optional: mount config.py for easy editing # - ./config.py:/app/config.py restart: unless-stopped @@ -26,7 +27,3 @@ services: # limits: # cpus: '0.5' # memory: 256M - -volumes: - minecraft-bot-db: - driver: local diff --git a/main.py b/main.py index 62cd816..13dfffd 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,7 @@ from update_checker import start_update_checker # Bot version (increment when making changes) -BOT_VERSION = "1.0" +BOT_VERSION = "1.0.0" # Database file to track posted versions DB_DIR = os.path.join(os.path.dirname(__file__), 'DB') @@ -135,21 +135,172 @@ def check_for_updates(reddit): # Check Bedrock Edition releases if enabled if config.CHECK_BEDROCK: + print(f"[BOT] Checking Bedrock Edition releases...") bedrock_release = get_latest_bedrock_release() if bedrock_release: bedrock_id = f"bedrock-{bedrock_release['version']}" + source = bedrock_release.get('source', 'unknown') if bedrock_id not in posted_versions: - print(f"[BOT] New Bedrock release found: {bedrock_release['version']}") + print(f"[BOT] New Bedrock release found: {bedrock_release['version']} (from {source})") if post_to_subreddit(reddit, bedrock_release): save_posted_version(bedrock_id) else: print(f"[BOT] Bedrock version {bedrock_release['version']} already posted, skipping") + else: + print(f"[BOT] ⚠ No Bedrock release data available") + else: + print(f"[BOT] Bedrock Edition checking is disabled (REDDIT_CHECK_BEDROCK={config.CHECK_BEDROCK})") except Exception as e: print(f"[BOT] ✗ Error checking for updates: {e}") +def repost_latest_versions(reddit): + """ + Repost the latest Minecraft releases (Java & Bedrock). + + This bypasses the "already posted" check, allowing moderators to + manually repost the latest versions via the "repost-latest" chat command. + + Args: + reddit: PRAW Reddit instance + """ + try: + posted_count = 0 + + # Repost latest Java Edition releases + java_releases = get_latest_releases(config.RELEASE_TYPES) + for version_info in java_releases: + version_id = version_info["id"] + print(f"[BOT] Reposting Java release: {version_id}") + if post_to_subreddit(reddit, version_info): + posted_count += 1 + + # Repost latest Bedrock Edition release if enabled + if config.CHECK_BEDROCK: + bedrock_release = get_latest_bedrock_release() + if bedrock_release: + version_id = bedrock_release["id"] + print(f"[BOT] Reposting Bedrock release: {version_id}") + if post_to_subreddit(reddit, bedrock_release): + posted_count += 1 + else: + print(f"[BOT] ⚠ No Bedrock release data available for repost") + + print(f"[BOT] ✓ Reposted {posted_count} version(s)") + return posted_count > 0 + + except Exception as e: + print(f"[BOT] ✗ Error reposting latest versions: {e}") + return False + + +def chat_message_watcher(reddit): + """ + Background thread that watches for chat messages with reload commands. + + Monitors Reddit chat messages for moderators sending "reload-config" + to trigger a reload of the wiki configuration without restarting the bot. + + Args: + reddit: PRAW Reddit instance + """ + chat_requests_file = os.path.join(DB_DIR, 'chat_wiki_requests.txt') + processed_message_ids = set() + subreddit = reddit.subreddit(config.SUBREDDIT) + + print("[CHAT] Chat message watcher started") + + # Load previously processed message IDs + if os.path.exists(chat_requests_file): + try: + with open(chat_requests_file, 'r', encoding='utf-8') as f: + for line in f: + processed_message_ids.add(line.strip()) + except Exception as e: + print(f"[CHAT] Error loading processed message IDs: {e}") + + while True: + try: + for message in reddit.inbox.stream(): + # Skip if no ID or already processed + if not hasattr(message, 'id') or message.id in processed_message_ids: + continue + + # Mark as processed + processed_message_ids.add(message.id) + try: + with open(chat_requests_file, 'a', encoding='utf-8') as f: + f.write(message.id + '\n') + except Exception as e: + print(f"[CHAT] Error saving message ID: {e}") + + # Check for reload-config command + if hasattr(message, 'body') and 'reload-config' in message.body.lower(): + author = getattr(message, 'author', None) + + # Verify sender is a moderator + try: + if author and author in subreddit.moderator(): + print(f"[CHAT] Moderator '{author}' requested config reload") + + # Reload wiki configuration + try: + wiki_config.fetch_from_wiki() + print("[CHAT] Wiki config reloaded successfully") + reply_text = "✓ Wiki config reloaded successfully!" + except Exception as e: + print(f"[CHAT] Failed to reload wiki config: {e}") + reply_text = f"✗ Failed to reload wiki config: {e}" + + # Reply to the message + try: + message.reply(reply_text) + print(f"[CHAT] Replied to message {message.id}") + except Exception as e: + print(f"[CHAT] Error replying to message {message.id}: {e}") + else: + print(f"[CHAT] Non-moderator '{author}' attempted reload-config (ignored)") + except Exception as e: + print(f"[CHAT] Error checking moderator status: {e}") + + # Check for repost-latest command + elif hasattr(message, 'body') and 'repost-latest' in message.body.lower(): + author = getattr(message, 'author', None) + + # Verify sender is a moderator + try: + if author and author in subreddit.moderator(): + print(f"[CHAT] Moderator '{author}' requested repost of latest versions") + + # Repost latest versions + try: + if repost_latest_versions(reddit): + reply_text = "✓ Latest versions reposted successfully!" + else: + reply_text = "✗ Failed to repost latest versions." + except Exception as e: + print(f"[CHAT] Error reposting latest versions: {e}") + reply_text = f"✗ Error reposting latest versions: {e}" + + # Reply to the message + try: + message.reply(reply_text) + print(f"[CHAT] Replied to message {message.id}") + except Exception as e: + print(f"[CHAT] Error replying to message {message.id}: {e}") + else: + print(f"[CHAT] Non-moderator '{author}' attempted repost-latest (ignored)") + except Exception as e: + print(f"[CHAT] Error checking moderator status: {e}") + + except Exception as e: + print(f"[CHAT] Error in chat message watcher: {e}") + + time.sleep(30) + + def bot_thread(reddit): """ Background thread that periodically checks for Minecraft updates. @@ -191,10 +342,14 @@ def start_bot(): # Do an initial check check_for_updates(reddit) - # Start background thread + # Start background thread for update checking thread = threading.Thread(target=bot_thread, args=(reddit,), daemon=True) thread.start() + # Start background thread for chat commands + chat_thread = threading.Thread(target=chat_message_watcher, args=(reddit,), daemon=True) + chat_thread.start() + print("[BOT] ✓ Bot is running") # Keep main thread alive diff --git a/requirements.txt b/requirements.txt index a34395a..3ecedb7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ praw==7.7.0 requests==2.31.0 PyYAML==6.0.1 +beautifulsoup4==4.12.2 diff --git a/wiki_config.py b/wiki_config.py index e5e72b0..6af8e19 100644 --- a/wiki_config.py +++ b/wiki_config.py @@ -7,10 +7,10 @@ import json import re import yaml from typing import Dict, Optional, Tuple +import config # Cache TTL in seconds (refresh wiki config every 30 minutes) WIKI_CACHE_TTL = 1800 -WIKI_PAGE_NAME = "minecraft_update_bot" class WikiConfig: @@ -72,7 +72,10 @@ class WikiConfig: """ try: subreddit = self.reddit.subreddit(self.subreddit_name) - wiki_page = subreddit.wiki[WIKI_PAGE_NAME] + print(f"[WIKI_CONFIG] Attempting to fetch wiki page: {config.WIKI_PAGE_NAME}") + + # Try the wiki page with the configured name + wiki_page = subreddit.wiki[config.WIKI_PAGE_NAME] content = wiki_page.content_md self.configs = self._parse_yaml_content(content) @@ -88,7 +91,8 @@ class WikiConfig: return False except Exception as e: - print(f"[WIKI_CONFIG] ✗ Error fetching wiki: {e}") + print(f"[WIKI_CONFIG] ✗ Error fetching wiki page '{config.WIKI_PAGE_NAME}' from r/{self.subreddit_name}: {e}") + print(f"[WIKI_CONFIG] ⚠ Check that the page exists at reddit.com/r/{self.subreddit_name}/wiki/{config.WIKI_PAGE_NAME}") return False def _parse_yaml_content(self, content: str) -> Dict[str, Dict[str, str]]: