initial code upload
Some checks failed
Python CI / build (push) Failing after 27s

This commit is contained in:
Space-Banane
2026-02-07 12:01:15 +01:00
commit 144d9c1618
8 changed files with 287 additions and 0 deletions

36
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Python CI
on:
push:
branches: [ "main", "master" ]
pull_request:
branches: [ "main", "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Check syntax
run: |
python -m py_compile main.py

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
config.json
__pycache__/

16
License Normal file
View File

@@ -0,0 +1,16 @@
MIT No Attribution
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
config.example.json Normal file
View File

@@ -0,0 +1,11 @@
{
"bot_token": "YOUR BOT TOKEN",
"prefix": ";",
"command_name": "reddit",
"comment_limit": 2,
"delete_user_message_on_dismiss": true,
"embed_color_submission": "blue",
"embed_color_comments": "green",
"uptime_kuma_url": "",
"uptime_kuma_interval": 60
}

10
docker-compose.yml Normal file
View File

@@ -0,0 +1,10 @@
services:
bot:
working_dir: /app
command: bash -c "pip install -r requirements.txt && python main.py"
container_name: reddit-fix-please
restart: unless-stopped
environment:
- PYTHONUNBUFFERED=1
volumes:
- .:/app

146
main.py Normal file
View File

@@ -0,0 +1,146 @@
import discord
from discord.ext import commands
import redditwarp.SYNC
import json
import os
import aiohttp
import asyncio
# Load configuration
config_path = os.path.join(os.path.dirname(__file__), "config.json")
with open(config_path, "r") as f:
config = json.load(f)
bot_token = config.get("bot_token")
prefix = config.get("prefix", ";")
command_name = config.get("command_name", "rediddy")
comment_limit = config.get("comment_limit", 2)
delete_user_msg = config.get("delete_user_message_on_dismiss", True)
uptime_kuma_url = config.get("uptime_kuma_url", "")
uptime_kuma_interval = config.get("uptime_kuma_interval", 60)
# Color mapping
COLORS = {
"blue": discord.Color.blue(),
"green": discord.Color.green(),
"red": discord.Color.red(),
"gold": discord.Color.gold(),
"purple": discord.Color.purple(),
}
sub_color = COLORS.get(
config.get("embed_color_submission", "blue"), discord.Color.blue()
)
comment_color = COLORS.get(
config.get("embed_color_comments", "green"), discord.Color.green()
)
# Setup Discord bot intents
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix=prefix, intents=intents)
reddit_client = redditwarp.SYNC.Client()
@bot.event
async def on_ready():
print(f"Logged in as {bot.user} (ID: {bot.user.id})")
print("------")
if uptime_kuma_url:
bot.loop.create_task(uptime_kuma_heartbeat())
async def uptime_kuma_heartbeat():
async with aiohttp.ClientSession() as session:
while not bot.is_closed():
try:
async with session.get(uptime_kuma_url) as resp:
if resp.status == 200:
print("Uptime Kuma heartbeat sent.")
else:
print(f"Uptime Kuma error: {resp.status}")
except Exception as e:
print(f"Uptime Kuma connection failed: {e}")
await asyncio.sleep(uptime_kuma_interval)
class RediddyView(discord.ui.View):
def __init__(self, author_msg: discord.Message, submission_url: str):
super().__init__(timeout=60)
self.author_msg = author_msg
self.add_item(discord.ui.Button(label="Open Submission", url=submission_url))
@discord.ui.button(label="Dismiss", style=discord.ButtonStyle.danger)
async def dismiss(
self, interaction: discord.Interaction, button: discord.ui.Button
):
if delete_user_msg:
try:
await self.author_msg.delete()
except discord.Forbidden:
pass # May not have permission to delete user messages
await interaction.message.delete()
@bot.command(name=command_name)
async def fetch_reddit_submission(ctx, subreddit_name: str, *, query: str):
"""Searches Reddit and returns the top post and comments in embeds."""
try:
# Search for the subreddit name to get a valid subreddit object/ID
sr_list = reddit_client.p.subreddit.search_names(subreddit_name)
if not sr_list:
await ctx.send(f"Subreddit '{subreddit_name}' not found.")
return
target_sr = sr_list[0]
# Search for submissions within that subreddit
submissions = reddit_client.p.submission.search(target_sr, query, 1, sort="top")
found = False
for submission_brief in submissions:
found = True
# Get full submission details
submission = reddit_client.p.submission.get(submission_brief.id)
title = submission.d.get("title", "Reddit Post")
selftext = submission.d.get("selftext", "No content.")
permalink = f"https://www.reddit.com{submission.d.get('permalink')}"
# Submission Embed
main_embed = discord.Embed(
title=title,
url=permalink,
description=selftext[:2000] if selftext else "No content.",
color=sub_color,
)
main_embed.set_author(name=f"r/{target_sr}")
embeds = [main_embed]
# Fetch comments based on limit
try:
comment_tree = reddit_client.p.comment_tree.fetch(
submission.id, limit=comment_limit, sort="top"
)
for i, child in enumerate(comment_tree.children[:comment_limit]):
comment_body = child.value.body
comment_embed = discord.Embed(
title=f"Top Comment #{i+1}",
description=comment_body[:1000],
color=comment_color,
)
embeds.append(comment_embed)
except Exception as e:
print(f"Error fetching comments: {e}")
view = RediddyView(ctx.message, permalink)
await ctx.send(embeds=embeds, view=view)
if not found:
await ctx.send(f"No results found for '{query}' in {target_sr}.")
except Exception as e:
await ctx.send(f"An error occurred: {e}")
bot.run(bot_token)

