-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathbot_linking.py
148 lines (119 loc) · 4.88 KB
/
bot_linking.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
from os import environ as env
from typing import Literal
import nextcord
from nextcord.ext import commands, tasks
from nextcord.mentions import AllowedMentions
LOG_CHANNEL_ID = int(env["BOT_LINKING_LOG_CHANNEL_ID"])
GUILD_ID = int(env["GUILD_ID"])
BOOSTER_ROLE_ID = int(env["BOOSTER_ROLE_ID"])
class BotLinking(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.prune_loop.start()
@commands.group()
async def link(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send("No.")
@link.command()
@commands.has_permissions(administrator=True)
async def add(
self,
ctx,
status: Literal["booster", "admin", "special"],
bot: nextcord.User,
owner: nextcord.User,
):
db = self.bot.get_cog("Database")
if not bot.bot or owner.bot:
await ctx.send("You fucked up the order. Good job.")
return
await db.set(f"bots/{bot.id}", {"owner_id": owner.id, "status": status})
await ctx.send(f"Successfully linked <@{bot.id}> to <@{owner.id}>.")
@link.command()
@commands.has_permissions(administrator=True)
async def remove(self, ctx, bot: nextcord.Object):
db = self.bot.get_cog("Database")
current = await db.get(f"bots/{bot.id}")
if not current:
await ctx.send(f"This bot is not linked to anyone.")
return
await db.delete(f"bots/{bot.id}")
await ctx.send(f"Successfully unlinked <@{bot.id}>.")
@link.command()
@commands.has_permissions(administrator=True)
async def list(self, ctx):
db = self.bot.get_cog("Database")
bots = await db.list("bots/")
if bots is None:
await ctx.send("No bots linked.")
return
text = ""
for bot_id, metadata in bots.items():
bot_id = bot_id.removeprefix("bots/")
text += f"<@{bot_id}> linked to <@{metadata['owner_id']}> ({metadata['status']})\n"
await ctx.send(text, allowed_mentions=AllowedMentions(users=[]))
@link.command()
@commands.has_permissions(administrator=True)
async def prune(self, ctx):
await self.prune_bots()
await ctx.send("ok")
@tasks.loop(seconds=30)
async def prune_loop(self):
await self.prune_bots()
async def prune_bots(self):
await self.bot.wait_until_ready()
guild = self.bot.get_guild(GUILD_ID)
log_channel = await guild.fetch_channel(LOG_CHANNEL_ID)
db = self.bot.get_cog("Database")
for user in guild.members:
if not user.bot:
continue
metadata = await db.get(f"bots/{user.id}")
if not metadata:
# Bot is not linked, kick it
try:
await user.kick(reason="Unlinked bot")
except nextcord.Forbidden:
await log_channel.send(
f"Failed to kick {user.mention} (bot not linked)"
)
continue
await log_channel.send(
f"Unlinked bot {user.mention} found, bot has been kicked. Please use previous' link command."
)
continue
if metadata["status"] == "booster":
owner = guild.get_member(metadata["owner_id"])
if owner is None:
# Owner not in server?
try:
await user.kick(reason="Owner not in server")
except nextcord.Forbidden:
await log_channel.send(
f"Failed to kick {user.mention} (owner not in server)"
)
continue
await log_channel.send(
f"Owner <@{metadata['owner_id']}> not in server, {user.mention} has been kicked."
)
continue
if owner.get_role(BOOSTER_ROLE_ID) is None:
# Owner unboosted
try:
await user.kick(reason="Owner unboosted")
except nextcord.Forbidden:
await log_channel.send(
f"Failed to kick {user.mention} (owner unboosted)"
)
continue
await log_channel.send(
f"Owner <@{metadata['owner_id']}> unboosted, {user.mention} has been kicked."
)
try:
await owner.send(
f"As a result of you unboosting nextcord, your bot {user.mention} has been kicked. Please re-boost to get your bot added back."
)
except nextcord.Forbidden: # 400 error lol?
pass
def setup(bot):
bot.add_cog(BotLinking(bot))