This repository has been archived by the owner on Jul 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.py
171 lines (129 loc) · 5.58 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import os
import random
import threading
import time
import re
from random import randrange
import praw
from colorama import init, Fore, Style
from praw.exceptions import RedditAPIException
reply_rate_limit_sleep = 5
general_rate_limit_sleep = 0.5
def read_file_contents(_file_name):
with open(_file_name, "r") as file:
file_contents = file.read()
return file_contents
def get_quotes_list():
return read_file_contents("quotes_list").split("\n")
def get_quote_dict():
contents = read_file_contents("quotes_dict")
lines = contents.split("\n")
_quotes_dict = {}
for line in lines:
if line != "":
key, value = line.split(":")
_quotes_dict[key] = value
return _quotes_dict
def get_random_quote():
return quotes_list[randrange(0, len(quotes_list))]
def get_matched_quote(_comment_body):
return next((tag for tag in quotes_dict.keys() if tag in _comment_body), None)
def handle_comment(_comment):
_comment.replies.replace_more(limit=None)
replies = _comment.replies.list()
handle_single_comment(_comment, 0)
if len(replies) > 0:
for comment_replay in replies:
time.sleep(general_rate_limit_sleep)
handle_comment(comment_replay)
def is_replying():
return os.getenv("is_replying", False) == "True"
def get_allowed_subs():
return os.getenv("allowed_subs", "test")
def get_trigger_word():
return os.getenv("trigger_word", "protagonist")
def get_bot_username():
return os.getenv("username", "TheProtagonistBot")
def handle_rate_limit_exception(_message, _comment):
if "Take a break" in _message:
seconds = calculate_break_time(_message)
print(f"Rate limit exception, sleeping for {seconds} seconds then retrying!")
thread = threading.Thread(target=handle_single_comment, args=(_comment, seconds,))
thread.start()
def calculate_break_time(_message):
p_seconds = re.compile(r"\d+ seconds", re.IGNORECASE)
p_minutes = re.compile(r"\d+ minutes", re.IGNORECASE)
seconds_match = p_seconds.findall(_message)
minutes_match = p_minutes.findall(_message)
if len(seconds_match) > 0:
seconds = int(seconds_match[0].replace("seconds", "").strip())
elif len(minutes_match) > 0:
seconds = int(minutes_match[0].replace("minutes", "").strip()) * 60
else:
seconds = 600
seconds += random.randint(10, 30)
return seconds
def is_replied_to_it(_replies):
if len(_replies) > 0:
return any(reply for reply in _replies if reply.author.name == get_bot_username())
else:
return False
def handle_single_comment(_single_comment, _sleep):
if _sleep != 0:
time.sleep(_sleep)
comment_body = _single_comment.body.lower()
if get_trigger_word() in comment_body and _single_comment.author.name != get_bot_username():
try:
reply_body = get_reply_body(comment_body)
sub_name = _single_comment.subreddit.display_name
print(f"{Fore.GREEN}Comment:")
print(f"{Fore.YELLOW}###")
print(f"{Fore.BLUE}{comment_body}")
print(f"{Fore.YELLOW}###")
already_replied = is_replied_to_it(_single_comment.replies.list())
if is_replying() and sub_name in get_allowed_subs().split("+") and not already_replied:
print(f"Replying to comment: {_single_comment.id}, Wait...{Style.RESET_ALL}")
print(f"{Fore.GREEN}Reply:")
print(f"{Fore.BLUE}{reply_body}")
time.sleep(random.randint(1, reply_rate_limit_sleep))
_single_comment.reply(reply_body)
print(f"{Fore.GREEN}Replied to comment.")
else:
print(f"{Fore.RED}Reply is forbidden in this subreddit: {Fore.CYAN}{sub_name}{Style.RESET_ALL}")
print(f"{Fore.RED}Because:")
print(f"{Fore.RED}generally replying allowance is:{Style.RESET_ALL}", end='')
print(f"{Fore.CYAN} {is_replying()}{Style.RESET_ALL}")
print(f"{Fore.RED}, Or bot already replied to this comment:{Style.RESET_ALL}", end='')
print(f"{Fore.CYAN} {already_replied}{Style.RESET_ALL}")
except RedditAPIException as reddit_api_exception:
message = reddit_api_exception.args[0].message
print(f"{Fore.RED}Reddit API Exception: {Fore.CYAN}{message}{Style.RESET_ALL}")
handle_rate_limit_exception(message, _single_comment)
except Exception as e:
print(f"{Fore.RED}Failed to reply to comment: {Fore.CYAN}{str(e)}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}Invalid comment: {Fore.CYAN}{_single_comment.id}{Style.RESET_ALL}")
def get_reply_body(comment_body):
match = get_matched_quote(comment_body)
return quotes_dict[match] if match is not None else get_random_quote()
init()
print(f"{Fore.YELLOW}Starting bot...")
print(f"Trigger word: {Fore.GREEN}{get_trigger_word()}")
print(f"{Fore.YELLOW}Getting quotes...")
quotes_list = get_quotes_list()
quotes_dict = get_quote_dict()
print(f"{Fore.YELLOW}Getting reddit instance... for user: {Fore.GREEN}{get_bot_username()}")
reddit = praw.Reddit(
client_id=os.getenv("client_id"),
client_secret=os.getenv("client_secret"),
user_agent=os.getenv("user_agent"),
username=os.getenv("username"),
password=os.getenv("password")
)
print(f"{Fore.YELLOW}Getting subreddits...")
subs = reddit.subreddit(get_allowed_subs())
print(f"{Fore.YELLOW}Getting comments...{Style.RESET_ALL}")
for comment in subs.stream.comments():
time.sleep(general_rate_limit_sleep)
comment.refresh()
handle_comment(comment)