Skip to content

Commit 4466d13

Browse files
committed
+ [ 26 files changed ] Merge branch 'dev' into overhaul
2 parents 4508037 + d3949ab commit 4466d13

26 files changed

+983
-578
lines changed

CHANGELOG.md

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
# v3.3
2+
3+
## 3.3.0
4+
5+
- [**New**] Added realurl (get real url of a shorten url)
6+
- [**Improved**] Added case number to modlog message
7+
- [**Changed**] Rename `Bot.master` -> `Bot.owner_ids`
8+
- [**Fixed**] Fix Admin commands' checks not working properly
9+
- [**Improved**] Decrease modlog delay to 2 seconds delay
10+
- [**Improved**] Merged `>help filter: custom` with `>command list`
11+
- [**Changed**] `>command disable` and `>command enable` no longer uses flag,
12+
replaced with choice buttons when there's more than 1 type is found with
13+
identical name
14+
- [**Fixed**] Anilist commands now works in DMs
15+
- [**Fixed**] `>manga search` actually search for manga not anime
16+
- [**Improved**] User now given choices between command and category when their
17+
names are conflicted
18+
- [**Improved**] Custom command list now paginated
19+
- [**New**] Added "compact mode" to paginator
20+
- [**Improved**] Failed NSFW check will now properly "yell" at the executor,
21+
instead of yelling "Check failed!"
22+
- [**Fixed**] Fixed caselog type `mute` being inconsistent ( [**For
23+
self-hoster**] sql query to fix your database: `UPDATE OR IGNORE caseLog SET
24+
type='mute' WHERE type='muted'`)
25+
- [**New**] Added createdAt column to caselog ( [**For self-hoster**]: sql
26+
query to add this column without dropping the table `ALTER TABLE caseLog ADD
27+
COLUMN createdAt INTEGER DEFAULT 0`) [**NOTE**]: Old cases' time will return
28+
either "Unknown" or `1/1/1970`
29+
- [**New**] Added `caselogs`/`cases` command to get moderator's cases
30+
- [**Improved**] Modlog now log unmute and unban
31+
- [**Disabled**] Disable `google` command (blocking the whole bot)
32+
133
# v3.2
234

335
## 3.2.9
@@ -8,8 +40,6 @@
840

941
- [**Fixed**] Fixed Moderation commands' checks not working properly
1042

