-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbot.py
142 lines (125 loc) · 8 KB
/
bot.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
import praw, config, re, time, prawcore, string
from datetime import datetime
from statistics import median
def main():
reddit = praw.Reddit(client_id=config.client_id, client_secret=config.client_secret, user_agent=config.user_agent, username=config.username, password=config.password)
print(f"Logged into reddit as /u/{config.username}")
while True:
try:
for message in reddit.inbox.stream():
if message.new:
try:
if isinstance(message, praw.models.Message):
username = extract_user_pm(message.body)
else:
username = extract_user(message.body)
except Exception:
print(f"Failed on \"{message.body}\"")
else:
reply_stats(message, username, reddit)
finally:
message.mark_read()
except (praw.exceptions.PRAWException, prawcore.PrawcoreException) as e:
print(f"Error connecting to reddit: {str(e)}")
time.sleep(20)
def extract_user(comment):
comment = comment.replace("\\", "")
username = re.match(r"(/?(u/){1})?[\w-]{3,20}", comment.lower().split(f"u/{config.username} ")[1])
if username:
username = re.sub(r"/?(u/){1}", "", username.group(0))
else:
raise Exception
return username
def extract_user_pm(message): # Yes I know this method is stupid and ineffecient, but it should be rare so I don't care.
if message.startswith(f"/u/{config.username} ") or message.startswith(f"u/{config.username} "):
return extract_user(message)
else:
return extract_user(f"/u/{config.username} " + message)
def reply_stats(comment, username, reddit):
user = reddit.redditor(username)
posts = user.submissions.new(limit=None)
comments = user.comments.new(limit=None)
footer = "\n\n___\n\n^[FAQ](https://www.reddit.com/r/user_stats/wiki/faq) ^[Subreddit](https://reddit.com/r/user_stats)"
try:
stats = compile_stats(posts, comments, username)
except prawcore.exceptions.NotFound:
stats = f"Error: user \"{username}\" does not seem to exist."
except (praw.exceptions.PRAWException, prawcore.PrawcoreException) as e:
print("Bot encountered an error, waiting 5 sec and retrying...\n - Error: " + str(e))
try:
time.sleep(5)
stats = compile_stats(posts, comments, username)
except (praw.exceptions.PRAWException, prawcore.PrawcoreException):
print(f"Error getting posts/comments for \"{username}\"")
return
try:
comment.reply(stats + footer)
except (praw.exceptions.PRAWException, prawcore.PrawcoreException) as e:
print("Bot encountered an error, waiting 5 sec and retrying...\n - Error: " + str(e))
try:
time.sleep(5)
comment.reply(stats + footer)
except (praw.exceptions.PRAWException, prawcore.PrawcoreException):
print(f"Couldn't reply to {comment.id} in /r/{comment.subreddit}. Banned?")
return
def compile_stats(posts, comments, username):
# Post vars:
oldest_post = None
score_posts = []
words_posts = 0
# Comment vars:
oldest_comment = None
score_comments = []
words_comments = 0
for post in posts:
if oldest_post:
if post.created_utc < oldest_post:
oldest_post = post.created_utc
else:
oldest_post = post.created_utc
score_posts.append(post.score)
words_posts += len(re.sub('[' + string.punctuation + ']', '', post.title).split())
for comment in comments:
if oldest_comment:
if comment.created_utc < oldest_comment:
oldest_comment = comment.created_utc
else:
oldest_comment = comment.created_utc
score_comments.append(comment.score)
words_comments += len(re.sub('[' + string.punctuation + ']', '', comment.body).split())
count_posts = len(score_posts)
count_comments = len(score_comments)
total_score_posts = sum(score_posts)
total_score_comments = sum(score_comments)
if count_posts == 0 and count_comments == 0:
return "Error. User appears to have 0 posts and 0 comments."
current_time = datetime.now().timestamp()
if not oldest_post:
oldest_post = current_time
elif not oldest_comment:
oldest_comment = current_time
stats_string = (
f"**Stats for {username}:**\n\n" # For readability:
f"**Over the last {str(count_posts)} posts (over {str(round((current_time - oldest_post) / 86400))} days):** \n" # Post header
f"Net post upvotes: {str(total_score_posts - count_posts)} \n" # -Post score
f"Average post score: {str(round(total_score_posts / count_posts) if count_posts > 0 else 0)} \n" # -Avg. post score
f"Median post score: {str(round(median(score_posts)) if count_posts > 0 else 0)} \n" # -Med. post score
"Average post upvotes/day: " # -Post score/day
f"{str(round((total_score_posts - count_posts) / ((current_time - oldest_post) / 86400)) if current_time != oldest_post else 0)} \n"
f"Average posts/day: {str(round(count_posts / ((current_time - oldest_post) / 86400), 1) if current_time != oldest_post else 0)} \n" # -Posts/day
f"Total words in post titles: {str(words_posts)} \n" # -Title words
f"Average words per post title: {str(round(words_posts / count_posts) if count_posts > 0 else 0)}\n\n" # -Avg. title words
#----------------------
f"**Over the last {str(count_comments)} comments (over {str(round((current_time - oldest_comment) / 86400))} days):** \n" # Comment header
f"Net comment upvotes: {str(total_score_comments - count_comments)} \n" # -Comment score
f"Average comment score: {str(round(total_score_comments / count_comments) if count_comments > 0 else 0)} \n" # -Avg. comment score
f"Median comment score: {str(round(median(score_comments)) if count_comments > 0 else 0)} \n" # -Med. comment score
"Average comment upvotes/day: " # -Comment score/day
f"{str(round((total_score_comments - count_comments) / ((current_time - oldest_comment) / 86400)) if current_time != oldest_comment else 0)} \n"
f"Average comments/day: {str(round(count_comments / ((current_time - oldest_comment) / 86400), 1) if current_time != oldest_comment else 0)} \n" # -Comments/day
f"Total words in comments: {str(words_comments)} \n" # -Comment words
f"Average words per comment: {str(round(words_comments / count_comments) if count_comments > 0 else 0)}" # -Avg. comment words
)
return stats_string
if __name__ == "__main__":
main()