Skip to content

Commit

Permalink
Merge pull request #97 from Dysta/chore/separate-cogs-and-services
Browse files Browse the repository at this point in the history
feat: refactor services and cogs
  • Loading branch information
Dysta authored Jan 15, 2025
2 parents 5ca194f + ee040e3 commit 16a0522
Show file tree
Hide file tree
Showing 38 changed files with 383 additions and 365 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10-bookworm
FROM python:3.11-bookworm

WORKDIR /app

Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ services:

volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- ..:/app:cached
- ..:/app

# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python-unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: JukeBot CI Full
on:
push:
branches:
- '**'
- 'main'
pull_request:
branches:
- '**'
Expand All @@ -19,7 +19,7 @@ jobs:

strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.9', '3.10', '3.11']

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion jukebot/abstract_components/abstract_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __getitem__(self, idx: int) -> _T:
def __str__(self) -> str:
return str(self.set)

def __add__(self, other: "AbstractCollection") -> "AbstractCollection":
def __add__(self, other: AbstractCollection) -> AbstractCollection:
assert isinstance(other, AbstractCollection)
self.set += other.set
return self
7 changes: 7 additions & 0 deletions jukebot/abstract_components/abstract_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
class AbstractService:
"""This class allow you to implement your own service and using it from the bot.
To implement a service, create a new file in the `services` package then implement this class.
Don't forget, services are named `XXXService` where `XXX` is your action.
To register a service, go to the cog where it's used then in the setup function, add your service by using `bot.add_service(XXXService())`.
To use a service: `bot.services.XXX` where `XXX` is your previous named action.
"""

def __init__(self, bot):
self.bot = bot

Expand Down
119 changes: 95 additions & 24 deletions jukebot/cogs/music.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
from typing import Optional
from urllib import parse

from disnake import CommandInteraction, Embed
from disnake import APISlashCommand, CommandInteraction, Embed, Forbidden
from disnake.ext import commands
from disnake.ext.commands import Bot, BucketType
from disnake.ext.commands import BucketType

from jukebot import JukeBot
from jukebot.components.player import Player
from jukebot.components.requests import ShazamRequest
from jukebot.exceptions import QueryFailed
from jukebot.services.music import (
Expand All @@ -26,7 +28,7 @@

class Music(commands.Cog):
def __init__(self, bot):
self.bot: Bot = bot
self.bot: JukeBot = bot

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -43,8 +45,18 @@ async def play(self, inter: CommandInteraction, query: str, top: Optional[bool]
top : Optional[bool], optional
Put the requested song at the top of the queue, by default False
"""
with PlayService(self.bot) as ps:
await ps(interaction=inter, query=query, top=top)
if self.bot.players.get(inter.guild.id).is_playing:
# ? if player is playing, play command is just a shortcut for queue add command
await self.bot.get_slash_command("queue add").callback(self, inter, query, top)
return

if not inter.response.is_done():
await inter.response.defer()

song, loop = await self.bot.services.play(interaction=inter, query=query, top=top)

e: Embed = embed.music_message(song, loop)
await inter.edit_original_message(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -59,8 +71,10 @@ async def leave(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with LeaveService(self.bot) as ls:
await ls(interaction=inter)
await self.bot.services.leave(guild_id=inter.guild.id)

e = embed.basic_message(title="Player disconnected")
await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -76,8 +90,10 @@ async def stop(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with StopService(self.bot) as ss:
await ss(interaction=inter)
await self.bot.services.stop(guild_id=inter.guild.id)

e = embed.basic_message(title="Player stopped")
await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -93,8 +109,10 @@ async def pause(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with PauseService(self.bot) as ps:
await ps(interaction=inter)
await self.bot.services.pause(guild_id=inter.guild.id)

e = embed.basic_message(title="Player paused")
await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -110,8 +128,23 @@ async def resume(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with ResumeService(self.bot) as rs:
await rs(interaction=inter)
player: Player = self.bot.players[inter.guild.id]
if player.state.is_stopped and not player.queue.is_empty():
# ? if player is stopped but queue isn't empty, resume the queue
await self.bot.get_slash_command("play").callback(self, inter, query="")
return

ok = await self.bot.services.resume(guild_id=inter.guild.id)

if ok:
e = embed.basic_message(title="Player resumed")
else:
cmd: APISlashCommand = self.bot.get_global_command_named("play")
e = embed.basic_message(
title="Nothing is currently playing", content=f"Try </play:{cmd.id}> to add a music !"
)

await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -126,8 +159,17 @@ async def current(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with CurrentSongService(self.bot) as css:
await css(inter)
song, stream, loop = await self.bot.services.current_song(guild_id=inter.guild.id)

if stream and song:
e = embed.music_message(song, loop, stream.progress)
else:
cmd: APISlashCommand = self.bot.get_global_command_named("play")
e = embed.basic_message(
title="Nothing is currently playing", content=f"Try </play:{cmd.id}> to add a music !"
)

await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -141,8 +183,12 @@ async def join(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with JoinService(self.bot) as js:
await js(interaction=inter)
await self.bot.services.join(interaction=inter)

e = embed.basic_message(
content=f"Connected to <#{inter.author.voice.channel.id}>\n" f"Bound to <#{inter.channel.id}>\n",
)
await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(3, 10.0, BucketType.user)
Expand All @@ -158,8 +204,10 @@ async def skip(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with SkipService(self.bot) as ss:
await ss(interaction=inter)
await self.bot.services.skip(guild_id=inter.guild.id)

e: embed = embed.basic_message(title="Skipped !")
await inter.send(embed=e)

@commands.slash_command()
@commands.check(checks.bot_is_playing)
Expand All @@ -175,8 +223,18 @@ async def grab(self, inter: CommandInteraction):
inter : CommandInteraction
The interaction
"""
with GrabService(self.bot) as gs:
await gs(interaction=inter)
song, stream = await self.bot.services.grab(guild_id=inter.guild.id)

e = embed.grab_message(song, stream.progress)
e.add_field(
name="Voice channel",
value=f"`{inter.guild.name}{inter.author.voice.channel.name}`",
)
try:
await inter.author.send(embed=e)
await inter.send("Check your DMs!", ephemeral=True)
except Forbidden:
await inter.send("Your DMs are closed!", embed=e, ephemeral=True)

@commands.slash_command()
@commands.cooldown(1, 5.0, BucketType.user)
Expand All @@ -199,8 +257,10 @@ async def loop(
- queue (loop the current queue)
- none (disable looping)
"""
with LoopService(self.bot) as lp:
await lp(interaction=inter, mode=mode)
new_status = await self.bot.services.loop(guild_id=inter.guild.id, mode=mode)

e: embed = embed.basic_message(title=new_status)
await inter.send(embed=e)

@commands.slash_command()
@commands.cooldown(1, 15.0, BucketType.guild)
Expand Down Expand Up @@ -267,5 +327,16 @@ async def share(self, inter: CommandInteraction, url: str):
await inter.edit_original_message(embed=e)


def setup(bot):
def setup(bot: JukeBot):
bot.add_cog(Music(bot))

bot.add_service(GrabService(bot))
bot.add_service(JoinService(bot))
bot.add_service(LeaveService(bot))
bot.add_service(LoopService(bot))
bot.add_service(PauseService(bot))
bot.add_service(PlayService(bot))
bot.add_service(ResumeService(bot))
bot.add_service(SkipService(bot))
bot.add_service(StopService(bot))
bot.add_service(CurrentSongService(bot))
Loading

0 comments on commit 16a0522

Please sign in to comment.