11-
<!-- (TODO: Check if Admin commands' checks also broken) -->
12-
1343
## 3.2.7
1444

1545
- [**Fixed**] Fixed help command not working in DMs
@@ -18,7 +48,7 @@
1848

1949
## 3.2.6
2050

21-
- [**Fixed**] Fixed modlog. Added 5 second delay, letting Audit Logs to update
51+
- [**Fixed**] Fixed modlog. Added 5 seconds delay, letting Audit Logs to update
2252
before sending modlog
2353

2454
## 3.2.5

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,17 @@ Moved to [CHANGELOG.md](./CHANGELOG.md)
8888
## Plans
8989

9090
- Event for ~~member boosting a guild~~ (Just need to implement setup for it)
91-
- Properly support different SQL scheme (databases have `database_url.scheme` to check scheme type)
9291
- Tags (stripped version of custom command)
9392
- Unify categories/exts emoji
9493
- Channel manager commands
95-
- Reaction Role
94+
- Reaction Role (With buttons... button role?)
9695
- Starboard
9796

9897
### Pending Plan
9998

10099
- i18n using gettext (Learning how gettext works)
101-
- Slash command (RIP dpy, have to design this myself for now)
100+
- Slash command (Waiting for implementation)
101+
- Properly support different SQL scheme (designing best way to do this)
102102

103103
### Scrapped Plan
104104

core/bot.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import logging
77
import os
88
import re
9+
import warnings
910
from collections import Counter
1011
from contextlib import suppress
1112
from typing import Any, Dict, Iterable, List, Optional, Union
@@ -60,7 +61,7 @@ class ziBot(commands.Bot):
6061

6162
# --- NOTE: Information about the bot
6263
author: str = getattr(config, "author", "ZiRO2264#9999")
63-
version: str = "`3.2.9` - `overhaul`"
64+
version: str = "`3.3.0` - `overhaul`"
6465
links: Dict[str, str] = getattr(
6566
config,
6667
"links",
@@ -74,16 +75,20 @@ class ziBot(commands.Bot):
7475
# ---
7576

7677
def __init__(self) -> None:
78+
# custom intents, required since dpy v1.5
79+
intents = discord.Intents.all()
80+
7781
super().__init__(
7882
command_prefix=_callablePrefix,
7983
description=(
8084
"A **free and open source** multi-purpose **discord bot** "
8185
"created by ZiRO2264, formerly called `ziBot`."
8286
),
8387
case_insensitive=True,
84-
intents=discord.Intents.all(),
88+
intents=intents,
8589
heartbeat_timeout=150.0,
8690
)
91+
8792
# make cogs case insensitive
8893
self._BotBase__cogs: commands.core._CaseInsensitiveDict = (
8994
commands.core._CaseInsensitiveDict()
@@ -98,7 +103,7 @@ def __init__(self) -> None:
98103

99104
# Bot master(s)
100105
# self.master = (186713080841895936,)
101-
self.master: tuple = (
106+
self.owner_ids: tuple = (
102107
tuple()
103108
if not hasattr(config, "botMasters")
104109
else tuple([int(master) for master in config.botMasters])
@@ -197,16 +202,17 @@ async def asyncInit(self) -> None:
197202
async def startUp(self) -> None:
198203
"""Will run when the bot ready"""
199204
await self.wait_until_ready()
200-
if not self.master:
205+
206+
if not self.owner_ids:
201207
# If self.master not set, warn the hoster
202208
self.logger.warning(
203209
"No master is set, you may not able to use certain commands! (Unless you own the Bot Application)"
204210
)
205211

206-
# Add application owner into bot master list
212+
# Add application owner into owner_ids list
207213
owner: discord.User = (await self.application_info()).owner
208-
if owner and owner.id not in self.master:
209-
self.master += (owner.id,)
214+
if owner and owner.id not in self.owner_ids:
215+
self.owner_ids += (owner.id,)
210216

211217
# change bot's presence into guild live count
212218
self.changing_presence.start()
@@ -216,6 +222,11 @@ async def startUp(self) -> None:
216222
if not hasattr(self, "uptime"):
217223
self.uptime: datetime.datetime = utcnow()
218224

225+
@property
226+
def master(self):
227+
warnings.warn("Bot.master is deprecated, use self.owner_ids instead")
228+
return self.owner_ids
229+
219230
async def getGuildConfigs(
220231
self, guildId: int, filters: Iterable = "*", table: str = "guildConfigs"
221232
) -> Dict[str, Any]:
@@ -609,7 +620,7 @@ async def on_message(self, message) -> None:
609620
message.author.bot
610621
or message.author.id in self.blacklist.users
611622
or (message.guild and message.guild.id in self.blacklist.guilds)
612-
) and message.author.id not in self.master:
623+
) and message.author.id not in self.owner_ids:
613624
return
614625

615626
# if bot is mentioned without any other message, send prefix list
@@ -636,7 +647,7 @@ async def on_message_edit(self, before, after):
636647
message.author.bot
637648
or message.author.id in self.blacklist.users
638649
or (message.guild and message.guild.id in self.blacklist.guilds)
639-
) and message.author.id not in self.master:
650+
) and message.author.id not in self.owner_ids:
640651
return
641652

642653
await self.process(message)

core/checks.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def has_guild_permissions(**perms):
88
async def predicate(ctx):
99
orig = commands.has_guild_permissions(**perms).predicate
1010
try:
11-
isMaster = ctx.author.id in ctx.bot.master
11+
isMaster = ctx.author.id in ctx.bot.owner_ids
1212
except AttributeError:
1313
isMaster = False
1414
return isMaster or await orig(ctx)
@@ -21,7 +21,7 @@ async def predicate(ctx):
2121

2222
def is_botmaster():
2323
def predicate(ctx):
24-
return ctx.author.id in ctx.bot.master
24+
return ctx.author.id in ctx.bot.owner_ids
2525

2626
return commands.check(predicate)
2727

core/errors.py

+5
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ def __init__(self, missing_permissions=None, *args):
8080
)
8181

8282
super().__init__(message, *args)
83+
84+
85+
class NotNSFWChannel(CommandError):
86+
def __init__(self):
87+
super().__init__("You're only allowed to use this command in a NSFW channels!")

core/menus.py

+62-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from __future__ import annotations
2+
13
import asyncio
4+
from collections import namedtuple
25
from contextlib import suppress
3-
from typing import List, Optional, Union
6+
from typing import TYPE_CHECKING, Any, Iterable, List, Optional, Union
47

58
import discord
69
from discord.ext import menus
@@ -9,6 +12,10 @@
912
from core.views import ZView
1013

1114

15+
if TYPE_CHECKING:
16+
from core.context import Context
17+
18+
1219
class ZMenu(menus.MenuPages):
1320
def __init__(self, source, init_msg=None, check_embeds=True, ping=False, loop=None):
1421
super().__init__(source=source, check_embeds=check_embeds)
@@ -46,7 +53,7 @@ async def finalize(self, timed_out):
4653

4754

4855
class ZReplyMenu(ZMenu):
49-
def __init__(self, source, ping=False):
56+
def __init__(self, source, ping=False) -> None:
5057
self.ping = ping or False
5158
super().__init__(source=source, check_embeds=True)
5259

@@ -74,15 +81,20 @@ class ZMenuView(ZView):
7481