63
readme.md Normal file
View File

@@ -0,0 +1,63 @@
# Reddit Fix Please - Discord Bot
A configurable Discord bot that searches Reddit subreddits for specific queries and returns the top submission along with its top comments in clean embeds.
## Features
- **Reddit Search**: Finds the most relevant "top" submission for a given subreddit and query.
- **Rich Embeds**: Displays the submission title, body, and top comments in easy-to-read Discord embeds.
- **Interactive UI**:
- **Open Submission**: Direct link button to the Reddit thread.
- **Dismiss**: Cleans up the bot's response and (optionally) the user's command message.
- **Fully Configurable**: Manage everything from tokens to UI colors via `config.json`.
- **Uptime Kuma Integration**: Support for push monitor heartbeats to track bot status.
## Setup
### Prerequisites
- Python 3.8+
- A Discord Bot Token (from [Discord Developer Portal](https://discord.com/developers/applications)) (enable "Message Content Intent" for the bot)
### Installation
1. Install the required dependencies:
```bash
pip install discord.py redditwarp
```
2. Copy `config.example.json` to `config.json`:
```bash
cp config.example.json config.json
```
3. Open `config.json` and fill in your `bot_token`.
### Configuration Options
| Key | Description | Default |
|-----|-------------|---------|
| `bot_token` | Your Discord bot application token | 😬 |
| `prefix` | The character(s) used to trigger the bot | `;` |
| `command_name` | The name of the search command | `reddit` |
| `comment_limit` | Number of top comments to display | `2` |
| `delete_user_message_on_dismiss` | Whether the Dismiss button deletes the user's message | `true` |
| `embed_color_submission` | Color of the main submission embed | `blue` |
| `embed_color_comments` | Color of the comment embeds | `green` |
| `uptime_kuma_url` | Uptime Kuma Push Monitor URL | `""` |
| `uptime_kuma_interval` | Interval in seconds for heartbeats | `60` |
## Usage
Start the bot:
```bash
python main.py
```
In Discord, use the configured command (default is `;reddit`):
```text
;reddit [subreddit] [query]
```
**Example:**
`;reddit valorantechsupport van-57`

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
redditwarp
discord.py
aiohttp