From bef9f53cae902db1d32fe2be78a8631918ff508e Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Sun, 17 Sep 2017 12:29:44 -0400 Subject: [PATCH 1/8] Set theme jekyll-theme-cayman --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 3397c9a..c419263 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-architect \ No newline at end of file +theme: jekyll-theme-cayman \ No newline at end of file From 8e0fc63925966c14dc82b66282c8b9eec2ed454e Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Sun, 17 Sep 2017 12:35:22 -0400 Subject: [PATCH 2/8] Show downloads --- _config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 3397c9a..a6f0c65 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1,2 @@ -theme: jekyll-theme-architect \ No newline at end of file +theme: jekyll-theme-architect +show_downloads: true \ No newline at end of file From a06c15cd42b7ba07bee539fa38fc4bf92c4854d5 Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Tue, 19 Sep 2017 20:21:02 -0400 Subject: [PATCH 3/8] Add logger level customization --- modules/logger.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/logger.py b/modules/logger.py index 2e89e2e..102cd48 100644 --- a/modules/logger.py +++ b/modules/logger.py @@ -3,13 +3,13 @@ import sys -def setup_logger(name): +def setup_logger(name, loglevel=logging.INFO): file_handler = logging.FileHandler(filename='logs/{}_{}.log'.format(name, datetime.now().strftime('%m_%d_%y'))) stdout_handler = logging.StreamHandler(sys.stdout) handlers = [file_handler, stdout_handler] logging.basicConfig( - level=logging.INFO, + level=loglevel, format='[%(asctime)s] {%(filename)s:%(lineno)d} (%(funcName)s) %(levelname)s - %(message)s', handlers=handlers ) From 5f8124cbaaf3b613701f52676543234a6623e876 Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Wed, 20 Sep 2017 21:33:52 -0400 Subject: [PATCH 4/8] Major code overhaul --- duplicate.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/duplicate.py b/duplicate.py index 2752868..a277303 100644 --- a/duplicate.py +++ b/duplicate.py @@ -8,8 +8,8 @@ logger = setup_logger('duplicates') -def action(): - for sub_id in reddit.subreddit('all').stream.submissions(): +def run_bot(sub_id): + if True: try: logging.debug('Starting submission {}'.format(sub_id)) blockeduser = 0 @@ -62,7 +62,11 @@ def action(): raise KeyboardInterrupt except: logger.error('Error on submission {} occured.'.format(str(sub_id)), exc_info=True) - + + +def action(): + for sub_id in reddit.subreddit('all').stream.submissions(): + run_bot(sub_id) if __name__ == '__main__': From c7ad3232ff13e088f6f3852c8676f1c6f8561011 Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Thu, 18 Jan 2018 18:15:52 -0500 Subject: [PATCH 5/8] Add --- duplicate.py | 158 +++++++++++++++++++++++++++++----------------- entriesadder.py | 44 +++++++++++++ modules/footer.py | 1 - modules/table.py | 4 ++ 4 files changed, 148 insertions(+), 59 deletions(-) create mode 100644 entriesadder.py delete mode 100644 modules/footer.py create mode 100644 modules/table.py diff --git a/duplicate.py b/duplicate.py index a277303..0b9b047 100644 --- a/duplicate.py +++ b/duplicate.py @@ -1,79 +1,121 @@ -from modules.logger import setup_logger import logging from datetime import datetime + import praw import prawcore +from pokestarfansloggingsetup import setup_logger + from modules.login import reddit -from modules.footer import footer +from modules.table import starter logger = setup_logger('duplicates') + +# noinspection PyBroadException +def generate_and_reply(submission): + footer = '\n\n----\n\n ^^I ^^am ^^a ^^bot ^^[FAQ](https://www.reddit.com/r/DuplicatesBot/wiki/index)-[' \ + 'Code](https://github.com/PokestarFan/DuplicateBot)-[Bugs](' \ + 'https://www.reddit.com/r/DuplicatesBot/comments/6ypgmx/bugs_and_problems/)-[Suggestions](' \ + 'https://www.reddit.com/r/DuplicatesBot/comments/6ypg85/suggestion_for_duplicatesbot/)-[Block ' \ + 'user (op only)' \ + '](' \ + 'https://www.reddit.com/message/compose/?to=DuplicatesBotBlocker&subject=remove%20user&message' \ + '={user})-[Block from subreddit (mods only)](' \ + 'https://www.reddit.com/message/compose/?to=DuplicatesBotBlocker&subject=remove%20subreddit' \ + '&message={sub})\n' \ + '\n^^Now ^^you ^^can ^^remove ^^the ^^comment ^^by ^^replying ^^delete! '.format(user= + str( + submission.author), sub=str(submission.subreddit)) + global message + sub_id = submission.subreddit + for dup_sub in submission.duplicates(): + duplicates = [] + time = dup_sub.created + time = str(datetime.fromtimestamp(time)) + author = '/u/' + str(dup_sub.author) + if str(submission.author) == author: + author = author + ' [author of both threads]' + duplicates.append(['[{}]({})'.format(str(dup_sub.title), 'https://www.reddit.com' + str(dup_sub.permalink)), + str(dup_sub.subreddit), author, str(time), str(dup_sub.score)]) + if len(duplicates) > 0: + message = 'Here is a list of threads in other subreddits about the same content:\n' + for dup in duplicates: + starter.add_row_with_list(dup) + message += '\n' + starter.table + message += '\n' + footer + try: + submission.reply(message) + logger.info('Message posted on {}'.format(sub_id)) + logger.debug('Message: {}'.format(message)) + message = '' + except praw.exceptions.APIException: + logger.debug('Submission {} has been skipped due to missing text.'.format(sub_id)) + message = '' + except prawcore.exceptions.Forbidden: + logger.debug('You are blocked on /r/{}'.format(str(submission.subreddit))) + message = '' + except AssertionError: + logger.debug('Assertion Error occured! Printing message and traceback.') + logger.debug(message + str(len(message)), exc_info=True) + message = '' + except(KeyboardInterrupt, SystemExit): + raise + except Exception: + logger.error('Error occurred!', exc_info=True) + message = '' + except: + logger.critical( + 'Massive Error occurred! Not part of the Exception, KeyboardInterrupt or SystemExit exceptions. Fix ASAP.', + exc_info=True) + message = '' + + def run_bot(sub_id): + global blocked_sub if True: try: - logging.debug('Starting submission {}'.format(sub_id)) - blockeduser = 0 - duplicates = [] - submission = praw.models.Submission(reddit, id = sub_id) - with open('blockusers.txt','r') as newfile: - for line in newfile.readlines(): - line = line.strip('\n') - if str(submission.author) == line or 'bot' in str(submission.author).lower(): - blockeduser = 1 - logger.debug('User {}\'s submission {} was blocked from posting'.format(str(submission.author),str(sub_id))) - else: - pass - if blockeduser == 0: - for duplicate in submission.duplicates(): - dup_sub = praw.models.Submission(reddit, id = duplicate) - if 'imagesof' not in str(dup_sub.subreddit).lower() and 'auto' not in str(dup_sub.subreddit).lower() and 'bot' not in str(dup_sub.author).lower() and 'mistyfront' not in str(dup_sub.subreddit).lower() and 'unitedfederation' not in str(dup_sub.subreddit).lower(): - time = dup_sub.created - time = str(datetime.fromtimestamp(time)) - author = '/u/'+str(dup_sub.author) - if str(submission.author) == author: - author = author + ' [author of both threads]' - duplicates.append({'title':str(dup_sub.title), 'subreddit':str(dup_sub.subreddit), 'link':'https://www.reddit.com'+str(dup_sub.permalink), 'time':str(time), 'author':author, 'karma': str(dup_sub.score)}) - if len(duplicates) > 0: - message = 'Here is a list of threads in other subreddits about the same content:\n' - for dup in duplicates: - message = str(message + '\n * [{}]({}) on /r/{} with {} karma (created at {} by {})').format(dup['title'], dup['link'], dup['subreddit'], dup['karma'],dup['time'], dup['author']) - message = message + footer - try: - submission.reply(message) - logger.info('Message posted on {}'.format(sub_id)) - logger.debug('Message: {}'.format(message)) - message = '' - except(praw.exceptions.APIException, UnboundLocalError)as e: - logger.debug('Submission {} has been skipped due to missing text'.format(sub_id)) - message = '' - except(prawcore.exceptions.Forbidden): - logger.debug('You are blocked on /r/{}'.format(str(submission.subreddit))) - message = '' - except(AssertionError): - logger.debug('Assertion Error occured! Printing message and traceback.') - logger.debug(message + str(len(message)), exc_info=True) - message = '' - except(KeyboardInterrupt): - raise KeyboardInterrupt - except: - logger.error('Error occured!', exc_info=True) - message = '' - except(KeyboardInterrupt): - raise KeyboardInterrupt - except: - logger.error('Error on submission {} occured.'.format(str(sub_id)), exc_info=True) + logging.debug('Starting submission {}'.format(str(sub_id))) + blocked_user = 0 + blocked_sub = 0 + submission = sub_id + try: + with open('blockusers.txt', 'r') as new_file: + for line in new_file.readlines(): + line = line.strip('\n') + if str(submission.author).lower() == line.lower() or 'bot' in str(submission.author).lower(): + blocked_user = 1 + break + except FileNotFoundError: + with open('blockusers.txt', 'w'): + blocked_user = 0 + try: + with open('blockedsubs.txt', 'r') as new_file: + for line in new_file.readlines(): + line = line.strip('\n') + if str(submission.subreddit).lower() == line.lower(): + blocked_sub = 1 + break + except FileNotFoundError: + with open('blockedsubs.txt', 'w'): + blocked_sub = 0 + if blocked_user == 0 and blocked_sub == 0: + generate_and_reply(sub_id) + except(KeyboardInterrupt, SystemExit): + raise + except Exception: + logger.error('Error on submission {} occurred.'.format(str(sub_id)), exc_info=True) def action(): for sub_id in reddit.subreddit('all').stream.submissions(): run_bot(sub_id) - + if __name__ == '__main__': while True: try: action() - except(KeyboardInterrupt): - raise KeyboardInterrupt - except: - logger.critical('Error has occured when running main loop, please resolve asap', exc_info=True) \ No newline at end of file + except(KeyboardInterrupt, SystemExit): + raise + except Exception: + logger.critical('Error has occured when running main loop, please resolve asap', exc_info=True) diff --git a/entriesadder.py b/entriesadder.py new file mode 100644 index 0000000..921334c --- /dev/null +++ b/entriesadder.py @@ -0,0 +1,44 @@ +import praw +from pokestarfansloggingsetup import setup_logger +import logging +from modules.entrylogin import reddit + +logger = setup_logger('usersubblocker') + + +def write_to_user_file(text): + with open('blockusers.txt', 'a') as file: + file.write(text) + + +def write_to_sub_file(text): + with open('blockedsubs.txt', 'a') as file: + file.write(text) + + +def strip_message(message): + try: + if message.subject == 'remove subreddit': + subreddit = reddit.subreddit(message) + mod = False + for moderator in reddit.subreddit(subreddit).moderator(): + if str(message.author) == str(moderator): + mod = True + break + if mod: + write_to_sub_file(message.body) + else: + message.reply('You are not a moderator of the subreddit so your request has not been preformed.') + elif message.subject == 'remove user': + if str(message.author) == message.body: + write_to_user_file(message.body) + else: + message.reply('You are not the OP of the submission so your request has not been preformed.') + except Exception: + logging.warning('', exc_info=True) + + +def check_for_messages(reddit): + for message in reddit.inbox.unread(mark_read=True): + strip_message(message) + reddit.inbox.mark_read(message) diff --git a/modules/footer.py b/modules/footer.py deleted file mode 100644 index 5d6c938..0000000 --- a/modules/footer.py +++ /dev/null @@ -1 +0,0 @@ -footer = '\n\n----\n\n ^^I ^^am ^^a ^^bot ^^[FAQ](https://www.reddit.com/r/DuplicatesBot/wiki/index)-[Code](https://github.com/PokestarFan/DuplicateBot)-[Bugs](https://www.reddit.com/r/DuplicatesBot/comments/6ypgmx/bugs_and_problems/)-[Suggestions](https://www.reddit.com/r/DuplicatesBot/comments/6ypg85/suggestion_for_duplicatesbot/)-[Block](https://www.reddit.com/r/DuplicatesBot/wiki/index#wiki_block_bot_from_tagging_on_your_posts)\n\n^^Now ^^you ^^can ^^remove ^^the ^^comment ^^by ^^replying ^^delete!' \ No newline at end of file diff --git a/modules/table.py b/modules/table.py new file mode 100644 index 0000000..c2bb0ef --- /dev/null +++ b/modules/table.py @@ -0,0 +1,4 @@ +from markdowntable import Table as ta + +starter = ta('Title') +starter.all_columns('Subreddit','Author','Time','Karma') \ No newline at end of file From c907186debed424a7994cbfeb938b1c0bf89c9f1 Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Thu, 18 Jan 2018 18:49:23 -0500 Subject: [PATCH 6/8] Finally done --- delete.py | 47 +++++++++++++++++++++++++---------------------- duplicate.py | 22 ++++++++++------------ entriesadder.py | 18 +++++++++++++----- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/delete.py b/delete.py index 2f6658e..4eab928 100644 --- a/delete.py +++ b/delete.py @@ -1,30 +1,33 @@ -import praw -from modules.logger import setup_logger -from modules.login import reddit -from modules.footer import footer import logging import time +from modules.logger import setup_logger +from modules.login import reddit + logger = setup_logger('user_removed_comments') def main(): - try: - for item in reddit.inbox.stream(): - logger.debug('On item {}'.format(str(item))) - try: - if 'delete' in item.body.lower(): - item.parent().delete() - logging.info('Comment {} removed'.format(str(item.parent()))) - item.author.message('Removal of comment {}'.format(str(item.parent())),'The top level post has been removed.') - except: - logging.debug('Item {} skipped'.format(str(item))) - except(KeyboardInterrupt): - raise KeyboardInterrupt - except: - logging.error('Error!', exc_info=True) - main() - + try: + for item in reddit.inbox.stream(): + logger.debug('On item {}'.format(str(item))) + try: + if 'delete' in item.body.lower() and item.author == item.submission.author: + item.parent().delete() + logging.info('Comment {} removed'.format(str(item.parent()))) + item.author.message('Removal of comment {}'.format(str(item.parent())), + 'The top level post has been removed.') + except AttributeError: + pass + except: + logging.debug('Item {} skipped'.format(str(item))) + except(KeyboardInterrupt): + raise KeyboardInterrupt + except: + logging.error('Error!', exc_info=True) + main() + + while True: - main() - time.sleep(30) \ No newline at end of file + main() + time.sleep(30) diff --git a/duplicate.py b/duplicate.py index 0b9b047..f6ba10a 100644 --- a/duplicate.py +++ b/duplicate.py @@ -3,18 +3,20 @@ import praw import prawcore +from markdowntable import Table as ta from pokestarfansloggingsetup import setup_logger from modules.login import reddit -from modules.table import starter logger = setup_logger('duplicates') # noinspection PyBroadException def generate_and_reply(submission): - footer = '\n\n----\n\n ^^I ^^am ^^a ^^bot ^^[FAQ](https://www.reddit.com/r/DuplicatesBot/wiki/index)-[' \ - 'Code](https://github.com/PokestarFan/DuplicateBot)-[Bugs](' \ + starter = ta('Title') + starter.all_columns('Subreddit', 'Author', 'Time', 'Karma') + footer = '\n\n----\n\n I am a bot [FAQ](https://www.reddit.com/r/DuplicatesBot/wiki/index)-[' \ + 'Code](https://github.com/PokestarFan/DuplicateBot)-[Bugs](' \ 'https://www.reddit.com/r/DuplicatesBot/comments/6ypgmx/bugs_and_problems/)-[Suggestions](' \ 'https://www.reddit.com/r/DuplicatesBot/comments/6ypg85/suggestion_for_duplicatesbot/)-[Block ' \ 'user (op only)' \ @@ -23,7 +25,7 @@ def generate_and_reply(submission): '={user})-[Block from subreddit (mods only)](' \ 'https://www.reddit.com/message/compose/?to=DuplicatesBotBlocker&subject=remove%20subreddit' \ '&message={sub})\n' \ - '\n^^Now ^^you ^^can ^^remove ^^the ^^comment ^^by ^^replying ^^delete! '.format(user= + '\nNow you can remove the comment by replying delete! '.format(user= str( submission.author), sub=str(submission.subreddit)) global message @@ -36,7 +38,7 @@ def generate_and_reply(submission): if str(submission.author) == author: author = author + ' [author of both threads]' duplicates.append(['[{}]({})'.format(str(dup_sub.title), 'https://www.reddit.com' + str(dup_sub.permalink)), - str(dup_sub.subreddit), author, str(time), str(dup_sub.score)]) + '/r/' + str(dup_sub.subreddit), author, str(time), str(dup_sub.score)]) if len(duplicates) > 0: message = 'Here is a list of threads in other subreddits about the same content:\n' for dup in duplicates: @@ -45,28 +47,24 @@ def generate_and_reply(submission): message += '\n' + footer try: submission.reply(message) - logger.info('Message posted on {}'.format(sub_id)) + logger.info('Message posted on {}'.format(str(submission))) logger.debug('Message: {}'.format(message)) - message = '' - except praw.exceptions.APIException: + except(praw.exceptions.APIException, UnboundLocalError): logger.debug('Submission {} has been skipped due to missing text.'.format(sub_id)) - message = '' except prawcore.exceptions.Forbidden: logger.debug('You are blocked on /r/{}'.format(str(submission.subreddit))) - message = '' except AssertionError: logger.debug('Assertion Error occured! Printing message and traceback.') logger.debug(message + str(len(message)), exc_info=True) - message = '' except(KeyboardInterrupt, SystemExit): raise except Exception: logger.error('Error occurred!', exc_info=True) - message = '' except: logger.critical( 'Massive Error occurred! Not part of the Exception, KeyboardInterrupt or SystemExit exceptions. Fix ASAP.', exc_info=True) + finally: message = '' diff --git a/entriesadder.py b/entriesadder.py index 921334c..21fa0c1 100644 --- a/entriesadder.py +++ b/entriesadder.py @@ -1,6 +1,7 @@ -import praw -from pokestarfansloggingsetup import setup_logger import logging + +from pokestarfansloggingsetup import setup_logger + from modules.entrylogin import reddit logger = setup_logger('usersubblocker') @@ -39,6 +40,13 @@ def strip_message(message): def check_for_messages(reddit): - for message in reddit.inbox.unread(mark_read=True): - strip_message(message) - reddit.inbox.mark_read(message) + try: + for message in reddit.inbox.unread(mark_read=True): + strip_message(message) + reddit.inbox.mark_read(message) + except Exception: + logging.error('error!', exc_info=True) + + +while True: + check_for_messages(reddit) From 4cc8275c166512e60d445fc2d5ab3a04240d740a Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Mon, 14 May 2018 15:39:24 -0400 Subject: [PATCH 7/8] Update duplicate.py --- duplicate.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/duplicate.py b/duplicate.py index f6ba10a..abc8d7a 100644 --- a/duplicate.py +++ b/duplicate.py @@ -1,3 +1,28 @@ +# +# +# PPPPPPPPPPPPPPPPP kkkkkkkk tttt FFFFFFFFFFFFFFFFFFFFFF +# P::::::::::::::::P k::::::k ttt:::t F::::::::::::::::::::F +# P::::::PPPPPP:::::P k::::::k t:::::t F::::::::::::::::::::F +# PP:::::P P:::::P k::::::k t:::::t FF::::::FFFFFFFFF::::F +# P::::P P:::::P ooooooooooo k:::::k kkkkkkk eeeeeeeeeeee ssssssssss ttttttt:::::ttttttt aaaaaaaaaaaaa rrrrr rrrrrrrrr F:::::F FFFFFFaaaaaaaaaaaaa nnnn nnnnnnnn +# P::::P P:::::Poo:::::::::::oo k:::::k k:::::kee::::::::::::ee ss::::::::::s t:::::::::::::::::t a::::::::::::a r::::rrr:::::::::r F:::::F a::::::::::::a n:::nn::::::::nn +# P::::PPPPPP:::::Po:::::::::::::::o k:::::k k:::::ke::::::eeeee:::::eess:::::::::::::s t:::::::::::::::::t aaaaaaaaa:::::ar:::::::::::::::::r F::::::FFFFFFFFFF aaaaaaaaa:::::an::::::::::::::nn +# P:::::::::::::PP o:::::ooooo:::::o k:::::k k:::::ke::::::e e:::::es::::::ssss:::::stttttt:::::::tttttt a::::arr::::::rrrrr::::::rF:::::::::::::::F a::::ann:::::::::::::::n +# P::::PPPPPPPPP o::::o o::::o k::::::k:::::k e:::::::eeeee::::::e s:::::s ssssss t:::::t aaaaaaa:::::a r:::::r r:::::rF:::::::::::::::F aaaaaaa:::::a n:::::nnnn:::::n +# P::::P o::::o o::::o k:::::::::::k e:::::::::::::::::e s::::::s t:::::t aa::::::::::::a r:::::r rrrrrrrF::::::FFFFFFFFFF aa::::::::::::a n::::n n::::n +# P::::P o::::o o::::o k:::::::::::k e::::::eeeeeeeeeee s::::::s t:::::t a::::aaaa::::::a r:::::r F:::::F a::::aaaa::::::a n::::n n::::n +# P::::P o::::o o::::o k::::::k:::::k e:::::::e ssssss s:::::s t:::::t tttttta::::a a:::::a r:::::r F:::::F a::::a a:::::a n::::n n::::n +# PP::::::PP o:::::ooooo:::::ok::::::k k:::::ke::::::::e s:::::ssss::::::s t::::::tttt:::::ta::::a a:::::a r:::::r FF:::::::FF a::::a a:::::a n::::n n::::n +# P::::::::P o:::::::::::::::ok::::::k k:::::ke::::::::eeeeeeee s::::::::::::::s tt::::::::::::::ta:::::aaaa::::::a r:::::r F::::::::FF a:::::aaaa::::::a n::::n n::::n +# P::::::::P oo:::::::::::oo k::::::k k:::::kee:::::::::::::e s:::::::::::ss tt:::::::::::tt a::::::::::aa:::ar:::::r F::::::::FF a::::::::::aa:::a n::::n n::::n +# PPPPPPPPPP ooooooooooo kkkkkkkk kkkkkkk eeeeeeeeeeeeee sssssssssss ttttttttttt aaaaaaaaaa aaaarrrrrrr FFFFFFFFFFF aaaaaaaaaa aaaa nnnnnn nnnnnn +# +# +# +# +# +# +# import logging from datetime import datetime From 86b5c7a4cc2122f991ba1b2e81a2c16725efe1cc Mon Sep 17 00:00:00 2001 From: PokestarFan Date: Mon, 14 May 2018 15:40:26 -0400 Subject: [PATCH 8/8] Update duplicate.py --- duplicate.py | 82 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/duplicate.py b/duplicate.py index abc8d7a..5c6ebe8 100644 --- a/duplicate.py +++ b/duplicate.py @@ -1,28 +1,60 @@ -# -# -# PPPPPPPPPPPPPPPPP kkkkkkkk tttt FFFFFFFFFFFFFFFFFFFFFF -# P::::::::::::::::P k::::::k ttt:::t F::::::::::::::::::::F -# P::::::PPPPPP:::::P k::::::k t:::::t F::::::::::::::::::::F -# PP:::::P P:::::P k::::::k t:::::t FF::::::FFFFFFFFF::::F -# P::::P P:::::P ooooooooooo k:::::k kkkkkkk eeeeeeeeeeee ssssssssss ttttttt:::::ttttttt aaaaaaaaaaaaa rrrrr rrrrrrrrr F:::::F FFFFFFaaaaaaaaaaaaa nnnn nnnnnnnn -# P::::P P:::::Poo:::::::::::oo k:::::k k:::::kee::::::::::::ee ss::::::::::s t:::::::::::::::::t a::::::::::::a r::::rrr:::::::::r F:::::F a::::::::::::a n:::nn::::::::nn -# P::::PPPPPP:::::Po:::::::::::::::o k:::::k k:::::ke::::::eeeee:::::eess:::::::::::::s t:::::::::::::::::t aaaaaaaaa:::::ar:::::::::::::::::r F::::::FFFFFFFFFF aaaaaaaaa:::::an::::::::::::::nn -# P:::::::::::::PP o:::::ooooo:::::o k:::::k k:::::ke::::::e e:::::es::::::ssss:::::stttttt:::::::tttttt a::::arr::::::rrrrr::::::rF:::::::::::::::F a::::ann:::::::::::::::n -# P::::PPPPPPPPP o::::o o::::o k::::::k:::::k e:::::::eeeee::::::e s:::::s ssssss t:::::t aaaaaaa:::::a r:::::r r:::::rF:::::::::::::::F aaaaaaa:::::a n:::::nnnn:::::n -# P::::P o::::o o::::o k:::::::::::k e:::::::::::::::::e s::::::s t:::::t aa::::::::::::a r:::::r rrrrrrrF::::::FFFFFFFFFF aa::::::::::::a n::::n n::::n -# P::::P o::::o o::::o k:::::::::::k e::::::eeeeeeeeeee s::::::s t:::::t a::::aaaa::::::a r:::::r F:::::F a::::aaaa::::::a n::::n n::::n -# P::::P o::::o o::::o k::::::k:::::k e:::::::e ssssss s:::::s t:::::t tttttta::::a a:::::a r:::::r F:::::F a::::a a:::::a n::::n n::::n -# PP::::::PP o:::::ooooo:::::ok::::::k k:::::ke::::::::e s:::::ssss::::::s t::::::tttt:::::ta::::a a:::::a r:::::r FF:::::::FF a::::a a:::::a n::::n n::::n -# P::::::::P o:::::::::::::::ok::::::k k:::::ke::::::::eeeeeeee s::::::::::::::s tt::::::::::::::ta:::::aaaa::::::a r:::::r F::::::::FF a:::::aaaa::::::a n::::n n::::n -# P::::::::P oo:::::::::::oo k::::::k k:::::kee:::::::::::::e s:::::::::::ss tt:::::::::::tt a::::::::::aa:::ar:::::r F::::::::FF a::::::::::aa:::a n::::n n::::n -# PPPPPPPPPP ooooooooooo kkkkkkkk kkkkkkk eeeeeeeeeeeeee sssssssssss ttttttttttt aaaaaaaaaa aaaarrrrrrr FFFFFFFFFFF aaaaaaaaaa aaaa nnnnnn nnnnnn -# -# -# -# -# -# -# +# +# +# PPPPPPPPPPPPPPPPP kkkkkkkk +# P::::::::::::::::P k::::::k +# P::::::PPPPPP:::::P k::::::k +# PP:::::P P:::::P k::::::k +# P::::P P:::::P ooooooooooo k:::::k kkkkkkk eeeeeeeeeeee +# P::::P P:::::Poo:::::::::::oo k:::::k k:::::kee::::::::::::ee +# P::::PPPPPP:::::Po:::::::::::::::o k:::::k k:::::ke::::::eeeee:::::ee +# P:::::::::::::PP o:::::ooooo:::::o k:::::k k:::::ke::::::e e:::::e +# P::::PPPPPPPPP o::::o o::::o k::::::k:::::k e:::::::eeeee::::::e +# P::::P o::::o o::::o k:::::::::::k e:::::::::::::::::e +# P::::P o::::o o::::o k:::::::::::k e::::::eeeeeeeeeee +# P::::P o::::o o::::o k::::::k:::::k e:::::::e +# PP::::::PP o:::::ooooo:::::ok::::::k k:::::ke::::::::e +# P::::::::P o:::::::::::::::ok::::::k k:::::ke::::::::eeeeeeee +# P::::::::P oo:::::::::::oo k::::::k k:::::kee:::::::::::::e +# PPPPPPPPPP ooooooooooo kkkkkkkk kkkkkkk eeeeeeeeeeeeee +# SSSSSSSSSSSSSSS tttt +# SS:::::::::::::::S ttt:::t +# S:::::SSSSSS::::::S t:::::t +# S:::::S SSSSSSS t:::::t +# S:::::S ttttttt:::::ttttttt aaaaaaaaaaaaa rrrrr rrrrrrrrr +# S:::::S t:::::::::::::::::t a::::::::::::a r::::rrr:::::::::r +# S::::SSSS t:::::::::::::::::t aaaaaaaaa:::::ar:::::::::::::::::r +# SS::::::SSSSStttttt:::::::tttttt a::::arr::::::rrrrr::::::r +# SSS::::::::SS t:::::t aaaaaaa:::::a r:::::r r:::::r +# SSSSSS::::S t:::::t aa::::::::::::a r:::::r rrrrrrr +# S:::::S t:::::t a::::aaaa::::::a r:::::r +# S:::::S t:::::t tttttta::::a a:::::a r:::::r +# SSSSSSS S:::::S t::::::tttt:::::ta::::a a:::::a r:::::r +# S::::::SSSSSS:::::S tt::::::::::::::ta:::::aaaa::::::a r:::::r +# S:::::::::::::::SS tt:::::::::::tt a::::::::::aa:::ar:::::r +# SSSSSSSSSSSSSSS ttttttttttt aaaaaaaaaa aaaarrrrrrr +# FFFFFFFFFFFFFFFFFFFFFF +# F::::::::::::::::::::F +# F::::::::::::::::::::F +# FF::::::FFFFFFFFF::::F +# F:::::F FFFFFFaaaaaaaaaaaaa nnnn nnnnnnnn +# F:::::F a::::::::::::a n:::nn::::::::nn +# F::::::FFFFFFFFFF aaaaaaaaa:::::an::::::::::::::nn +# F:::::::::::::::F a::::ann:::::::::::::::n +# F:::::::::::::::F aaaaaaa:::::a n:::::nnnn:::::n +# F::::::FFFFFFFFFF aa::::::::::::a n::::n n::::n +# F:::::F a::::aaaa::::::a n::::n n::::n +# F:::::F a::::a a:::::a n::::n n::::n +# FF:::::::FF a::::a a:::::a n::::n n::::n +# F::::::::FF a:::::aaaa::::::a n::::n n::::n +# F::::::::FF a::::::::::aa:::a n::::n n::::n +# FFFFFFFFFFF aaaaaaaaaa aaaa nnnnnn nnnnnn +# +# +# +# +# +# +# import logging from datetime import datetime pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy