Compare commits
No commits in common. "393961410e65663bd7afef8e7d78c5ddd13c5fc6" and "186eda49344742682909302775474630f937b0d8" have entirely different histories.
393961410e
...
186eda4934
@ -38,9 +38,9 @@ def range_type(string, min=0, max=100):
|
||||
try:
|
||||
value = int(string)
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError("value is not a valid integer")
|
||||
raise argparse.ArgumentTypeError(f"value not a valid integer")
|
||||
|
||||
if min <= value <= max:
|
||||
return value
|
||||
else:
|
||||
raise argparse.ArgumentTypeError(f"value is not in range {min}-{max}")
|
||||
raise argparse.ArgumentTypeError(f"value not in range {min}-{max}")
|
||||
|
@ -1,16 +1,5 @@
|
||||
from . import bot, tools, utils, voice
|
||||
from .utils import Command, match, match_token, tokenize
|
||||
|
||||
__all__ = [
|
||||
"bot",
|
||||
"tools",
|
||||
"utils",
|
||||
"voice",
|
||||
"Command",
|
||||
"match",
|
||||
"match_token",
|
||||
"tokenize",
|
||||
]
|
||||
from .utils import *
|
||||
|
||||
|
||||
def __reload_module__():
|
||||
|
@ -1,6 +1,7 @@
|
||||
import re
|
||||
|
||||
import arguments
|
||||
|
||||
import commands
|
||||
import utils
|
||||
|
||||
@ -66,7 +67,7 @@ async def clear(message):
|
||||
if args.delete_command:
|
||||
try:
|
||||
await message.delete()
|
||||
except Exception:
|
||||
except:
|
||||
pass
|
||||
|
||||
regex = None
|
||||
@ -100,5 +101,5 @@ async def clear(message):
|
||||
message,
|
||||
f"purged **{messages}/{args.count} {'message' if args.count == 1 else 'messages'}**",
|
||||
)
|
||||
except Exception:
|
||||
except:
|
||||
pass
|
||||
|
@ -11,7 +11,7 @@ import youtubedl
|
||||
from state import client, players
|
||||
|
||||
|
||||
async def queue_or_play(message, edited=False):
|
||||
async def queue_or_play(message):
|
||||
await ensure_joined(message)
|
||||
if not command_allowed(message):
|
||||
return
|
||||
@ -73,15 +73,6 @@ async def queue_or_play(message, edited=False):
|
||||
if not (args := await parser.parse_args(message, tokens)):
|
||||
return
|
||||
|
||||
if edited:
|
||||
found = None
|
||||
for queued in players[message.guild.id].queue:
|
||||
if queued.trigger_message.id == message.id:
|
||||
found = queued
|
||||
break
|
||||
if found:
|
||||
players[message.guild.id].queue.remove(found)
|
||||
|
||||
if args.clear:
|
||||
players[message.guild.id].queue.clear()
|
||||
await utils.add_check_reaction(message)
|
||||
@ -126,11 +117,10 @@ async def queue_or_play(message, edited=False):
|
||||
)
|
||||
)
|
||||
>= 5
|
||||
and not len(message.guild.voice_client.channel.members) == 2
|
||||
):
|
||||
await utils.reply(
|
||||
message,
|
||||
"you can only queue **5 items** without the manage channels permission!",
|
||||
"you can only queue **5 songs** without the manage channels permission!",
|
||||
)
|
||||
return
|
||||
|
||||
@ -181,6 +171,7 @@ async def queue_or_play(message, edited=False):
|
||||
|
||||
def embed(description):
|
||||
e = disnake.Embed(
|
||||
title="Queued",
|
||||
description=description,
|
||||
color=constants.EMBED_COLOR,
|
||||
)
|
||||
@ -256,7 +247,6 @@ async def join(message):
|
||||
return await message.guild.voice_client.move_to(message.channel)
|
||||
|
||||
await message.channel.connect()
|
||||
await utils.add_check_reaction(message)
|
||||
|
||||
|
||||
async def leave(message):
|
||||
@ -264,7 +254,6 @@ async def leave(message):
|
||||
return
|
||||
|
||||
await message.guild.voice_client.disconnect()
|
||||
await utils.add_check_reaction(message)
|
||||
|
||||
|
||||
async def resume(message):
|
||||
@ -299,6 +288,9 @@ async def volume(message):
|
||||
if not command_allowed(message):
|
||||
return
|
||||
|
||||
if not message.guild.voice_client:
|
||||
return
|
||||
|
||||
tokens = commands.tokenize(message.content)
|
||||
parser = arguments.ArgumentParser(tokens[0], "set the current volume level")
|
||||
parser.add_argument(
|
||||
@ -311,7 +303,10 @@ async def volume(message):
|
||||
return
|
||||
|
||||
if not message.guild.voice_client.source:
|
||||
await utils.reply(message, "nothing is playing!")
|
||||
await utils.reply(
|
||||
message,
|
||||
f"nothing is playing!",
|
||||
)
|
||||
return
|
||||
|
||||
if args.volume is None:
|
||||
@ -324,17 +319,6 @@ async def volume(message):
|
||||
await utils.add_check_reaction(message)
|
||||
|
||||
|
||||
def delete_queued(messages):
|
||||
found = []
|
||||
for message in messages:
|
||||
for queued in players[message.guild.id].queue:
|
||||
if queued.trigger_message.id == message.id:
|
||||
found.append(queued)
|
||||
for queued in found:
|
||||
if queued in players[messages[0].guild.id].queue:
|
||||
players[messages[0].guild.id].queue.remove(queued)
|
||||
|
||||
|
||||
def play_after_callback(e, message, once):
|
||||
if e:
|
||||
print(f"player error: {e}")
|
||||
@ -352,11 +336,11 @@ def play_next(message, once=False):
|
||||
)
|
||||
except Exception as e:
|
||||
client.loop.create_task(
|
||||
utils.channel_send(message, f"error while trying to play: `{e}`")
|
||||
message.channel.send(f"error while trying to play: `{e}`")
|
||||
)
|
||||
return
|
||||
client.loop.create_task(
|
||||
utils.channel_send(message, f"**0.** {queued.format(show_queuer=True)}")
|
||||
message.channel.send(f"**0.** {queued.format(show_queuer=True)}")
|
||||
)
|
||||
|
||||
|
||||
|
@ -13,7 +13,6 @@ RELOADABLE_MODULES = [
|
||||
"constants",
|
||||
"core",
|
||||
"events",
|
||||
"tasks",
|
||||
"utils",
|
||||
"voice",
|
||||
"youtubedl",
|
||||
|
27
core.py
27
core.py
@ -4,20 +4,18 @@ import importlib
|
||||
import inspect
|
||||
import io
|
||||
import textwrap
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import disnake
|
||||
import disnake_paginator
|
||||
|
||||
import commands
|
||||
import constants
|
||||
import core
|
||||
import utils
|
||||
from state import client, command_locks, idle_tracker
|
||||
from state import client, command_locks, executed_messages
|
||||
|
||||
|
||||
async def on_message(message, edited=False):
|
||||
async def on_message(message):
|
||||
if not message.content.startswith(constants.PREFIX) or message.author.bot:
|
||||
return
|
||||
|
||||
@ -28,11 +26,6 @@ async def on_message(message, edited=False):
|
||||
if not matched:
|
||||
return
|
||||
|
||||
idle_tracker["last_used"] = time.time()
|
||||
if idle_tracker["is_idle"]:
|
||||
idle_tracker["is_idle"] = False
|
||||
await client.change_presence(status=disnake.Status.online)
|
||||
|
||||
if len(matched) > 1:
|
||||
await utils.reply(
|
||||
message,
|
||||
@ -88,7 +81,7 @@ async def on_message(message, edited=False):
|
||||
if len(output) > 2000:
|
||||
output = output.replace("`", "\\`")
|
||||
await disnake_paginator.ButtonPaginator(
|
||||
prefix="```\n",
|
||||
prefix=f"```\n",
|
||||
suffix="```",
|
||||
invalid_user_function=utils.invalid_user_handler,
|
||||
color=constants.EMBED_COLOR,
|
||||
@ -99,7 +92,11 @@ async def on_message(message, edited=False):
|
||||
elif len(output.strip()) == 0:
|
||||
await utils.add_check_reaction(message)
|
||||
else:
|
||||
await utils.channel_send(message, output)
|
||||
if message.id in executed_messages:
|
||||
await executed_messages[message.id].edit(output)
|
||||
else:
|
||||
response = await message.channel.send(output)
|
||||
executed_messages[message.id] = response
|
||||
case C.CLEAR | C.PURGE if message.author.id in constants.OWNERS:
|
||||
await commands.tools.clear(message)
|
||||
case C.JOIN:
|
||||
@ -108,7 +105,7 @@ async def on_message(message, edited=False):
|
||||
await commands.voice.leave(message)
|
||||
case C.QUEUE | C.PLAY:
|
||||
async with command_locks[message.guild.id]:
|
||||
await commands.voice.queue_or_play(message, edited)
|
||||
await commands.voice.queue_or_play(message)
|
||||
case C.SKIP:
|
||||
async with command_locks[message.guild.id]:
|
||||
await commands.voice.skip(message)
|
||||
@ -132,9 +129,9 @@ async def on_message(message, edited=False):
|
||||
|
||||
|
||||
async def on_voice_state_update(_, before, after):
|
||||
def is_empty(channel):
|
||||
return [m.id for m in (channel.members if channel else [])] == [client.user.id]
|
||||
|
||||
is_empty = lambda channel: [m.id for m in (channel.members if channel else [])] == [
|
||||
client.user.id
|
||||
]
|
||||
c = None
|
||||
if is_empty(before.channel):
|
||||
c = before.channel
|
||||
|
47
events.py
47
events.py
@ -1,52 +1,47 @@
|
||||
import asyncio
|
||||
import threading
|
||||
|
||||
import commands
|
||||
import core
|
||||
import tasks
|
||||
import events
|
||||
from state import client
|
||||
|
||||
dynamic_handlers = {}
|
||||
|
||||
async def on_ready():
|
||||
threading.Thread(
|
||||
name="cleanup",
|
||||
target=asyncio.run_coroutine_threadsafe,
|
||||
args=(
|
||||
tasks.cleanup(),
|
||||
client.loop,
|
||||
),
|
||||
).start()
|
||||
|
||||
async def trigger_dynamic_handlers(event_type: str, *data):
|
||||
if event_type in dynamic_handlers:
|
||||
for dynamic_handler in dynamic_handlers[event_type]:
|
||||
try:
|
||||
await dynamic_handler(*data)
|
||||
except Exception as e:
|
||||
print(
|
||||
f"error in dynamic event handler {dynamic_handler} for {event_type}: {e}"
|
||||
)
|
||||
|
||||
|
||||
async def on_message(message):
|
||||
await events.trigger_dynamic_handlers("on_message", message)
|
||||
|
||||
await core.on_message(message)
|
||||
|
||||
|
||||
async def on_message_edit(before, after):
|
||||
await events.trigger_dynamic_handlers("on_message_edit", before, after)
|
||||
|
||||
if before.content == after.content:
|
||||
return
|
||||
|
||||
await core.on_message(after, edited=True)
|
||||
|
||||
|
||||
async def on_message_delete(message):
|
||||
commands.voice.delete_queued([message])
|
||||
|
||||
|
||||
async def on_bulk_message_delete(messages):
|
||||
commands.voice.delete_queued(messages)
|
||||
await core.on_message(after)
|
||||
|
||||
|
||||
async def on_voice_state_update(member, before, after):
|
||||
await events.trigger_dynamic_handlers(
|
||||
"on_voice_state_update", member, before, after
|
||||
)
|
||||
|
||||
await core.on_voice_state_update(member, before, after)
|
||||
|
||||
|
||||
for k, v in client.get_listeners().items():
|
||||
for f in v:
|
||||
client.remove_listener(f, k)
|
||||
|
||||
client.add_listener(on_bulk_message_delete, "on_bulk_message_delete")
|
||||
client.add_listener(on_message, "on_message")
|
||||
client.add_listener(on_message_delete, "on_message_delete")
|
||||
client.add_listener(on_message_edit, "on_message_edit")
|
||||
client.add_listener(on_voice_state_update, "on_voice_state_update")
|
||||
|
3
main.py
3
main.py
@ -7,9 +7,8 @@ from state import client, start_time
|
||||
|
||||
@client.event
|
||||
async def on_ready():
|
||||
await events.trigger_dynamic_handlers("on_ready")
|
||||
print(f"logged in as {client.user} in {round(time.time() - start_time, 1)}s")
|
||||
|
||||
await events.on_ready()
|
||||
|
||||
|
||||
client.run(constants.SECRETS["TOKEN"])
|
||||
|
24
state.py
24
state.py
@ -1,32 +1,14 @@
|
||||
import collections
|
||||
import time
|
||||
|
||||
import disnake
|
||||
|
||||
|
||||
class LimitedSizeDict(collections.OrderedDict):
|
||||
def __init__(self, *args, **kwds):
|
||||
self.size_limit = kwds.pop("size_limit", 1000)
|
||||
super().__init__(*args, **kwds)
|
||||
self._check_size_limit()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super().__setitem__(key, value)
|
||||
self._check_size_limit()
|
||||
|
||||
def _check_size_limit(self):
|
||||
if self.size_limit is not None:
|
||||
while len(self) > self.size_limit:
|
||||
self.popitem(last=False)
|
||||
|
||||
command_locks = {}
|
||||
executed_messages = {}
|
||||
players = {}
|
||||
|
||||
intents = disnake.Intents.default()
|
||||
intents.message_content = True
|
||||
intents.members = True
|
||||
client = disnake.Client(intents=intents)
|
||||
|
||||
command_locks = LimitedSizeDict()
|
||||
idle_tracker = {"is_idle": False, "last_used": time.time()}
|
||||
message_responses = LimitedSizeDict()
|
||||
players = {}
|
||||
start_time = time.time()
|
||||
|
25
tasks.py
25
tasks.py
@ -1,25 +0,0 @@
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
import disnake
|
||||
|
||||
from state import client, idle_tracker, players
|
||||
|
||||
|
||||
async def cleanup():
|
||||
while True:
|
||||
await asyncio.sleep(3600)
|
||||
|
||||
targets = []
|
||||
for id, player in players:
|
||||
if len(player.queue) == 0:
|
||||
targets.append(id)
|
||||
for target in targets:
|
||||
del players[target]
|
||||
|
||||
if (
|
||||
not idle_tracker["is_idle"]
|
||||
and time.time() - idle_tracker["last_used"] >= 3600
|
||||
):
|
||||
await client.change_presence(status=disnake.Status.idle)
|
||||
idle_tracker["is_idle"] = True
|
25
utils.py
25
utils.py
@ -1,13 +1,10 @@
|
||||
import disnake
|
||||
|
||||
import constants
|
||||
from state import message_responses
|
||||
|
||||
|
||||
def format_duration(duration: int):
|
||||
def format_plural(noun, count):
|
||||
return noun if count == 1 else noun + "s"
|
||||
|
||||
format_plural = lambda noun, count: noun if count == 1 else noun + "s"
|
||||
segments = []
|
||||
|
||||
weeks, duration = divmod(duration, 604800)
|
||||
@ -37,27 +34,9 @@ async def add_check_reaction(message):
|
||||
|
||||
|
||||
async def reply(message, *args, **kwargs):
|
||||
if message.id in message_responses:
|
||||
await message_responses[message.id].edit(
|
||||
await message.reply(
|
||||
*args, **kwargs, allowed_mentions=disnake.AllowedMentions.none()
|
||||
)
|
||||
else:
|
||||
response = await message.reply(
|
||||
*args, **kwargs, allowed_mentions=disnake.AllowedMentions.none()
|
||||
)
|
||||
message_responses[message.id] = response
|
||||
|
||||
|
||||
async def channel_send(message, *args, **kwargs):
|
||||
if message.id in message_responses:
|
||||
await message_responses[message.id].edit(
|
||||
*args, **kwargs, allowed_mentions=disnake.AllowedMentions.none()
|
||||
)
|
||||
else:
|
||||
response = await message.channel.send(
|
||||
*args, **kwargs, allowed_mentions=disnake.AllowedMentions.none()
|
||||
)
|
||||
message_responses[message.id] = response
|
||||
|
||||
|
||||
async def invalid_user_handler(interaction):
|
||||
|
@ -68,7 +68,7 @@ class QueuedSong:
|
||||
)
|
||||
else:
|
||||
return (
|
||||
f"[`{self.player.title}`]({'<' if hide_preview else ''}{self.player.original_url}{'>' if hide_preview else ''}) **[{self.format_duration(self.player.duration) if self.player.duration else 'live'}]**"
|
||||
f"[`{self.player.title}`]({'<' if hide_preview else ''}{self.player.original_url}{'>' if hide_preview else ''}) [{self.format_duration(self.player.duration) if self.player.duration else 'live'}]"
|
||||
+ (f" (<@{self.trigger_message.author.id}>)" if show_queuer else "")
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user