6
6
import sys
7
7
import threading
8
8
import time
9
- from typing import Optional
10
9
11
10
# lib imports
12
11
import praw
@@ -43,8 +42,14 @@ def __init__(self, **kwargs):
43
42
44
43
# directories
45
44
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 ()
46
52
47
- self .last_online_file = os .path .join (self .data_dir , 'last_online' )
48
53
self .reddit = praw .Reddit (
49
54
client_id = os .environ ['PRAW_CLIENT_ID' ],
50
55
client_secret = os .environ ['PRAW_CLIENT_SECRET' ],
@@ -55,6 +60,9 @@ def __init__(self, **kwargs):
55
60
)
56
61
self .subreddit = self .reddit .subreddit (self .subreddit_name ) # "AskReddit" for faster testing of submission loop
57
62
63
+ self .migrate_shelve ()
64
+ self .migrate_last_online ()
65
+
58
66
@staticmethod
59
67
def validate_env () -> bool :
60
68
required_env = [
@@ -70,9 +78,43 @@ def validate_env() -> bool:
70
78
return False
71
79
return True
72
80
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
+
73
101
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 )
76
118
77
119
def process_submission (self , submission : models .Submission ):
78
120
"""
@@ -83,44 +125,28 @@ def process_submission(self, submission: models.Submission):
83
125
submission : praw.models.Submission
84
126
The submission to process.
85
127
"""
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 :
89
141
print (f'submission id: { submission .id } ' )
90
142
print (f'submission title: { submission .title } ' )
91
143
print ('---------' )
144
+ if os .getenv ('DISCORD_WEBHOOK' ):
145
+ self .discord (submission = submission )
146
+ self .flair (submission = submission )
147
+ self .karma (submission = submission )
92
148
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 ):
124
150
"""
125
151
Send a discord message.
126
152
@@ -180,54 +206,45 @@ def discord(self, db: shelve.Shelf, submission: models.Submission) -> Optional[s
180
206
r = requests .post (os .environ ['DISCORD_WEBHOOK' ], json = discord_webhook )
181
207
182
208
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
185
214
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 ):
193
216
# todo
194
- return db
217
+ pass
195
218
196
- def commands (self , db : shelve . Shelf , submission : models .Submission ) -> shelve . Shelf :
219
+ def karma (self , submission : models .Submission ):
197
220
# 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
229
222
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
231
248
232
249
def _comment_loop (self , test : bool = False ):
233
250
# process comments and then keep monitoring
0 commit comments