changes to config to enable multiflair support

This commit is contained in:
2026-03-05 20:45:46 +00:00
parent 87f1f12bc8
commit 0e70503a3b
4 changed files with 122 additions and 66 deletions
+1 -5
View File
@@ -7,11 +7,7 @@ user_agent = "Flair Timer Mod Mail Bot"
#Subreddits
subreddit = "" # "INEEEEDIT" "Ofcoursethatsathing" "All"
flair_text = "" # Case Sensitive
interval = 30 # How often should the bot scan the subreddit for these posts, in seconds. Higher = slower/less accurate/save resources, lower = faster/more accurate/use more resources.
hours = 0.17 # How many hours must the flair been on the post to send the notification
searchlimit = 900 # Max: 1000, this should only be limited to save on resources. The bot sorts by new and if it isn't catching posts that are being changed to the flair simply because they are too old (say the 301st post on the subreddit is changed to the flair) then increase this limit.
messagetitle = "" # Title of the modmail
searchlimit = 900 # Max: 1000, this should only be limited to save on resources. The bot sorts by new and if it isn't catching posts that are being changed to the flair simply because they are too old (say the 301st post on the subreddit is changed to the flair) then increase this limit.his limit.
+12
View File
@@ -0,0 +1,12 @@
# flairconfig.py
# This file defines the list of flair time configs for the bot.
# Edit this file to customize flair behaviors.
flair_times = [
{
"flair_text": "Waiting for OP",
"hours": 48,
"messagetitle": "Modmail Notification",
},
# Add more configs as needed
]
-3
View File
@@ -5,8 +5,5 @@ CLIENT_ID=your_reddit_client_id
CLIENT_SECRET=your_reddit_client_secret
USER_AGENT=Flair Timer Mod Mail Bot
SUBREDDIT=your_subreddit
FLAIR_TEXT=Waiting for OP
INTERVAL=30
HOURS=48
MESSAGETITLE=Modmail Notification
SEARCHLIMIT=600
+86 -35
View File
@@ -1,15 +1,19 @@
import praw
import os
import os.path
import json
import time
# Create default config/config.py if it doesn't exist and exit to prompt manual editing
import sys
default_config_path = os.path.join('config', 'config.py')
# 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:
@@ -18,73 +22,116 @@ def write_config_from_env():
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 Comment Bot" )}"\n'
f'user_agent = "{env_or_default("USER_AGENT", "Flair Timer ModMail Bot")}"\n'
'\n'
f'subreddit = "{env_or_default("SUBREDDIT", "")}"\n'
f'flair_text = "{env_or_default("FLAIR_TEXT", "Waiting for OP")}"\n'
f'interval = {env_or_default("INTERVAL", "30")}\n'
f'hours = {env_or_default("HOURS", "48")}\n'
f'messagetitle = "{env_or_default("MESSAGETITLE", "Modmail Notification")}"\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 is missing or empty
populate_config = False
# 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):
populate_config = True
else:
return True
try:
with open(default_config_path, 'r') as f:
content = f.read().strip()
if not content:
populate_config = True
return len(content) == 0
except Exception:
populate_config = True
return True
if populate_config:
if config_needs_populating():
write_config_from_env()
sys.exit(0)
if not os.path.exists(default_config_path):
sys.exit(0)
# 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,
reddit = praw.Reddit(
username=config.username,
password=config.password,
client_id=config.client_id,
client_secret=config.client_secret,
user_agent = config.user_agent)
user_agent=config.user_agent
)
print("Authenticated as {}.".format(reddit.user.me()))
return reddit
def main(reddit, posts: dict):
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.keys() and submission.link_flair_text == config.flair_text:
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 {config.flair_text}")
if submission.id in posts.keys() and submission.link_flair_text != config.flair_text:
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 {config.flair_text}")
print(f"Post {submission} has been unflaired {flair_text}")
for submission in posts:
if time.time() > posts[submission] + (config.hours * 60 * 60):
posts.pop(submission)
reddit.submission(submission).save()
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": config.messagetitle,
"text": f"It has been {config.hours/24} day/s since this was flaired [{config.flair_text}](https://old.reddit.com{reddit.submission(submission).permalink})",
"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} has been flaired {config.flair_text} for {config.hours * 60} minutes, sent modmail")
break
print(f"Post {submission_id} has been flaired {flair_text} for {hours} hours, sent modmail")
save_posts(posts)
save_posts(all_posts)
time.sleep(config.interval)
def load_posts():
@@ -93,8 +140,12 @@ def load_posts():
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)
@@ -103,6 +154,6 @@ def save_posts(data):
while True:
try:
posts = load_posts()
main(reddit = authentication(), posts = posts)
main(reddit=authentication(), all_posts=posts)
except Exception as e:
print(e)