From 0bca5c4c852497b7a674369aa937fb1b579b3ea3 Mon Sep 17 00:00:00 2001 From: Jon Berry Date: Sat, 9 May 2020 13:36:38 -0400 Subject: [PATCH 1/3] Inital work to migrate from python 2 to 3 - Updated moved from `dotenv` to `python-dotenv` for environment variable injection. - Handeled exceptions related to utf string formatting - Added additional logging for action dispatching Signed-off-by: Jon Berry --- .coverage | Bin 0 -> 53248 bytes actions/action_dispatch.py | 1 + actions/action_request.py | 23 +++++++++---- .../reddit/configuration/get_permissions.py | 10 +++--- actions/reddit/flair/bulk_update_from_csv.py | 2 +- actions/reddit/flair/rule_parse.py | 10 +++--- actions/reddit/flair/update_flair_text.py | 4 +-- .../reddit/flair/update_flair_text_by_user.py | 4 +-- .../reddit/flair/update_flair_with_rules.py | 14 ++++---- .../flair/update_flair_with_rules_by_user.py | 6 ++-- .../reddit/redditor/banned_relationship.py | 2 +- .../reddit/redditor/moderator_relationship.py | 2 +- bot.py | 32 +++++++++--------- messages/message_dispatcher.py | 2 +- permissions.json | 2 +- requirements.txt | 4 +-- rules.json | 2 +- runtime.txt | 2 +- start.py | 9 ++--- test-requirement.txt | 3 ++ 20 files changed, 74 insertions(+), 60 deletions(-) create mode 100644 .coverage create mode 100644 test-requirement.txt diff --git a/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..a5f84506d2a0d70b0c3796469262245b09e2e68a GIT binary patch literal 53248 zcmeI)PjAy^90zba4snwvn5n8FR#knZtqK)Q(*QjH(zY^sKm$!>2u+%{@FaQCnk9Cz zozfnrsW6EbFlp~#+HI$C+pFNTaoKUZB5|46VZWd4r%9ke+={~2YEu7sp2yGgdH%(* z+b=e+yO9zdKj_IwoHtGxrfGa4gkcy3dX?y<7n@eHdV_wOL+j&K3&zUjXC>#hQOx~h zINy}MbgIRlOSS2z#ohdm)4$kv^IbZC1p*L&00bZq3mj|~?egi<=7aAd+3cz)kS!G? z@1;*~Zmi$h5VzK^T;CAMK5?cXXsK4kx(NLHVn+p{<93yBy|&wuk?U=VXj|#f{ZO@e z#-n{S=W)Q5I6kj6+&0CE)D|VN6SzGY?2B*J{&E~3JzJ#qqGSgpqTDTyLx?kJ^d%9f zjtZ35Qel#dGj4mSu=Mczf?b}OF(0Y8OfqQE&-6%XXvd%^*E*C?%MaR|`(_}$*0u_l zg*+@_%cp$qMM-G`zgLTV(RIDJm|o~cuI~x8r&|3;wT~>|GNb8*@PKlXHzGvHG5Sudfa(e_0G-F2}|2{AIy~pcb$=ohx6QF%4>!YA?Lkr4L>W z*^m5qyFr!TsMA~VhxexJ^1_1o=w94Vn5WTnqwsJgKhkIpcaLd0e0+Sn;a)P@NVpeu zyTb3pU4~V3gE-Bt1gKsoJ^n`rNqUq~RL%bY<$m&f4YK zS@R(25j-yO>%>SQc+a2c?v@KrEJMX59S5D;0muJUioU_oV^Ly^$%}ku- zM|P~=qd}iv)<~9l&mha6sr~A%?9ynmBi(?yERDg*3?MjQTT)=z^!riVet9!)o;>#q z@|z?u*w*$GYAFs*-J4DnUeX()vMoa%e8P%o`hHhQFPRc3;I)uW<%S|Y^{bQ7$AdJ& zeNJO*w-RSX&nY~*-=e;zyA`eUdeUpB(-hCXNvbsDbD!k%Bx46f6cy@=A@$6c($tBj zM|q&q>96b%1*h7R?WC7;T@0moe_OqhTrvq=m63|vo)R1+&P?2%?#ocL0!0UD3SFvL zud98oq(+_J`6_veKgb*`n0EQ>S@WQu_Q7O$X@oSF_oU8tx|tbi8!sIkG?UM1oTU#r z!_9;3hB$aLIRlSrNewm=1sy8=h*MbN3w+agVbBj22tWV=5P$##AOHafKmY;|fB*z0 zPrx!Wrp?#?S?5>7`P=!!`JGmHCErZ ztl9JYyu!KFbF0pU@>C(d){ALp-QE+9@10SG_<0uX=z1Rwwb2tWV=5P-lN2^6h)Q-4K}ow8<4 z{)WJsw&u+A>wwI(HJ{ht1@Qg047k zWCQ{bfB*y_009U<00Izz00bZa0mJyvx?zsLv`?=8GmF+{etaN({g40uhXw@!2tWV= z5P$##AOHafKmY;|m}miuo)9SU{eRQ>&!8VH5P$##AOHafKmY;|fB*y_009V0pnzqS z^2y)-KQo+voo5qRL=*`E5P$##AOHafKmY;|fB*y_@NNp^GFdZ!GV{?1Gn>z!%q4&S z|J-n1IM3fr5R@7M5P$##AOHafKmY;|fB*y_Fqr~5`Ub$vWU}-HKz#q-I5nB&M5!PE z0SG_<0uX=z1Rwwb2tWV=5J&|0{y(n&(HbBC0SG_<0uX=z1Rwwb2tWV=lP$o1|Bvhc b$*yCR4gwH>00bZa0SG_<0uX=z1R(G~jiYmV literal 0 HcmV?d00001 diff --git a/actions/action_dispatch.py b/actions/action_dispatch.py index 5b4ccab..2f57301 100644 --- a/actions/action_dispatch.py +++ b/actions/action_dispatch.py @@ -29,6 +29,7 @@ def __init__(self, requestIdentifier, payload, reddit): 'BULK_UPDATE_FLAIRS': lambda: BulkUpdateFromCSV(payload, reddit).complete, } + # TODO: Catch errors parsing permissions, as this results in a loop otherwise. "config/permissions on the wiki having `PING` instead of `PINGPONG` caused loop." activePermissions = Permissions(reddit).currentPermissions botPermissions = activePermissions['bot'] requestPermissions = activePermissions['actions'][requestIdentifier] diff --git a/actions/action_request.py b/actions/action_request.py index 5ac2590..2dab6c5 100644 --- a/actions/action_request.py +++ b/actions/action_request.py @@ -1,6 +1,6 @@ import os import sys -from action_dispatch import ActionDispatch +from .action_dispatch import ActionDispatch class ActionRequest: # ActionRequest is triggered _any_ time a message is recieved. In short, init defines the list of possible actions, and known exceptions, and determines if the request will @@ -28,29 +28,38 @@ def __init__(self, request, payload, reddit): 'comment reply' ] - print('Message: /u/' + str(payload.author) + " sent '" + str(request) + "': " + str(payload.body) ) + # Decoding the initial request aftern utf-8 sanitization + decodedRequest = request.decode('utf-8') + + print('Message: /u/' + str(payload.author) + " sent '" + str(decodedRequest) + "': " + str(payload.body) ) sys.stdout.flush() # Try to see if requestIdentifier (the subject line of the dispatched message) is in the requestCommand dict # TODO - JRB: Suppport the passing of args in the requestIdentifier line try: - requestIdentifier = requestCommand[request] + requestIdentifier = requestCommand[decodedRequest] # Except messages where requestIdentifier does not exist in the requestCommand dict - except KeyError: - exception = request + except KeyError as e: + exception = decodedRequest # If this is a non-actionable message (such as notifications about replies to posts or comments, mark them as read and take no action.) if exception in knownExceptions: + print(str(decodedRequest) + " is on the list of known exceptions. Taking no action, marking message as read. ") + sys.stdout.flush() payload.mark_read() # Else dispatch a message and mark as read if the provided requestIdentifier doesn't exist in the requestCommand or knownExceptions dicts else: + print(str(decodedRequest) + " does not match a known action or known exception. Replying with error message...") + sys.stdout.flush() # TODO - JRB: I think this message should be more generic(?) - reddit.redditor(str(payload.author)).message('An Error Occurred', 'An error occured. Please contact the subreddit moderators.') + reddit.redditor(str(payload.author)).message('An Error Occurred', 'An error occured. Please contact the subreddit moderators: (Key Error: ' + str(e) + ')') payload.mark_read() # Catch all other excpetions except Exception as e: - reddit.redditor(str(payload.author)).message('An Error Occurred', 'An error occured. Please contact the subreddit moderators.') + reddit.redditor(str(payload.author)).message('An Error Occurred', 'An error occured. Please contact the subreddit moderators: (Exception: ' + str(e) + ')') payload.mark_read() # If all conditions are met, dispatch the action. else: + print(str(decodedRequest) + " matches action " + str(requestIdentifier) + ". Dispatching Action...") + sys.stdout.flush() ActionDispatch(requestIdentifier, payload, self.reddit) diff --git a/actions/reddit/configuration/get_permissions.py b/actions/reddit/configuration/get_permissions.py index 9e67fef..7edbbc1 100644 --- a/actions/reddit/configuration/get_permissions.py +++ b/actions/reddit/configuration/get_permissions.py @@ -19,19 +19,19 @@ def __init__(self, reddit): def get_permissions(self): try: - documentPath = os.environ.get("USERNAME") + '/config/permissions' + documentPath = os.getenv("USERNAME") + '/config/permissions' print("* Updating permissions") - print(" * Looking for permissions at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + documentPath + '...') + print(" * Looking for permissions at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + documentPath + '...') sys.stdout.flush() - permissionsDefinition = self.reddit.subreddit(os.environ.get("SUBREDDIT")).wiki[documentPath].content_md + permissionsDefinition = self.reddit.subreddit(os.getenv("SUBREDDIT")).wiki[documentPath].content_md except Exception as e: - print(" * No permissions found at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + documentPath + "") + print(" * No permissions found at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + documentPath + "") print("* Updating permissionss failed. Continuing with no active permissionss.") sys.stdout.flush() self.status = { 'statusCode': 400, 'subject': 'Error: Permissions Not Found', - 'message': "Permissions definition cannot be found. Confirm your permissions definition is located at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + path + " :" + str(e) + 'message': "Permissions definition cannot be found. Confirm your permissions definition is located at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + path + " :" + str(e) } else: self.parse_permissions(permissionsDefinition) diff --git a/actions/reddit/flair/bulk_update_from_csv.py b/actions/reddit/flair/bulk_update_from_csv.py index 01dfbbf..9a3ee48 100644 --- a/actions/reddit/flair/bulk_update_from_csv.py +++ b/actions/reddit/flair/bulk_update_from_csv.py @@ -15,7 +15,7 @@ def __init__(self, payload, reddit): remoteURL = str(payload.body) - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) flair_dicts = [] diff --git a/actions/reddit/flair/rule_parse.py b/actions/reddit/flair/rule_parse.py index c2c0305..895a3a4 100644 --- a/actions/reddit/flair/rule_parse.py +++ b/actions/reddit/flair/rule_parse.py @@ -19,19 +19,19 @@ def __init__(self, reddit): def get_rules(self): try: - path = os.environ.get("USERNAME") + '/rules' + path = os.getenv("USERNAME") + '/rules' print("* Updating rulesets") - print(" * Looking for ruleset at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + path + '...') + print(" * Looking for ruleset at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + path + '...') sys.stdout.flush() - ruledef = self.reddit.subreddit(os.environ.get("SUBREDDIT")).wiki[path].content_md + ruledef = self.reddit.subreddit(os.getenv("SUBREDDIT")).wiki[path].content_md except Exception as e: - print(" * No ruleset found at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + path + "") + print(" * No ruleset found at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + path + "") print("* Updating rulesets failed. Continuing with no active rulesets.") sys.stdout.flush() self.status = { 'statusCode': 400, 'subject': 'Error: Flair Rules Not Found', - 'message': "Ruleset cannot be found. Confirm your ruleset is located at reddit.com/r/" + os.environ.get("SUBREDDIT") + '/wiki/' + path + " :" + str(e) + 'message': "Ruleset cannot be found. Confirm your ruleset is located at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + path + " :" + str(e) } else: self.parse_rules(ruledef) diff --git a/actions/reddit/flair/update_flair_text.py b/actions/reddit/flair/update_flair_text.py index fbea749..6d28c6b 100644 --- a/actions/reddit/flair/update_flair_text.py +++ b/actions/reddit/flair/update_flair_text.py @@ -14,7 +14,7 @@ def __init__(self, payload, reddit): author = str(payload.author) content = str(payload.body) current_class = None - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) for user in subreddit.flair.__call__(redditor=author): @@ -24,7 +24,7 @@ def __init__(self, payload, reddit): self.status['statusCode'] = 200 self.status['subject'] = 'Flair Changed' - self.status['message'] = author + ', your flair on /r/' + os.environ.get("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' + self.status['message'] = author + ', your flair on /r/' + os.getenv("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' @property diff --git a/actions/reddit/flair/update_flair_text_by_user.py b/actions/reddit/flair/update_flair_text_by_user.py index 5f5a119..6dc77a4 100644 --- a/actions/reddit/flair/update_flair_text_by_user.py +++ b/actions/reddit/flair/update_flair_text_by_user.py @@ -14,7 +14,7 @@ def __init__(self, payload, reddit): author = str(payload.author) content = str(payload.body) current_class = None - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) for user in subreddit.flair.__call__(redditor=author): @@ -24,7 +24,7 @@ def __init__(self, payload, reddit): self.status['statusCode'] = 200 self.status['subject'] = 'Flair Changed' - self.status['message'] = author + ', your flair on /r/' + os.environ.get("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' + self.status['message'] = author + ', your flair on /r/' + os.getenv("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' @property diff --git a/actions/reddit/flair/update_flair_with_rules.py b/actions/reddit/flair/update_flair_with_rules.py index 7e61acc..80b45c8 100644 --- a/actions/reddit/flair/update_flair_with_rules.py +++ b/actions/reddit/flair/update_flair_with_rules.py @@ -5,7 +5,7 @@ import re import calendar from time import gmtime, strftime -from rule_parse import Rules +from .rule_parse import Rules class UpdateFlairWithRules: @@ -26,7 +26,7 @@ def __init__(self, payload, reddit): } current_class = '' new_class = '' - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) for user in subreddit.flair.__call__(redditor=author): @@ -39,8 +39,8 @@ def __init__(self, payload, reddit): except KeyError: ruleset = False self.status['statusCode'] = 200 - self.status['subject'] = 'Invalid Flair for /r/' + os.environ.get("SUBREDDIT") - self.status['message'] = '/u/' + author + ',\n\nThe flair you requested ("' + content + '") is not valid. Please try again.\n\nPlease go to the [list of available flairs](https://www.reddit.com/r/survivor/wiki/available_flairs) and follow the instructions provided.\n\nIf you continue to experience errors, please [message the /r/' + os.environ.get("SUBREDDIT") + ' moderators](https://www.reddit.com/message/compose/?to=/r/Survivor&subject=Help%20with%20flair) for help.' + self.status['subject'] = 'Invalid Flair for /r/' + os.getenv("SUBREDDIT") + self.status['message'] = '/u/' + author + ',\n\nThe flair you requested ("' + content + '") is not valid. Please try again.\n\nPlease go to the [list of available flairs](https://www.reddit.com/r/survivor/wiki/available_flairs) and follow the instructions provided.\n\nIf you continue to experience errors, please [message the /r/' + os.getenv("SUBREDDIT") + ' moderators](https://www.reddit.com/message/compose/?to=/r/Survivor&subject=Help%20with%20flair) for help.' else: process_rules = Rules(reddit).currentRules process_rules = process_rules[ruleset] @@ -73,11 +73,11 @@ def __init__(self, payload, reddit): except: self.status['statusCode'] = 200 self.status['subject'] = 'An Error Occurred' - self.status['message'] = author + ', your requested flair of "' + content + '" on /r/' + os.environ.get("SUBREDDIT") + ' is not valid. This bot is in beta. Is this an error? Please contact your moderator.' + self.status['message'] = author + ', your requested flair of "' + content + '" on /r/' + os.getenv("SUBREDDIT") + ' is not valid. This bot is in beta. Is this an error? Please contact your moderator.' else: self.status['statusCode'] = 200 - self.status['subject'] = '/r/' + os.environ.get("SUBREDDIT") + ' Flair Updated' - self.status['message'] = '/u/' + author + ',\n\nYour flair has been updated to "' + content + '".\n\nIf your updated flair is incorrect, [message the /r/' + os.environ.get("SUBREDDIT") + ' moderators](https://www.reddit.com/message/compose/?to=/r/Survivor&subject=Help%20with%20flair) for help.' + self.status['subject'] = '/r/' + os.getenv("SUBREDDIT") + ' Flair Updated' + self.status['message'] = '/u/' + author + ',\n\nYour flair has been updated to "' + content + '".\n\nIf your updated flair is incorrect, [message the /r/' + os.getenv("SUBREDDIT") + ' moderators](https://www.reddit.com/message/compose/?to=/r/Survivor&subject=Help%20with%20flair) for help.' @property diff --git a/actions/reddit/flair/update_flair_with_rules_by_user.py b/actions/reddit/flair/update_flair_with_rules_by_user.py index abc9199..bce297b 100644 --- a/actions/reddit/flair/update_flair_with_rules_by_user.py +++ b/actions/reddit/flair/update_flair_with_rules_by_user.py @@ -5,7 +5,7 @@ import re import calendar from time import gmtime, strftime -from rule_parse import Rules +from .rule_parse import Rules class UpdateFlairWithRulesByUser: @@ -19,7 +19,7 @@ def __init__(self, payload, reddit): content = str(payload.body) current_class = None new_class = '' - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) for user in subreddit.flair.__call__(redditor=author): @@ -55,7 +55,7 @@ def __init__(self, payload, reddit): self.status['statusCode'] = 200 self.status['subject'] = 'Flair Changed' - self.status['message'] = author + ', your flair on /r/' + os.environ.get("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' + self.status['message'] = author + ', your flair on /r/' + os.getenv("SUBREDDIT") + ' has been updated to: ' + content + '. This bot is in beta. Not seeing your flair update? Please contact your moderator.' @property diff --git a/actions/reddit/redditor/banned_relationship.py b/actions/reddit/redditor/banned_relationship.py index adaeb60..7f2a47a 100644 --- a/actions/reddit/redditor/banned_relationship.py +++ b/actions/reddit/redditor/banned_relationship.py @@ -16,7 +16,7 @@ def __init__(self, payload, reddit): 'message': str(userToCheck) } - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) callBannedList = subreddit.banned.__call__(redditor=userToCheck) self.is_banned = userToCheck in callBannedList diff --git a/actions/reddit/redditor/moderator_relationship.py b/actions/reddit/redditor/moderator_relationship.py index e888811..93d8b14 100644 --- a/actions/reddit/redditor/moderator_relationship.py +++ b/actions/reddit/redditor/moderator_relationship.py @@ -16,7 +16,7 @@ def __init__(self, payload, reddit): 'message': str(userToCheck) } - target_sub = os.environ.get("SUBREDDIT") + target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) callModeratorList = subreddit.moderator.__call__(redditor=userToCheck) self.is_moderator = userToCheck in callModeratorList diff --git a/bot.py b/bot.py index c722997..66e1180 100644 --- a/bot.py +++ b/bot.py @@ -16,26 +16,26 @@ class Bot: def __init__(self): # Initializtion. - if os.environ.get("LOGGING"): + if os.getenv("LOGGING"): os.chdir(os.path.dirname(os.path.abspath(__file__))) else: self.logging = False print('') - print('Bot: Starting /u/' + os.environ.get("USERNAME") + ' for subreddit /r/' + os.environ.get("SUBREDDIT")) + print('Bot: Starting /u/' + os.getenv("USERNAME") + ' for subreddit /r/' + os.getenv("SUBREDDIT")) sys.stdout.flush() self.login() def login(self): - print('* Authenticating /u/' + os.environ.get("USERNAME") + ' on reddit.com') + print('* Authenticating /u/' + os.getenv("USERNAME") + ' on reddit.com') sys.stdout.flush() - app_id = os.environ.get("APP_ID") - app_secret = os.environ.get("APP_SECRET") - user_agent = "Flair Updater for /r/" + os.environ.get("SUBREDDIT") + app_id = os.getenv("APP_ID") + app_secret = os.getenv("APP_SECRET") + user_agent = "Flair Updater for /r/" + os.getenv("SUBREDDIT") - username = os.environ.get("USERNAME") - password = os.environ.get("USER_PASSWORD") + username = os.getenv("USERNAME") + password = os.getenv("USER_PASSWORD") try: print(' * Signing in...') @@ -49,37 +49,37 @@ def login(self): print(' * Failed to authenticate: ' + str(e)) sys.stdout.flush() else: - print('* Authenticated /u/' + os.environ.get("USERNAME") + ' on reddit.com') + print('* Authenticated /u/' + os.getenv("USERNAME") + ' on reddit.com') sys.stdout.flush() self.run() - # print('* Authenticated /u/' + os.environ.get("USERNAME") + ' on reddit.com') + # print('* Authenticated /u/' + os.getenv("USERNAME") + ' on reddit.com') # self.run() def run(self): - print('Bot: Started /u/' + os.environ.get("USERNAME") + ' at ' + str(datetime.datetime.now())) + print('Bot: Started /u/' + os.getenv("USERNAME") + ' at ' + str(datetime.datetime.now())) print('') sys.stdout.flush() # Get the initial set of rules. This should probaby be split out into a separate initilization lifecycle script. - print('Bot: Initializing /u/' + os.environ.get("USERNAME") + ' for subreddit /r/' + os.environ.get("SUBREDDIT")) + print('Bot: Initializing /u/' + os.getenv("USERNAME") + ' for subreddit /r/' + os.getenv("SUBREDDIT")) sys.stdout.flush() currentPermissions = Permissions(self.reddit).currentPermissions currentRules = Rules(self.reddit).currentRules - print('Bot: /u/' + os.environ.get("USERNAME") + ' successfully initialized at ' + str(datetime.datetime.now())) + print('Bot: /u/' + os.getenv("USERNAME") + ' successfully initialized at ' + str(datetime.datetime.now())) sys.stdout.flush() # Starts running the bot... running = True print('') - print('Bot: /u/' + os.environ.get("USERNAME") + " running from " + str(datetime.datetime.now())) + print('Bot: /u/' + os.getenv("USERNAME") + " running from " + str(datetime.datetime.now())) sys.stdout.flush() while running: try: MessageReceiver(self.reddit) - time.sleep(int(os.environ.get("REFRESH_INTERVAL"))) + time.sleep(int(os.getenv("REFRESH_INTERVAL"))) except Exception as e: - time.sleep(int(os.environ.get("REFRESH_INTERVAL"))) + time.sleep(int(os.getenv("REFRESH_INTERVAL"))) return 0 diff --git a/messages/message_dispatcher.py b/messages/message_dispatcher.py index 9f992a3..cb889aa 100644 --- a/messages/message_dispatcher.py +++ b/messages/message_dispatcher.py @@ -18,7 +18,7 @@ def __init__(self, payload, response, reddit): elif response['statusCode'] == 204: payload.mark_read() elif response['statusCode'] == 400: - reddit.redditor('/r/' + os.environ.get("SUBREDDIT")).message(response['subject'], response['message']) + reddit.redditor('/r/' + os.getenv("SUBREDDIT")).message(response['subject'], response['message']) payload.mark_read() else: payload.mark_read() \ No newline at end of file diff --git a/permissions.json b/permissions.json index 88eb4c9..e385153 100644 --- a/permissions.json +++ b/permissions.json @@ -1 +1 @@ -{"bot": {"restrictedUsers": [], "restrictedRelationships": ["banned"]}, "actions": {"BULK_UPDATE_FLAIRS": {"restrictedUsers": [], "authorizedUsers": ["Gariond"], "authorizedRelationships": []}, "UPDATE_FLAIR_WITH_RULES": {"restrictedUsers": [], "authorizedUsers": [], "authorizedRelationships": ["moderator", "redditor"]}, "UPDATE_RULES": {"restrictedUsers": [], "authorizedUsers": [], "authorizedRelationships": ["moderator"]}, "PING": {"restrictedUsers": [], "authorizedUsers": [], "authorizedRelationships": ["moderator"]}, "UPDATE_FLAIR_TEXT": {"restrictedUsers": [], "authorizedUsers": [], "authorizedRelationships": ["moderator"]}}} \ No newline at end of file +{"actions": {"PINGPONG": {"authorizedRelationships": ["moderator"], "authorizedUsers": [], "restrictedUsers": []}, "UPDATE_FLAIR_TEXT": {"authorizedRelationships": ["moderator"], "authorizedUsers": [], "restrictedUsers": []}, "UPDATE_FLAIR_WITH_RULES": {"authorizedRelationships": ["moderator", "redditor"], "authorizedUsers": [], "restrictedUsers": []}, "UPDATE_RULES": {"authorizedRelationships": ["moderator"], "authorizedUsers": [], "restrictedUsers": []}, "BULK_UPDATE_FLAIRS": {"authorizedRelationships": [], "authorizedUsers": ["Gariond"], "restrictedUsers": []}}, "bot": {"restrictedRelationships": ["banned"], "restrictedUsers": []}} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9823711..16c06e4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -praw==5.0.1 +praw==7.0.0 configparser==3.5.0 -dotenv==0.0.5 \ No newline at end of file +python-dotenv==0.13.0 \ No newline at end of file diff --git a/rules.json b/rules.json index ea45a14..37f902b 100644 --- a/rules.json +++ b/rules.json @@ -1 +1 @@ -{"rules": [{"set": {"text": ["Queen Sandra", "President Sarah Lacina", "Troyzan's Island", "F*** you, Brad Culpepper!", "Depth Charge", "Dogs Samsung Chinese lol", "This is a dictatorship - majority rules.", "\"Hero\"", "\"Healer\"", "\"Hustler\""], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "X", "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "type": "string"}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "GreyFlairs"}}, {"set": {"text": ["A.K. (AUS)", "Adam (AUS)", "Aimee (AUS)", "Anneliese (AUS)", "Ben (AUS)", "Henry (AUS)", "Jacqui (AUS)", "Jarrad (AUS)", "Jericho (AUS)", "Joan (AUS)", "Kate (AUS)", "Kent (AUS)", "Locky (AUS)", "Luke (AUS)", "Mark H (AUS)", "Tarzan (AUS)", "Mark W (AUS)", "Michelle (AUS)", "Odette (AUS)", "Peter (AUS)", "Sam (AUS)", "Sarah (AUS)", "Tara (AUS)", "Tessa (AUS)", "Ziggy (AUS)"], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "AUS17", "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "type": "string"}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "AustralianSurvivor2017"}}, {"set": {"text": ["Alan", "Ben", "Cole", "Devon", "Joe", "John", "Mike", "Patrick", "Ryan", "Alexandrea", "Ashley", "Christine", "Desiree", "Jessica", "Katrina", "Lauren", "Roark", "Simone"], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "35Gold", "limit": {"available": 0, "expires": 1507161600, "usergroup": "all"}, "type": "string"}, {"content": "35Silver", "limit": {"available": 1507161601, "expires": 9999999999, "usergroup": "all"}, "type": "string"}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "Season35"}}]} \ No newline at end of file +{"rules": [{"set": {"text": ["Queen Sandra", "President Sarah Lacina", "Troyzan's Island", "F*** you, Brad Culpepper!", "Depth Charge", "Dogs Samsung Chinese lol", "This is a dictatorship - majority rules.", "\"Hero\"", "\"Healer\"", "\"Hustler\""], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "X", "type": "string", "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "GreyFlairs"}}, {"set": {"text": ["A.K. (AUS)", "Adam (AUS)", "Aimee (AUS)", "Anneliese (AUS)", "Ben (AUS)", "Henry (AUS)", "Jacqui (AUS)", "Jarrad (AUS)", "Jericho (AUS)", "Joan (AUS)", "Kate (AUS)", "Kent (AUS)", "Locky (AUS)", "Luke (AUS)", "Mark H (AUS)", "Tarzan (AUS)", "Mark W (AUS)", "Michelle (AUS)", "Odette (AUS)", "Peter (AUS)", "Sam (AUS)", "Sarah (AUS)", "Tara (AUS)", "Tessa (AUS)", "Ziggy (AUS)"], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "AUS17", "type": "string", "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "AustralianSurvivor2017"}}, {"set": {"text": ["Alan", "Ben", "Cole", "Devon", "Joe", "John", "Mike", "Patrick", "Ryan", "Alexandrea", "Ashley", "Christine", "Desiree", "Jessica", "Katrina", "Lauren", "Roark", "Simone"], "limit": {"available": 0, "expires": 9999999999, "usergroup": "all"}, "class": [{"content": "35Gold", "type": "string", "limit": {"available": 0, "expires": 1507161600, "usergroup": "all"}}, {"content": "35Silver", "type": "string", "limit": {"available": 1507161601, "expires": 9999999999, "usergroup": "all"}}, {"content": " W", "type": "string"}, {"content": "(?<=W)(.*?)(?=W)", "type": "regex"}, {"content": "W ", "type": "string"}, {"content": "W.*W(.*)", "type": "regex"}], "setname": "Season35"}}]} \ No newline at end of file diff --git a/runtime.txt b/runtime.txt index ba85ab9..21bd0aa 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-2.7.13 \ No newline at end of file +python-3.7.5 \ No newline at end of file diff --git a/start.py b/start.py index 6f09eca..42685e9 100644 --- a/start.py +++ b/start.py @@ -2,11 +2,12 @@ from bot import Bot # Load env and initialize bot -if os.environ.get("APP_ID") is None: +if os.getenv("APP_ID") is None: from os.path import join, dirname - from dotenv import Dotenv + from dotenv import load_dotenv - dotenv = Dotenv(os.path.join(os.path.dirname(__file__), ".env")) - os.environ.update(dotenv) + load_dotenv() + # dotenv = Dotenv(os.path.join(os.path.dirname(__file__), ".env")) + # os.environ.update(dotenv) Bot() diff --git a/test-requirement.txt b/test-requirement.txt new file mode 100644 index 0000000..9823711 --- /dev/null +++ b/test-requirement.txt @@ -0,0 +1,3 @@ +praw==5.0.1 +configparser==3.5.0 +dotenv==0.0.5 \ No newline at end of file From c00bd6578d2315b9f41739fa55f1cc868d073322 Mon Sep 17 00:00:00 2001 From: Jon Berry Date: Sat, 9 May 2020 15:03:26 -0400 Subject: [PATCH 2/3] Additional Python 3 compatability updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated permissions related errors to reflect the actual path needed for permissions management and definition. - Resolved an issue related to utilizing a deprecated “urllib” module - Resolved an issue where regular expression parameters were being passed to conditional flar logic in the wrong encoding type. Signed-off-by: Jon Berry --- .../reddit/configuration/get_permissions.py | 2 +- actions/reddit/flair/bulk_update_from_csv.py | 4 +-- .../reddit/flair/update_flair_with_rules.py | 28 ++++++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/actions/reddit/configuration/get_permissions.py b/actions/reddit/configuration/get_permissions.py index 7edbbc1..c569d3e 100644 --- a/actions/reddit/configuration/get_permissions.py +++ b/actions/reddit/configuration/get_permissions.py @@ -31,7 +31,7 @@ def get_permissions(self): self.status = { 'statusCode': 400, 'subject': 'Error: Permissions Not Found', - 'message': "Permissions definition cannot be found. Confirm your permissions definition is located at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki/' + path + " :" + str(e) + 'message': "Permissions definition cannot be found. Confirm your permissions definition is located at reddit.com/r/" + os.getenv("SUBREDDIT") + '/wiki' + documentPath + " :" + str(e) } else: self.parse_permissions(permissionsDefinition) diff --git a/actions/reddit/flair/bulk_update_from_csv.py b/actions/reddit/flair/bulk_update_from_csv.py index 9a3ee48..93b4e40 100644 --- a/actions/reddit/flair/bulk_update_from_csv.py +++ b/actions/reddit/flair/bulk_update_from_csv.py @@ -1,7 +1,7 @@ import os import sys import csv -import urllib +import urllib.request import praw class BulkUpdateFromCSV: @@ -23,7 +23,7 @@ def __init__(self, payload, reddit): keys = ['user', 'flair_text', 'flair_css_class'] print('starting bulk update') sys.stdout.flush() - remoteFile = urllib.urlretrieve(remoteURL) + remoteFile = urllib.request.urlretrieve(remoteURL) # fileData = remoteFile.read() print(remoteFile[0]) diff --git a/actions/reddit/flair/update_flair_with_rules.py b/actions/reddit/flair/update_flair_with_rules.py index 80b45c8..a3b86b6 100644 --- a/actions/reddit/flair/update_flair_with_rules.py +++ b/actions/reddit/flair/update_flair_with_rules.py @@ -12,6 +12,10 @@ class UpdateFlairWithRules: def __init__(self, payload, reddit): author = str(payload.author) content = str(payload.body) + print("CONTENT IS:") + print(content) + print("CONTENT ********") + sys.stdout.flush() # Set a default status to be overwritten self.status = { 'statusCode': 0, @@ -29,23 +33,35 @@ def __init__(self, payload, reddit): target_sub = os.getenv("SUBREDDIT") subreddit = reddit.subreddit(target_sub) + # retrieve the current CSS class for the user's flair, otherwise set thier current css class to an empty string. for user in subreddit.flair.__call__(redditor=author): current_class = user['flair_css_class'] if current_class == None: current_class = '' + # todo: figure out why this is here.... it looks to set rules, but idk why it's in this "if" statement ruleset = Rules(reddit).findRuleset + try: - ruleset = ruleset[content] + rulesetIndex = ruleset[content] except KeyError: ruleset = False self.status['statusCode'] = 200 self.status['subject'] = 'Invalid Flair for /r/' + os.getenv("SUBREDDIT") self.status['message'] = '/u/' + author + ',\n\nThe flair you requested ("' + content + '") is not valid. Please try again.\n\nPlease go to the [list of available flairs](https://www.reddit.com/r/survivor/wiki/available_flairs) and follow the instructions provided.\n\nIf you continue to experience errors, please [message the /r/' + os.getenv("SUBREDDIT") + ' moderators](https://www.reddit.com/message/compose/?to=/r/Survivor&subject=Help%20with%20flair) for help.' + except Exception as e: + print('exception: ' + str(e)) + sys.stdout.flush() else: + print('Valid ruleset found for requested flair: ' + str(rulesetIndex)) + sys.stdout.flush() process_rules = Rules(reddit).currentRules - process_rules = process_rules[ruleset] + process_rules = process_rules[rulesetIndex] + + print('process rules by ruleset: ' + str(process_rules)) + sys.stdout.flush() for index, rule in enumerate(process_rules['set']['class']): + # enumerate through each class element to conditionally apply logic to the construction of a new css class will_apply_rule = True # Check to see if time on rule is valid if 'limit' in rule: @@ -57,13 +73,17 @@ def __init__(self, payload, reddit): if 'expires' in rule['limit']: if calendar.timegm(gmtime()) >= rule['limit']['expires']: will_apply_rule = False - + # When rule is eligible, apply it via the method speified as the "type" if will_apply_rule: if rule['type'] == 'string': new_class = new_class + str(rule['content']) elif rule['type'] == 'regex': + print("applying regex rule") + sys.stdout.flush() + # TODO: seems to be failing somewhere in here, probably due to python 3 encdoing shit regex = rule['content'].encode('ascii', 'ignore') - result = re.search(regex, current_class) + decodedRegex = regex.decode('ascii') + result = re.search(decodedRegex, current_class) if result is None: new_class = new_class else: From 72f35bf88f668759c4e9b8cfa5358d966b1688d2 Mon Sep 17 00:00:00 2001 From: Jon Berry Date: Sat, 9 May 2020 15:04:28 -0400 Subject: [PATCH 3/3] update prerequisite python version indicator in readme.md Signed-off-by: Jon Berry --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37dc5cc..d5d97a4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Balboa was initially created for [/r/survivor](https://www.reddit.com/r/survivor ## Getting Started ### Prerequisites -* [Python 2.7.x](https://docs.python.org/2/ "documentation") +* [Python 3.7.x](https://docs.python.org/3/ "documentation") * [pip](https://pip.pypa.io/en/stable/installing/ "installation instructions")