7582
def __init__(
7683
self,
77-
ctx,
84+
ctx: Context,
7885
*,
7986
timeout: float = 180.0,
8087
ownerOnly: bool = True,
8188
) -> None:
82-
super().__init__(ctx.author, timeout=timeout)
89+
owner: Union[discord.User, discord.Member] = ctx.author
90+
super().__init__(owner, timeout=timeout)
8391
self.context = ctx
8492
self._message: Optional[discord.Message] = None
8593
self.currentPage: int = 0
94+
if isinstance(owner, discord.Member):
95+
self.compact = owner.is_on_mobile()
96+
else:
97+
self.compact = False
8698

8799
def shouldAddButtons(self):
88100
return True
@@ -118,12 +130,14 @@ class ZMenuPagesView(ZMenuView):
118130

119131
def __init__(
120132
self,
121-
ctx,
133+
ctx: Context,
122134
source: Union[menus.PageSource, Pages],
123135
**kwargs,
124136
) -> None:
125137
self._source: Union[menus.PageSource, Pages] = source
126138
super().__init__(ctx, **kwargs)
139+
self.pageFmt = ("Page " if not self.compact else "") + "{current}/{last}"
140+
self._pageInfo.label = self.pageFmt.format(current="N/A", last="N/A")
127141

128142
def shouldAddButtons(self):
129143
source = self._source
@@ -161,10 +175,12 @@ async def sendInitialMessage(self, ctx):
161175
kwargs = await self.getPage(0)
162176
if self.shouldAddButtons():
163177
kwargs["view"] = self
164-
self._pageInfo.label = f"Page 1/{self.getMaxPages()}"
178+
self._pageInfo.label = self.pageFmt.format(
179+
current="1", last=self.getMaxPages()
180+
)
165181
if self.getMaxPages() == 2:
166-
self.remove_item(self._first)
167-
self.remove_item(self._last)
182+
self.remove_item(self._first) # type: ignore
183+
self.remove_item(self._last) # type: ignore
168184
return await ctx.try_reply(**kwargs)
169185

170186
async def sendPage(
@@ -175,8 +191,10 @@ async def sendPage(
175191

176192
self.currentPage = pageNumber
177193
kwargs = await self.getPage(pageNumber)
178-
self._pageInfo.label = f"Page {pageNumber+1}/{self.getMaxPages()}"
179-
await interaction.message.edit(view=self, **kwargs)
194+
self._pageInfo.label = self.pageFmt.format(
195+
current=pageNumber + 1, last=self.getMaxPages()
196+
)
197+
await interaction.message.edit(view=self, **kwargs) # type: ignore
180198

181199
async def sendCheckedPage(self, interaction: discord.Interaction, pageNumber):
182200
maxPages = self.getMaxPages()
@@ -228,8 +246,8 @@ async def _pageInfo(
228246
message: discord.Message = await self.context.bot.wait_for(
229247
"message",
230248
timeout=30.0,
231-
check=lambda msg: msg.author.id == interaction.user.id
232-
and msg.channel.id == interaction.channel.id
249+
check=lambda msg: msg.author.id == interaction.user.id # type: ignore
250+
and msg.channel.id == interaction.channel.id # type: ignore
233251
and msg.content.isdigit(),
234252
)
235253
with suppress(discord.HTTPException, discord.NotFound):
@@ -259,3 +277,35 @@ async def _last(self, button: discord.ui.Button, interaction: discord.Interactio
259277
)
260278
async def _stop(self, button: discord.ui.Button, interaction: discord.Interaction):
261279
await self.stop()
280+
281+
282+
choice = namedtuple("choice", ("label", "value"))
283+
284+
285+
class ZChoices(ZView):
286+
"""Basically send choices as buttons"""
287+
288+
def __init__(self, ctx: Context, choices: Iterable[Any]):
289+
super().__init__(owner=ctx.author)
290+
self.context = ctx
291+
self.choices: Iterable[Any] = choices
292+
self.value: Any = None
293+
294+
def makeCallback(choice):
295+
async def callback(interaction):
296+
await interaction.response.defer()
297+
self.value = choice.value
298+
self.stop()
299+
300+
return callback
301+
302+
for choice in self.choices:
303+
button = discord.ui.Button(label=choice.label)
304+
button.callback = makeCallback(choice)
305+
self.add_item(button)
306+
307+
async def wait(self):
308+
await super().wait()
309+
310+
async def start(self):
311+
await self.wait()

core/mixin.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
6+
if TYPE_CHECKING:
7+
from databases import Database
8+
9+
from core.bot import ziBot
10+
11+
112
class CogMixin:
213
"""Mixin for Cogs/Exts."""
314

4-
def __init__(self, bot):
5-
self.bot = bot
15+
icon = "❓"
16+
cc = False
17+
18+
def __init__(self, bot: ziBot) -> None:
19+
self.bot: ziBot = bot
620

721
@property
8-
def db(self):
22+
def db(self) -> Database:
923
return self.bot.db

0 commit comments

Comments
 (0)