66import sys
77import threading
88import time
9- from typing import Optional
109
1110# lib imports
1211import praw
@@ -43,8 +42,14 @@ def __init__(self, **kwargs):
4342
4443 # directories
4544 self .data_dir = common .data_dir
45+ self .commands_dir = os .path .join (self .data_dir , "support-bot-commands" , "docs" )
46+
47+ # files
48+ self .db = os .path .join (self .data_dir , 'reddit_bot_database' )
49+
50+ # locks
51+ self .lock = threading .Lock ()
4652
47- self .last_online_file = os .path .join (self .data_dir , 'last_online' )
4853 self .reddit = praw .Reddit (
4954 client_id = os .environ ['PRAW_CLIENT_ID' ],
5055 client_secret = os .environ ['PRAW_CLIENT_SECRET' ],
@@ -55,6 +60,9 @@ def __init__(self, **kwargs):
5560 )
5661 self .subreddit = self .reddit .subreddit (self .subreddit_name ) # "AskReddit" for faster testing of submission loop
5762
63+ self .migrate_shelve ()
64+ self .migrate_last_online ()
65+
5866 @staticmethod
5967 def validate_env () -> bool :
6068 required_env = [
@@ -70,9 +78,43 @@ def validate_env() -> bool:
7078 return False
7179 return True
7280
81+ def migrate_last_online (self ):
82+ if os .path .isfile (os .path .join (self .data_dir , 'last_online' )):
83+ os .remove (os .path .join (self .data_dir , 'last_online' ))
84+
85+ def migrate_shelve (self ):
86+ with self .lock , shelve .open (self .db ) as db :
87+ if 'submissions' not in db and 'comments' not in db :
88+ db ['comments' ] = {}
89+ db ['submissions' ] = {}
90+ submissions = db ['submissions' ]
91+ for k , v in db .items ():
92+ if k not in ['comments' , 'submissions' ]:
93+ submissions [k ] = v
94+ assert submissions [k ] == v
95+ db ['submissions' ] = submissions
96+ keys_to_delete = [k for k in db if k not in ['comments' , 'submissions' ]]
97+ for k in keys_to_delete :
98+ del db [k ]
99+ assert k not in db
100+
73101 def process_comment (self , comment : models .Comment ):
74- # todo
75- pass
102+ with self .lock , shelve .open (self .db ) as db :
103+ comments = db .get ('comments' , {})
104+ if comment .id in comments and comments [comment .id ].get ('processed' , False ):
105+ return
106+
107+ comments [comment .id ] = {
108+ 'author' : str (comment .author ),
109+ 'body' : comment .body ,
110+ 'created_utc' : comment .created_utc ,
111+ 'processed' : True ,
112+ 'slash_command' : {'project' : None , 'command' : None },
113+ }
114+ # the shelve doesn't update unless we recreate the main key
115+ db ['comments' ] = comments
116+
117+ self .slash_commands (comment = comment )
76118
77119 def process_submission (self , submission : models .Submission ):
78120 """
@@ -83,44 +125,28 @@ def process_submission(self, submission: models.Submission):
83125 submission : praw.models.Submission
84126 The submission to process.
85127 """
86- last_online = self .get_last_online ()
87-
88- if last_online < submission .created_utc :
128+ with self .lock , shelve .open (self .db ) as db :
129+ submissions = db .get ('submissions' , {})
130+ if submission .id not in submissions :
131+ submissions [submission .id ] = {}
132+ submission_exists = False
133+ else :
134+ submission_exists = True
135+
136+ # the shelve doesn't update unless we recreate the main key
137+ submissions [submission .id ].update (vars (submission ))
138+ db ['submissions' ] = submissions
139+
140+ if not submission_exists :
89141 print (f'submission id: { submission .id } ' )
90142 print (f'submission title: { submission .title } ' )
91143 print ('---------' )
144+ if os .getenv ('DISCORD_WEBHOOK' ):
145+ self .discord (submission = submission )
146+ self .flair (submission = submission )
147+ self .karma (submission = submission )
92148
93- with shelve .open (os .path .join (self .data_dir , 'reddit_bot_database' )) as db :
94- try :
95- db [submission .id ]
96- except KeyError :
97- submission_exists = False
98- db [submission .id ] = vars (submission )
99- else :
100- submission_exists = True
101-
102- if submission_exists :
103- for k , v in vars (submission ).items (): # update the database with current values
104- try :
105- if db [submission .id ][k ] != v :
106- db [submission .id ][k ] = v
107- except KeyError :
108- db [submission .id ][k ] = v
109-
110- else :
111- try :
112- os .environ ['DISCORD_WEBHOOK' ]
113- except KeyError :
114- pass
115- else :
116- db = self .discord (db = db , submission = submission )
117- db = self .flair (db = db , submission = submission )
118- db = self .karma (db = db , submission = submission )
119-
120- # re-write the last online time
121- self .last_online_writer ()
122-
123- def discord (self , db : shelve .Shelf , submission : models .Submission ) -> Optional [shelve .Shelf ]:
149+ def discord (self , submission : models .Submission ):
124150 """
125151 Send a discord message.
126152
@@ -180,54 +206,45 @@ def discord(self, db: shelve.Shelf, submission: models.Submission) -> Optional[s
180206 r = requests .post (os .environ ['DISCORD_WEBHOOK' ], json = discord_webhook )
181207
182208 if r .status_code == 204 : # successful completion of request, no additional content
183- # update the database
184- db [submission .id ]['bot_discord' ] = {'sent' : True , 'sent_utc' : int (time .time ())}
209+ with self .lock , shelve .open (self .db ) as db :
210+ # the shelve doesn't update unless we recreate the main key
211+ submissions = db ['submissions' ]
212+ submissions [submission .id ]['bot_discord' ] = {'sent' : True , 'sent_utc' : int (time .time ())}
213+ db ['submissions' ] = submissions
185214
186- return db
187-
188- def flair (self , db : shelve .Shelf , submission : models .Submission ) -> shelve .Shelf :
189- # todo
190- return db
191-
192- def karma (self , db : shelve .Shelf , submission : models .Submission ) -> shelve .Shelf :
215+ def flair (self , submission : models .Submission ):
193216 # todo
194- return db
217+ pass
195218
196- def commands (self , db : shelve . Shelf , submission : models .Submission ) -> shelve . Shelf :
219+ def karma (self , submission : models .Submission ):
197220 # todo
198- return db
199-
200- def last_online_writer (self ) -> int :
201- """
202- Write the current time to the last online file.
203-
204- Returns
205- -------
206- int
207- The current time.
208- """
209- last_online = int (time .time ())
210- with open (self .last_online_file , 'w' ) as f :
211- f .write (str (last_online ))
212-
213- return last_online
214-
215- def get_last_online (self ) -> int :
216- """
217- Get the last online time.
218-
219- Returns
220- -------
221- int
222- The last online time.
223- """
224- try :
225- with open (self .last_online_file , 'r' ) as f :
226- last_online = int (f .read ())
227- except FileNotFoundError :
228- last_online = self .last_online_writer ()
221+ pass
229222
230- return last_online
223+ def slash_commands (self , comment : models .Comment ):
224+ if comment .body .startswith ("/" ):
225+ print (f"Processing slash command: { comment .body } " )
226+ # Split the comment into project and command
227+ parts = comment .body [1 :].split ()
228+ project = parts [0 ]
229+ command = parts [1 ] if len (parts ) > 1 else None
230+
231+ # Check if the command file exists in self.commands_dir
232+ command_file = os .path .join (self .commands_dir , project , f"{ command } .md" ) if command else None
233+ if command_file and os .path .isfile (command_file ):
234+ # Open the markdown file and read its contents
235+ with open (command_file , 'r' , encoding = 'utf-8' ) as file :
236+ file_contents = file .read ()
237+
238+ # Reply to the comment with the contents of the file
239+ comment .reply (file_contents )
240+ else :
241+ # Log error message
242+ print (f"Unknown command: { command } in project: { project } " )
243+ with self .lock , shelve .open (self .db ) as db :
244+ # the shelve doesn't update unless we recreate the main key
245+ comments = db ['comments' ]
246+ comments [comment .id ]['slash_command' ] = {'project' : project , 'command' : command }
247+ db ['comments' ] = comments
231248
232249 def _comment_loop (self , test : bool = False ):
233250 # process comments and then keep monitoring
0 commit comments