2026-03-08 23:27:43 +00:00
import os
2026-03-08 18:08:24 +00:00
import praw
from config import get_reddit , Config
import time
2026-03-10 18:37:11 +00:00
class ModReplyBot :
2026-03-10 22:29:35 +00:00
def chat_message_watcher ( self ) :
chat_requests_file = os . path . join ( os . path . dirname ( __file__ ) , ' DB ' , ' chat_wiki_requests.txt ' )
processed_message_ids = set ( )
# Load processed IDs from file
if os . path . exists ( chat_requests_file ) :
with open ( chat_requests_file , ' r ' , encoding = ' utf-8 ' ) as f :
for line in f :
processed_message_ids . add ( line . strip ( ) )
while True :
try :
for message in self . reddit . inbox . stream ( ) :
if not hasattr ( message , ' id ' ) or message . id in processed_message_ids :
continue
processed_message_ids . add ( message . id )
# Save processed ID to file
with open ( chat_requests_file , ' a ' , encoding = ' utf-8 ' ) as f :
f . write ( message . id + ' \n ' )
if hasattr ( message , ' body ' ) and ' reload-config ' in message . body . lower ( ) :
# Check if sender is a moderator
author = getattr ( message , ' author ' , None )
if author and author in self . subreddit . moderator ( ) :
print ( f " [CHAT WATCH] Moderator ' { author } ' requested config reload. " )
result = self . fetch_yaml_config ( )
if result :
print ( " [CHAT WATCH] Wiki config reloaded successfully. " )
reply_text = " Config reloaded successfully. Config is valid. "
else :
print ( " [CHAT WATCH] Wiki config reload failed. " )
reply_text = " Config reload failed. Config is invalid. "
try :
message . reply ( reply_text )
print ( f " [CHAT WATCH] Replied to chat message { message . id } . " )
except Exception as e :
print ( f " [CHAT WATCH] Error replying to chat message { message . id } : { e } " )
except Exception as e :
print ( f " Chat message watcher error: { e } " )
import time
time . sleep ( 30 )
def comment_only ( self , submission , comment_text ) :
try :
comment = submission . reply ( comment_text )
comment . mod . distinguish ( sticky = True )
print ( f " Commented (no approval) on: { submission . id } " )
self . save_commented_post ( submission . id )
except Exception as e :
print ( f " Error commenting (no approval): { e } " )
2026-03-08 18:08:24 +00:00
def __init__ ( self ) :
2026-03-08 21:32:51 +00:00
import os
2026-03-08 18:08:24 +00:00
self . reddit = get_reddit ( )
self . subreddit = self . reddit . subreddit ( Config . SUBREDDIT )
2026-03-08 21:32:51 +00:00
self . config_path = os . path . join ( os . path . dirname ( __file__ ) , ' config ' , ' config.yaml ' )
2026-03-08 18:08:24 +00:00
self . triggers = [ ]
self . comments = [ ]
2026-03-08 23:27:43 +00:00
self . commented_posts = set ( )
self . commented_posts_file = os . path . join ( os . path . dirname ( __file__ ) , ' DB ' , ' commented_posts.txt ' )
2026-03-10 22:29:35 +00:00
self . tagged_commented_posts_file = os . path . join ( os . path . dirname ( __file__ ) , ' DB ' , ' tagged_commented_posts.txt ' )
self . tagged_commented_posts = set ( )
self . _wiki_config_cache = None
self . _wiki_config_cache_time = 0
self . _wiki_config_cache_ttl = 300 # seconds (5 minutes)
2026-03-08 21:32:51 +00:00
self . ensure_config_file ( )
2026-03-08 23:27:43 +00:00
self . load_commented_posts ( )
2026-03-10 18:37:11 +00:00
self . log_level = Config . LOG_LEVEL
def log ( self , message , debug_only = False ) :
if self . log_level == ' Debug ' or ( self . log_level == ' Default ' and not debug_only ) :
print ( message )
2026-03-08 18:08:24 +00:00
2026-03-08 21:32:51 +00:00
def ensure_config_file ( self ) :
import os
if not os . path . exists ( self . config_path ) :
default_yaml = (
' triggers: \n '
' - trigger: help \n '
' comment: | \n '
' Thank you for your report! \n '
' This post is now approved. \n '
' - trigger: question \n '
' comment: | \n '
' This post has been approved. \n '
' Your question will be answered soon. \n '
)
os . makedirs ( os . path . dirname ( self . config_path ) , exist_ok = True )
with open ( self . config_path , ' w ' , encoding = ' utf-8 ' ) as f :
f . write ( default_yaml )
def fetch_yaml_config ( self ) :
2026-03-10 18:37:11 +00:00
# Track last error revision to prevent modmail spam
if not hasattr ( self , ' _last_config_error_revision ' ) :
self . _last_config_error_revision = None
2026-03-10 22:29:35 +00:00
import yaml , time
now = time . time ( )
# Use cache if not expired
if self . _wiki_config_cache and ( now - self . _wiki_config_cache_time < self . _wiki_config_cache_ttl ) :
config = self . _wiki_config_cache
self . _wiki_revision_id = getattr ( self , ' _wiki_revision_id ' , None )
else :
try :
wiki_page = Config . WIKI_PAGE
wiki = self . subreddit . wiki [ wiki_page ]
wiki_content = wiki . content_md
self . _wiki_revision_id = getattr ( wiki , ' revision_id ' , None )
config = yaml . safe_load ( wiki_content )
self . _wiki_config_cache = config
self . _wiki_config_cache_time = now
except Exception as e :
self . log ( f " Error fetching YAML config from wiki: { e } " )
revision = getattr ( self , ' _wiki_revision_id ' , None )
if revision != self . _last_config_error_revision :
self . _last_config_error_revision = revision
return False
if not isinstance ( config , dict ) or ' triggers ' not in config :
self . log ( " Wiki config missing required ' triggers ' key or is not a dict. " )
2026-03-10 18:37:11 +00:00
return False
2026-03-10 22:29:35 +00:00
self . triggers = [ ]
self . comments = [ ]
self . statuses = [ ]
self . flair_ids = [ ]
self . stickied = [ ]
self . lock_post = [ ]
self . lock_comment = [ ]
self . tag_comments = { }
self . tag_statuses = { }
self . tag_flair_ids = { }
for entry in config . get ( ' triggers ' , [ ] ) :
self . triggers . append ( entry . get ( ' trigger ' , ' ' ) . strip ( ) )
self . comments . append ( entry . get ( ' comment ' , ' ' ) . strip ( ) )
self . statuses . append ( entry . get ( ' status ' , ' enabled ' ) . strip ( ) . lower ( ) )
self . flair_ids . append ( entry . get ( ' flair_id ' , ' ' ) . strip ( ) )
self . stickied . append ( bool ( entry . get ( ' stickied ' , False ) ) )
# Parse lock_post as a proper boolean
lock_post_val = entry . get ( ' lock_post ' , False )
if isinstance ( lock_post_val , str ) :
lock_post_val = lock_post_val . lower ( ) in [ ' true ' , ' 1 ' , ' yes ' ]
self . lock_post . append ( bool ( lock_post_val ) )
self . lock_comment . append ( bool ( entry . get ( ' lock_comment ' , False ) ) )
for entry in config . get ( ' post_tags ' , [ ] ) :
tags_str = entry . get ( ' tag ' , ' ' ) . strip ( )
comment = entry . get ( ' comment ' , ' ' ) . strip ( )
status = entry . get ( ' status ' , ' enabled ' ) . strip ( ) . lower ( )
flair_id = entry . get ( ' flair_id ' , ' ' ) . strip ( )
tags = [ t . strip ( ) . lower ( ) for t in tags_str . split ( ' , ' ) if t . strip ( ) ]
for tag in tags :
self . tag_comments [ tag ] = comment
self . tag_statuses [ tag ] = status
self . tag_flair_ids [ tag ] = flair_id
self . _last_config_error_revision = None
return True
2026-03-10 18:37:11 +00:00
def notify_mods_config_error ( self , error_message ) :
try :
subject = " ModReplyBot wiki config error "
body = f " The bot detected an error in the wiki config page and will not reload until it is fixed. \n \n Error details: { error_message } \n \n Please check the wiki config for formatting or missing information. "
data = {
" subject " : subject ,
" text " : body ,
" to " : f " /r/ { Config . SUBREDDIT } " ,
}
self . reddit . post ( " api/compose/ " , data = data )
self . log ( " Sent modmail notification about wiki config error. " )
2026-03-08 18:08:24 +00:00
except Exception as e :
2026-03-10 18:37:11 +00:00
self . log ( f " Error sending modmail notification about wiki config error: { e } " )
2026-03-08 23:27:43 +00:00
def load_commented_posts ( self ) :
try :
with open ( self . commented_posts_file , ' r ' , encoding = ' utf-8 ' ) as f :
for line in f :
self . commented_posts . add ( line . strip ( ) )
except FileNotFoundError :
pass
def save_commented_post ( self , post_id ) :
self . commented_posts . add ( post_id )
with open ( self . commented_posts_file , ' a ' , encoding = ' utf-8 ' ) as f :
f . write ( post_id + ' \n ' )
2026-03-08 18:08:24 +00:00
def run ( self ) :
2026-03-08 23:27:43 +00:00
import threading
print ( " ModReplyBot started. Watching for comments and new posts... " )
2026-03-08 21:32:51 +00:00
try :
2026-03-10 18:37:11 +00:00
config_ok = self . fetch_yaml_config ( )
if not config_ok :
self . log ( " Bot startup aborted due to wiki config error. " )
return
self . log ( f " Triggers loaded: { self . triggers } " )
self . log ( f " Tag comments loaded: { self . tag_comments } " )
self . log ( f " Reddit user: { self . reddit . user . me ( ) } " )
self . log ( f " Subreddit: { self . subreddit . display_name } " )
2026-03-08 21:32:51 +00:00
except Exception as e :
2026-03-10 18:37:11 +00:00
self . log ( f " Startup error: { e } " )
2026-03-08 21:32:51 +00:00
return
2026-03-08 23:27:43 +00:00
2026-03-10 18:37:11 +00:00
def mod_comment_watcher ( ) :
2026-03-08 23:27:43 +00:00
last_revision = None
while True :
try :
old_revision = last_revision
2026-03-10 18:37:11 +00:00
config_ok = self . fetch_yaml_config ( )
2026-03-08 23:27:43 +00:00
new_revision = getattr ( self , ' _wiki_revision_id ' , None )
if old_revision and new_revision and old_revision != new_revision :
2026-03-10 22:29:35 +00:00
if config_ok :
self . log ( " Wiki config changed, reloading triggers and tag comments. " )
else :
self . log ( " Wiki config error detected, not reloading bot. " )
2026-03-10 18:37:11 +00:00
self . log_level = Config . LOG_LEVEL
2026-03-08 23:27:43 +00:00
last_revision = new_revision
for comment in self . subreddit . stream . comments ( skip_existing = True ) :
2026-03-10 18:37:11 +00:00
if comment . author and comment . author in self . subreddit . moderator ( ) :
self . handle_comment ( comment )
2026-03-08 23:27:43 +00:00
except Exception as e :
2026-03-10 18:37:11 +00:00
print ( f " Mod comment watcher error: { e } " )
2026-03-10 22:29:35 +00:00
import time
time . sleep ( 5 )
2026-03-08 23:27:43 +00:00
2026-03-10 18:37:11 +00:00
def mod_report_watcher ( ) :
2026-03-08 23:27:43 +00:00
last_revision = None
while True :
try :
old_revision = last_revision
2026-03-10 18:37:11 +00:00
config_ok = self . fetch_yaml_config ( )
2026-03-08 23:27:43 +00:00
new_revision = getattr ( self , ' _wiki_revision_id ' , None )
if old_revision and new_revision and old_revision != new_revision :
2026-03-10 18:37:11 +00:00
if config_ok :
self . log ( " Wiki config changed, reloading triggers and tag comments. " )
self . notify_mods_config_change ( new_revision )
else :
self . log ( " Wiki config error detected, not reloading bot. " )
2026-03-08 23:27:43 +00:00
last_revision = new_revision
2026-03-10 18:37:11 +00:00
for submission in self . subreddit . mod . stream . reports ( ) :
self . handle_submission ( submission )
2026-03-08 23:27:43 +00:00
except Exception as e :
2026-03-10 18:37:11 +00:00
print ( f " Mod report watcher error: { e } " )
2026-03-08 23:27:43 +00:00
import time
2026-03-10 18:37:11 +00:00
time . sleep ( 30 )
2026-03-08 23:27:43 +00:00
2026-03-10 18:37:11 +00:00
threading . Thread ( target = mod_comment_watcher , daemon = True ) . start ( )
threading . Thread ( target = mod_report_watcher , daemon = True ) . start ( )
2026-03-10 22:29:35 +00:00
threading . Thread ( target = self . chat_message_watcher , daemon = True ) . start ( )
def tag_post_watcher ( ) :
while True :
try :
2026-03-10 23:36:40 +00:00
# Check new submissions
2026-03-10 22:29:35 +00:00
for submission in self . subreddit . stream . submissions ( skip_existing = True ) :
2026-03-10 23:48:39 +00:00
flair = ( getattr ( submission , ' link_flair_text ' , ' ' ) or ' ' ) . strip ( ) . lower ( )
2026-03-10 22:29:35 +00:00
title = submission . title . strip ( )
import re
title_tags = re . findall ( r ' \ [(.*?) \ ] ' , title )
title_tags_lower = [ t . strip ( ) . lower ( ) for t in title_tags ]
print ( f " [TAG WATCH] Post { submission . id } : title= ' { title } ' , flair= ' { flair } ' , title_tags= { title_tags_lower } " )
matched_tag = None
if flair in self . tag_comments :
matched_tag = flair
else :
for tag in title_tags_lower :
if tag in self . tag_comments :
matched_tag = tag
break
2026-03-10 23:36:40 +00:00
# Comment on all posts with matching tags
if matched_tag and ( submission . id not in self . commented_posts ) :
status = self . tag_statuses . get ( matched_tag , ' enabled ' )
comment_text = self . tag_comments [ matched_tag ]
flair_id = self . tag_flair_ids . get ( matched_tag , ' ' )
if flair_id :
try :
submission . flair . select ( flair_id )
print ( f " [TAG WATCH] Set flair ' { flair_id } ' for post { submission . id } " )
except Exception as e :
print ( f " [TAG WATCH] Error setting flair ' { flair_id } ' for post { submission . id } : { e } " )
print ( f " Auto-commenting on post { submission . id } with tag ' { matched_tag } ' " )
self . comment_only ( submission , comment_text )
2026-03-10 22:29:35 +00:00
except Exception as e :
print ( f " Tag post watcher error: { e } " )
import time
time . sleep ( 30 )
2026-03-10 23:36:40 +00:00
def modqueue_watcher ( ) :
while True :
try :
print ( " [MODQUEUE DEBUG] Entering modqueue loop... " )
modqueue_posts = list ( self . subreddit . mod . modqueue ( limit = 100 ) )
print ( f " [MODQUEUE DEBUG] Fetched { len ( modqueue_posts ) } posts from modqueue. " )
for submission in modqueue_posts :
2026-03-10 23:48:39 +00:00
# Only access link_flair_text if it's a Submission
if hasattr ( submission , ' link_flair_text ' ) :
flair = ( submission . link_flair_text or ' ' ) . strip ( ) . lower ( )
else :
flair = ' '
2026-03-10 23:52:19 +00:00
# Only access title if it's a Submission
if hasattr ( submission , ' title ' ) :
title = submission . title . strip ( )
else :
title = ' '
2026-03-10 23:36:40 +00:00
import re
title_tags = re . findall ( r ' \ [(.*?) \ ] ' , title )
title_tags_lower = [ t . strip ( ) . lower ( ) for t in title_tags ]
# Debug print all relevant attributes
print ( f " [MODQUEUE DEBUG] Post { submission . id } : title= ' { title } ' , flair= ' { flair } ' , title_tags= { title_tags_lower } , author= { submission . author } , removed_by_category= { getattr ( submission , ' removed_by_category ' , None ) } , banned_by= { getattr ( submission , ' banned_by ' , None ) } , mod_reason_title= { getattr ( submission , ' mod_reason_title ' , None ) } , spam= { getattr ( submission , ' spam ' , None ) } , removed= { getattr ( submission , ' removed ' , None ) } " )
matched_tag = None
if flair in self . tag_comments :
matched_tag = flair
else :
for tag in title_tags_lower :
if tag in self . tag_comments :
matched_tag = tag
break
# Detect filtered/removed posts
is_filtered = False
if getattr ( submission , ' removed_by_category ' , None ) :
is_filtered = True
if getattr ( submission , ' banned_by ' , None ) :
is_filtered = True
if getattr ( submission , ' mod_reason_title ' , None ) :
is_filtered = True
if getattr ( submission , ' spam ' , None ) :
is_filtered = True
if getattr ( submission , ' removed ' , None ) :
is_filtered = True
if is_filtered :
print ( f " [MODQUEUE WATCH] Post { submission . id } is filtered/removed. " )
# Comment only on filtered/removed posts with matching tags
if matched_tag and is_filtered and ( submission . id not in self . commented_posts ) :
status = self . tag_statuses . get ( matched_tag , ' enabled ' )
comment_text = self . tag_comments [ matched_tag ]
flair_id = self . tag_flair_ids . get ( matched_tag , ' ' )
if flair_id :
try :
submission . flair . select ( flair_id )
print ( f " [MODQUEUE WATCH] Set flair ' { flair_id } ' for post { submission . id } " )
except Exception as e :
print ( f " [MODQUEUE WATCH] Error setting flair ' { flair_id } ' for post { submission . id } : { e } " )
print ( f " Auto-commenting on filtered/removed post { submission . id } with tag ' { matched_tag } ' from modqueue " )
self . comment_only ( submission , comment_text )
except Exception as e :
print ( f " Modqueue watcher error: { e } " )
import time
time . sleep ( 30 )
2026-03-10 22:29:35 +00:00
threading . Thread ( target = tag_post_watcher , daemon = True ) . start ( )
2026-03-10 23:36:40 +00:00
threading . Thread ( target = modqueue_watcher , daemon = True ) . start ( )
2026-03-08 23:27:43 +00:00
# Keep main thread alive
2026-03-08 18:08:24 +00:00
while True :
2026-03-08 23:27:43 +00:00
import time
time . sleep ( 60 )
def handle_submission ( self , submission ) :
2026-03-10 18:37:11 +00:00
# Respond to mod reports containing trigger phrases
print ( f " New mod report detected: { submission . id } | Title: { submission . title } " )
matched_trigger = None
2026-03-08 23:27:43 +00:00
matched_comment = None
2026-03-10 15:10:39 +00:00
matched_status = None
2026-03-10 22:29:35 +00:00
matched_idx = None
2026-03-10 18:37:11 +00:00
# Check report reasons for triggers
if hasattr ( submission , ' mod_reports ' ) and submission . mod_reports :
for report_tuple in submission . mod_reports :
report_reason = report_tuple [ 0 ] . strip ( ) . lower ( )
for idx , trigger in enumerate ( self . triggers ) :
expected = f " ! { trigger . lower ( ) } "
if expected in report_reason :
matched_trigger = trigger
matched_comment = self . comments [ idx ]
matched_status = self . statuses [ idx ] if idx < len ( self . statuses ) else ' enabled '
2026-03-10 22:29:35 +00:00
matched_idx = idx
2026-03-10 18:37:11 +00:00
break
if matched_trigger :
break
if matched_trigger :
# Only skip if this exact trigger was already actioned for this post
trigger_key = f " { submission . id } : { matched_trigger } "
if hasattr ( self , ' triggered_posts ' ) :
if trigger_key in self . triggered_posts :
print ( f " Already actioned trigger [ { matched_trigger } ] on post { submission . id } , skipping. " )
return
else :
self . triggered_posts = set ( )
2026-03-08 21:32:51 +00:00
try :
2026-03-08 23:27:43 +00:00
footer = " ^I ^am ^a ^bot ^and ^this ^comment ^was ^made ^automatically. ^Message ^the ^Mod ^team ^if ^I ' m ^not ^working ^correctly. "
comment_text = matched_comment . replace ( " {{ author}} " , submission . author . name if submission . author else " unknown " ) + " \n \n " + footer
2026-03-10 22:29:35 +00:00
self . approve_and_comment ( submission , comment_text , matched_status , matched_idx )
self . triggered_posts . add ( trigger_key )
2026-03-08 21:32:51 +00:00
except Exception as e :
2026-03-10 18:37:11 +00:00
print ( f " Error commenting on mod report: { e } " )
2026-03-08 23:27:43 +00:00
else :
2026-03-10 18:37:11 +00:00
print ( f " No matching trigger found in mod report for post { submission . id } " )
2026-03-08 18:08:24 +00:00
2026-03-08 21:32:51 +00:00
def handle_comment ( self , comment ) :
comment_body = comment . body . lower ( )
for idx , trigger in enumerate ( self . triggers ) :
expected = f " ! { trigger . lower ( ) } "
2026-03-08 23:27:43 +00:00
words = [ w . strip ( ) for w in comment_body . split ( ) ]
# Only respond if author is a moderator
if expected in words and comment . author and comment . author in self . subreddit . moderator ( ) :
2026-03-10 15:10:39 +00:00
status = self . statuses [ idx ] if idx < len ( self . statuses ) else ' enabled '
if status == ' disabled ' :
print ( f " Trigger ' { trigger } ' is disabled. Skipping. " )
continue
2026-03-08 21:32:51 +00:00
try :
comment . mod . remove ( )
print ( f " Removed triggering comment: { comment . id } " )
except Exception as e :
print ( f " Error removing comment: { e } " )
submission = comment . submission
self . fetch_yaml_config ( )
2026-03-10 22:29:35 +00:00
self . approve_and_comment ( submission , self . comments [ idx ] , status , idx )
2026-03-08 21:32:51 +00:00
break
2026-03-08 18:08:24 +00:00
2026-03-10 22:29:35 +00:00
def approve_and_comment ( self , submission , comment_text , status = ' enabled ' , trigger_idx = None ) :
2026-03-08 18:08:24 +00:00
try :
2026-03-10 22:29:35 +00:00
print ( f " [DEBUG] approve_and_comment called with trigger_idx= { trigger_idx } " )
if trigger_idx is not None :
print ( f " [DEBUG] Config for trigger_idx= { trigger_idx } : lock_post= { self . lock_post [ trigger_idx ] } , stickied= { self . stickied [ trigger_idx ] } , lock_comment= { self . lock_comment [ trigger_idx ] } , flair_id= { self . flair_ids [ trigger_idx ] } " )
# Approve post if configured for this trigger
# Set flair, stickied, lock_post, lock_comment if configured for this trigger
if trigger_idx is not None :
flair_id = self . flair_ids [ trigger_idx ]
if flair_id :
try :
submission . flair . select ( flair_id )
print ( f " [DEBUG] Set flair ' { flair_id } ' for post { submission . id } " )
except Exception as e :
print ( f " [DEBUG] Error setting flair ' { flair_id } ' for post { submission . id } : { e } " )
print ( f " [DEBUG] lock_post[ { trigger_idx } ] = { self . lock_post [ trigger_idx ] } " )
if self . lock_post [ trigger_idx ] :
try :
submission . mod . lock ( )
print ( f " [DEBUG] Locked post { submission . id } " )
except Exception as e :
print ( f " [DEBUG] Error locking post { submission . id } : { e } " )
2026-03-10 15:10:39 +00:00
if status == ' enabled ' :
2026-03-10 22:29:35 +00:00
print ( f " [DEBUG] Submission object: { submission } , ID: { submission . id } , Type: { type ( submission ) } " )
2026-03-10 15:10:39 +00:00
comment = submission . reply ( comment_text )
2026-03-10 22:29:35 +00:00
print ( f " [DEBUG] Comment object: { comment } , ID: { comment . id } , Type: { type ( comment ) } " )
# Always sticky if stickied is True, match tag logic
if trigger_idx is not None and self . stickied [ trigger_idx ] :
try :
result = comment . mod . distinguish ( sticky = True )
print ( f " [DEBUG] Stickied bot comment { comment . id } on post { submission . id } , result: { result } " )
except Exception as e :
print ( f " [DEBUG] Error stickying comment { comment . id } on post { submission . id } : { e } " )
else :
try :
result = comment . mod . distinguish ( )
print ( f " [DEBUG] Distinguished bot comment { comment . id } on post { submission . id } , result: { result } " )
except Exception as e :
print ( f " [DEBUG] Error distinguishing comment { comment . id } on post { submission . id } : { e } " )
if trigger_idx is not None and self . lock_comment [ trigger_idx ] :
try :
comment . mod . lock ( )
print ( f " [DEBUG] Locked bot comment { comment . id } on post { submission . id } " )
except Exception as e :
print ( f " [DEBUG] Error locking comment { comment . id } on post { submission . id } : { e } " )
2026-03-10 15:10:39 +00:00
print ( f " Approved and commented on: { submission . id } " )
self . save_commented_post ( submission . id )
elif status == ' log-only ' :
print ( f " Log-only: Approved but did not comment on: { submission . id } " )
self . save_commented_post ( submission . id )
elif status == ' disabled ' :
print ( f " Disabled: Did not approve/comment/log for: { submission . id } " )
else :
print ( f " Unknown status ' { status } ' for submission { submission . id } " )
2026-03-08 18:08:24 +00:00
except Exception as e :
print ( f " Error approving/commenting: { e } " )
2026-03-08 23:27:43 +00:00
def notify_mods_config_change ( self , revision_id ) :
try :
subject = " ModReplyBot config wiki changed "
body = f " The config wiki page was updated (revision: { revision_id } ). \n \n Bot restarted and is running successfully. "
data = {
" subject " : subject ,
" text " : body ,
" to " : f " /r/ { Config . SUBREDDIT } " ,
}
self . reddit . post ( " api/compose/ " , data = data )
print ( " Sent modmail notification about config change. " )
except Exception as e :
print ( f " Error sending modmail notification: { e } " )
2026-03-08 18:08:24 +00:00
if __name__ == " __main__ " :
2026-03-10 18:37:11 +00:00
bot = ModReplyBot ( )
2026-03-08 18:08:24 +00:00
bot . run ( )