-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
211 lines (158 loc) · 5.78 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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import asyncio
import datetime
import signal
import time
import contractions
from discord import MessageType
from emoji import emojize, replace_emoji
from ftlangdetect import detect
from conf import (
BOT_TOKEN,
CHANNEL_GENERAL,
CHANNEL_ANN,
CHANNEL_REVIEWS,
GOOGLE_PLAY_ADMINS,
CHANNEL_GIT_MONITOR,
)
import discord
from discord.ext import tasks
from google_play import async_publish_fresh_reviews, async_publish_reply
from repo_monitor import check_repos
from utils import floodScore
import pylru
import shelve
def lang(arg):
if arg is None:
return None
arg = arg.replace("\n", " ")
ret = detect(text=arg, low_memory=True)
return ret["lang"]
strikes = shelve.open("strikes")
authors = {}
messages = {}
def signal_handler(signal, frame):
strikes.close()
exit(0)
signal.signal(signal.SIGINT, signal_handler)
def isGoodMessageForAny(text: str, author: str):
if author not in authors:
authors[author] = pylru.lrucache(128)
if text not in authors[author]:
authors[author][text] = 0
authors[author][text] += 1
if authors[author][text] >= 3:
return False, "Please don't spam this!"
text = replace_emoji(text)
text = contractions.fix(text)
if floodScore(text) >= 50:
return False, "Please don't flood!"
return True, ""
def isGoodMessageForGeneral(text: str, author: str):
if author not in authors:
authors[author] = pylru.lrucache(128)
if text not in authors[author]:
authors[author][text] = 0
authors[author][text] += 1
if authors[author][text] >= 3:
return False, "Please don't spam this!"
text = replace_emoji(text)
text = contractions.fix(text)
if floodScore(text) >= 30:
return False, "Please don't flood!"
if lang(text) != "en":
return False, "Please use only English here!"
return True, ""
class RemixedGuardian(discord.Client):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.purge_start = datetime.datetime(year=2023, month=9, day=1)
async def setup_hook(self) -> None:
# start the task to run in the background
# self.my_background_task.start()
self.reviews_task.start()
self.git_monitor_task.start()
pass
async def on_message(self, message):
# print(message)
filenames = " ".join([a.filename for a in message.attachments])
content_to_check = message.content + " " + filenames
print(content_to_check)
if message.channel.id == CHANNEL_REVIEWS and message.type in [
MessageType.reply
]:
if (
message.reference is not None
and message.author.id in GOOGLE_PLAY_ADMINS
):
await async_publish_reply(message.reference.message_id, message.content)
return
if message.type in [MessageType.default, MessageType.reply]:
author = str(message.author.id)
reason = ""
if message.channel.id == CHANNEL_GENERAL:
if not message.author.bot:
good, reason = isGoodMessageForGeneral(content_to_check, author)
if good:
# print("Good, general")
return
else:
good, reason = isGoodMessageForAny(content_to_check, author)
if good:
# print("Good, any")
return
if author not in strikes:
strikes[author] = 0
# print("Bad", author, strikes[author])
strikes[author] += 1
if strikes[author] >= 5:
await message.delete(delay=2)
else:
await message.channel.send(reason, reference=message)
async def on_ready(self):
print(f"Logged in as {self.user} (ID: {self.user.id})")
@tasks.loop(seconds=1200)
async def reviews_task(self):
await self.wait_until_ready() # wait until the bot logs in
channel = client.get_channel(CHANNEL_REVIEWS)
await async_publish_fresh_reviews(channel)
@tasks.loop(seconds=1537)
async def git_monitor_task(self):
await self.wait_until_ready() # wait until the bot logs in
def on_new_commit(repo, msg):
async def _on_new_commit():
await client.get_channel(CHANNEL_GIT_MONITOR).send(
f"New commit detected in {repo}: {msg}"
)
await asyncio.sleep(10)
asyncio.ensure_future(_on_new_commit())
check_repos(on_new_commit)
# task runs every 60 seconds
@tasks.loop(seconds=120) # task runs every 60 seconds
async def exterminatus(self):
await self.wait_until_ready()
print(f"Exterminatus!")
channel = client.get_channel(CHANNEL_GENERAL)
messages = [
i
async for i in channel.history(
after=self.purge_start, before=datetime.datetime.now(), limit=50
)
]
print("processing: ", len(messages))
for message in messages:
print(message.created_at, message.content, lang(message.content), sep="\n")
if message.created_at.replace(tzinfo=None) > self.purge_start:
good, reason = isGoodMessageForGeneral(
message.content, message.author.name
)
if good:
continue
print(f"{reason}, deleting")
await asyncio.sleep(2)
await message.delete(delay=2)
print("done")
self.purge_start = message.created_at.replace(tzinfo=None)
print("Sleep")
intent = discord.Intents.all()
client = RemixedGuardian(intents=intent)
client.run(BOT_TOKEN)