import praw import os import os.path import json import time # Helper to get env var or default def env_or_default(var, default): return os.environ.get(var, default) # Create config/config.py from environment if missing or empty default_config_path = os.path.join('config', 'config.py') def write_config_from_env(): os.makedirs('config', exist_ok=True) with open(default_config_path, 'w') as f: f.write( f'username = "{env_or_default("USERNAME", "")}"\n' f'password = "{env_or_default("PASSWORD", "")}"\n' f'client_id = "{env_or_default("CLIENT_ID", "")}"\n' f'client_secret = "{env_or_default("CLIENT_SECRET", "")}"\n' f'user_agent = "{env_or_default("USER_AGENT", "Flair Timer ModMail Bot")}"\n' '\n' f'subreddit = "{env_or_default("SUBREDDIT", "")}"\n' f'interval = {env_or_default("INTERVAL", "30")}\n' f'searchlimit = {env_or_default("SEARCHLIMIT", "600")}\n' ) print(f"Configuration file auto-populated from environment variables at {default_config_path}.") # Check if config file exists and is non-empty, else generate from env def config_needs_populating(): if not os.path.exists(default_config_path): return True try: with open(default_config_path, 'r') as f: content = f.read().strip() return len(content) == 0 except Exception: return True if config_needs_populating(): write_config_from_env() # Import main config import config # Create default flairconfig.py if missing flair_config_path = os.path.join('config', 'flairconfig.py') def write_default_flairconfig(): if not os.path.exists(flair_config_path): os.makedirs(os.path.dirname(flair_config_path), exist_ok=True) with open(flair_config_path, 'w') as f: f.write('# flairconfig.py\n') f.write('# This file defines the list of flair time configs for the bot.\n') f.write('flair_times = [\n') f.write(' {\n') f.write(' "flair_text": "Waiting for OP",\n') f.write(' "hours": 48,\n') f.write(' "messagetitle": "Modmail Notification",\n') f.write(' },\n') f.write(']\n') print(f"Default flairconfig.py created at {flair_config_path}.") write_default_flairconfig() # Load flair_times from flairconfig.py import importlib.util spec = importlib.util.spec_from_file_location("flairconfig", flair_config_path) flairconfig = importlib.util.module_from_spec(spec) spec.loader.exec_module(flairconfig) flair_times = getattr(flairconfig, "flair_times", []) def authentication(): print("Authenticating...") reddit = praw.Reddit( username=config.username, password=config.password, client_id=config.client_id, client_secret=config.client_secret, user_agent=config.user_agent ) print("Authenticated as {}.".format(reddit.user.me())) return reddit def main(reddit, all_posts: dict): # all_posts structure: {flair_text: {submission_id: timestamp}} while True: for flair_cfg in flair_times: flair_text = flair_cfg["flair_text"] hours = flair_cfg["hours"] messagetitle = flair_cfg.get("messagetitle", "Modmail Notification") # Ensure posts dict for this flair posts = all_posts.setdefault(flair_text, {}) for submission in reddit.subreddit(config.subreddit).new(limit=config.searchlimit): if not submission.saved: if submission.id not in posts and submission.link_flair_text == flair_text: posts[submission.id] = time.time() print(f"Post {submission} has been flaired {flair_text}") if submission.id in posts and submission.link_flair_text != flair_text: posts.pop(submission.id) print(f"Post {submission} has been unflaired {flair_text}") expired = [] for submission_id, flair_time in posts.items(): if time.time() > flair_time + (hours * 60 * 60): expired.append(submission_id) for submission_id in expired: posts.pop(submission_id) subm = reddit.submission(submission_id) subm.save() data = { "subject": messagetitle, "text": f"It has been {hours/24} day/s since this was flaired [{flair_text}](https://old.reddit.com{subm.permalink})", "to": "/r/{}".format(config.subreddit), } reddit.post("api/compose/", data=data) print(f"Post {submission_id} has been flaired {flair_text} for {hours} hours, sent modmail") save_posts(all_posts) time.sleep(config.interval) def load_posts(): if not os.path.exists("config/posts.json"): with open("config/posts.json", "w+") as file: json.dump({}, file) with open("config/posts.json", "r+") as file: data = json.load(file) # Ensure structure: {flair_text: {submission_id: timestamp}} if not isinstance(data, dict): return {} return data def save_posts(data): with open('config/posts.json', 'w+') as file: json.dump(data, file) while True: try: posts = load_posts() main(reddit=authentication(), all_posts=posts) except Exception as e: print(e)