Skip to content

Commit

Permalink
Merge pull request #221 from IgKniteDev/develop
Browse files Browse the repository at this point in the history
🔨 [tuning] Improved voice cleanups, restrictions and more
  • Loading branch information
hitblast authored May 22, 2023
2 parents 29fae98 + c2a29ba commit a113223
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 35 deletions.
1 change: 1 addition & 0 deletions .github/workflows/formatting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- develop

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

<br> <img src="static/banner.png">

[![CodeQL](https://github.com/IgKniteDev/IgKnite/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/IgKniteDev/IgKnite/actions/workflows/github-code-scanning/codeql)
[![CodeSee](https://github.com/IgKniteDev/IgKnite/actions/workflows/codesee-arch-diagram.yml/badge.svg)](https://github.com/IgKniteDev/IgKnite/actions/workflows/codesee-arch-diagram.yml)
[![Format](https://github.com/IgKniteDev/IgKnite/actions/workflows/formatting.yml/badge.svg)](https://github.com/IgKniteDev/IgKnite/actions/workflows/formatting.yml)
[![Lint](https://github.com/IgKniteDev/IgKnite/actions/workflows/linting.yml/badge.svg)](https://github.com/IgKniteDev/IgKnite/actions/workflows/linting.yml)
Expand Down
4 changes: 2 additions & 2 deletions cogs/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import core


# Backend for ping-labelled commands.
# Common backend for ping-labelled commands.
# Do not use it within other commands unless really necessary.
async def _ping_backend(inter: disnake.CommandInteraction) -> core.TypicalEmbed:
system_latency = round(inter.bot.latency * 1000)
Expand Down Expand Up @@ -88,7 +88,7 @@ async def on_reaction_add(self, reaction: disnake.Reaction, member: disnake.Memb
)
await member.send(embed=embed, view=view)

# Backend for avatar-labelled commands.
# Common backend for avatar-labelled commands.
# Do not use it within other commands unless really necessary.
async def _avatar_backend(
self, inter: disnake.CommandInteraction, member: disnake.Member = None
Expand Down
2 changes: 1 addition & 1 deletion cogs/inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async def _guildinfo(self, inter: disnake.CommandInteraction) -> None:

await inter.send(embed=embed)

# Backend for userinfo-labelled commands.
# Common backend for userinfo-labelled commands.
# Do not use it within other commands unless really necessary.
async def _userinfo_backend(
self, inter: disnake.CommandInteraction, member: disnake.Member = None
Expand Down
4 changes: 2 additions & 2 deletions cogs/moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async def _ban(
await inter.guild.ban(member, reason=reason)
await inter.send(f'Member **{member.display_name}** has been banned! Reason: {reason}')

# Backend for softban-labelled commands.
# Common backend for softban-labelled commands.
# Do not use it within other commands unless really necessary.
async def _softban_backend(
self,
Expand Down Expand Up @@ -191,7 +191,7 @@ def is_me(message: disnake.Message) -> bool:
else:
await inter.channel.purge(limit=amount)

# Backend for ripplepurge-labelled commands.
# Common backend for ripplepurge-labelled commands.
# Do not use it within other commands unless really necessary.
async def _ripplepurge_backend(
self,
Expand Down
88 changes: 60 additions & 28 deletions cogs/music.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ def parse_duration(duration: int) -> str:

duration = []
if days > 0:
duration.append(f'{days}d ')
duration.append(f'{days}')
if hours > 0:
duration.append(f'{hours}:')
duration.append(f'{hours}')
if minutes > 0:
duration.append(f'{minutes}:')
duration.append(f'{minutes}')
if seconds > 0:
duration.append(f'{seconds}')

return ''.join(duration)
return ':'.join(duration)


# YTDLSource class with equalized playback.
Expand Down Expand Up @@ -535,7 +535,11 @@ async def on_voice_state_update(

else:
if not member.voice:
state.voice.cleanup()
try:
state.voice.cleanup()
except AttributeError:
pass

await state.stop()
del self.voice_states[member.guild.id]

Expand All @@ -557,24 +561,26 @@ async def cog_before_user_command_invoke(self, inter: disnake.CommandInteraction
inter.voice_state = self.init_voice_state(inter)
return await inter.response.defer()

async def _ensure_voice_safety(self, inter: disnake.CommandInteraction) -> Any | None:
if not inter.voice_state.voice:
# A coroutine for ensuring proper voice safety during playback.
async def _ensure_voice_safety(
self, inter: disnake.CommandInteraction, skip_self: bool = False
) -> Any | None:
if (not skip_self) and (not inter.voice_state.voice):
return await inter.send('I\'m not inside any voice channel.', ephemeral=True)

if not inter.author.voice or inter.author.voice.channel != inter.voice_state.voice.channel:
elif (
not inter.author.voice or inter.author.voice.channel != inter.voice_state.voice.channel
):
return await inter.send('You\'re not in my voice channel.', ephemeral=True)
else:
return True

return True

# A coroutine for commands which sets the destination voice channel of the bot
# as needed. Commonly used in play-labelled commands.
async def _join_logic(
self,
inter: disnake.CommandInteraction,
channel: disnake.VoiceChannel | disnake.StageChannel | None = None,
) -> Any:
'''
A sub-method for commands requiring the bot to join a voice / stage channel.
'''

) -> Any | None:
destination = channel or (inter.author.voice and inter.author.voice.channel)

try:
Expand Down Expand Up @@ -650,15 +656,17 @@ async def _leave(self, inter: disnake.CommandInteraction) -> None:
dm_permission=False,
)
async def _volume(self, inter: disnake.CommandInteraction, volume: float) -> None:
if not inter.voice_state.is_playing:
if not await self._ensure_voice_safety(inter):
return
elif not inter.voice_state.is_playing:
return await inter.send('There\'s nothing being played at the moment.', ephemeral=True)

inter.voice_state.current.source.volume = (vol_mod := volume / 100)
inter.voice_state.volume = vol_mod

await inter.send(
f'Volume of the player is now set to **{volume}%**'
+ ('(⚠️ reduced quality) ' if volume > 100 else '')
+ (' (⚠️ reduced quality) ' if volume > 100 else '')
)

# now
Expand All @@ -671,6 +679,7 @@ async def _now(self, inter: disnake.CommandInteraction) -> None:
if inter.voice_state.is_playing:
embed, view = inter.voice_state.current.create_embed(inter)
await inter.send(embed=embed, view=view)

else:
await inter.send('There\'s nothing being played at the moment.', ephemeral=True)

Expand Down Expand Up @@ -736,8 +745,7 @@ async def _stop(self, inter: disnake.CommandInteraction) -> None:
async def _skip(self, inter: disnake.CommandInteraction) -> None:
if not await self._ensure_voice_safety(inter):
return

if not inter.voice_state.is_playing:
elif not inter.voice_state.is_playing:
return await inter.send('There\'s nothing being played at the moment.', ephemeral=True)

if inter.voice_state.loop:
Expand Down Expand Up @@ -773,7 +781,9 @@ async def _skip(self, inter: disnake.CommandInteraction) -> None:
name='queue', description='Shows the player\'s queue.', dm_permission=False
)
async def _queue(self, inter: disnake.CommandInteraction) -> None:
if len(songs := inter.voice_state.songs) == 0:
if not await self._ensure_voice_safety(inter):
return
elif len(songs := inter.voice_state.songs) == 0:
return await inter.send('The queue is empty.', ephemeral=True)

page = 1
Expand Down Expand Up @@ -835,8 +845,7 @@ async def page_loader(page_num: int) -> core.TypicalEmbed:
async def _rmqueue(self, inter: disnake.CommandInteraction, index: int):
if not await self._ensure_voice_safety(inter):
return

if len(inter.voice_state.songs) == 0:
elif len(inter.voice_state.songs) == 0:
return await inter.send('The queue is empty, so nothing to be removed.', ephemeral=True)

inter.voice_state.songs.remove(index - 1)
Expand All @@ -847,6 +856,9 @@ async def _rmqueue(self, inter: disnake.CommandInteraction, index: int):
name='shuffle', description='Shuffles the current queue.', dm_permission=False
)
async def _shuffle(self, inter: disnake.CommandInteraction) -> None:
if not await self._ensure_voice_safety(inter):
return

inter.voice_state.songs.shuffle()
await inter.send('Shuffled your queue!')

Expand All @@ -855,10 +867,13 @@ async def _shuffle(self, inter: disnake.CommandInteraction) -> None:
name='loop', description='Toggles loop for the current song.', dm_permission=False
)
async def _loop(self, inter: disnake.CommandInteraction) -> None:
if not await self._ensure_voice_safety(inter):
return

inter.voice_state.loop = not inter.voice_state.loop
await inter.send(f"Loop has been {'enabled' if inter.voice_state.loop else 'disabled'}!")

# Backend for play-labelled commands.
# Common backend for play-labelled commands.
# Do not use it within other commands unless really necessary.
async def _play_backend(
self,
Expand All @@ -868,9 +883,6 @@ async def _play_backend(
send_embed: bool = True,
boosted: bool = False,
) -> None:
if not inter.voice_state.voice:
await self._join_logic(inter)

try:
source = await (YTDLSource if not boosted else YTDLSourceBoosted).create_source(
inter, keyword, loop=self.bot.loop
Expand All @@ -896,6 +908,16 @@ async def _play_backend(
view = core.SmallView(inter).add_button(label='Redirect', url=song.source.url)
await inter.send(embed=embed, view=view)

# Separate coroutine for ensuring voice safety especially for play-labelled commands.
# Note: This coroutine is used in conjunction with _ensure_voice_safety() and _join_logic().
async def _ensure_play_safety(self, inter: disnake.CommandInteraction) -> True | False:
if (not inter.voice_state.voice) and (not await self._join_logic(inter)):
return False
elif not await self._ensure_voice_safety(inter, skip_self=True):
return False
else:
return True

# play (slash)
@commands.slash_command(
name='play',
Expand All @@ -918,6 +940,9 @@ async def _play_backend(
async def _play(
self, inter: disnake.CommandInteraction, keyword: str, boosted: bool = False
) -> None:
if not await self._ensure_play_safety(inter):
return

inter.voice_state.boosted = boosted

async def process_spotify_tracks(ids, tracks) -> None:
Expand Down Expand Up @@ -963,13 +988,20 @@ async def process_spotify_tracks(ids, tracks) -> None:
async def _play_message(
self, inter: disnake.CommandInteraction, message: disnake.Message
) -> None:
if not await self._ensure_play_safety(inter):
return

await self._play_backend(inter, message.content)

# Backend for play-labelled commands.
# Common backend for playrich-labelled commands.
# Do not use it within other commands unless really necessary.
# Note: This backend is used in conjunction with _play_backend().
async def _playrich_backend(
self, inter: disnake.CommandInteraction, member: disnake.Member | None = None
) -> None:
if not await self._ensure_play_safety(inter):
return

member = member or inter.author

for activity in member.activities:
Expand Down
2 changes: 1 addition & 1 deletion core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .ui import *

# Set version number.
__version_info__ = ('2023', '5', '19') # Year.Month.Day
__version_info__ = ('2023', '5', '22') # Year.Month.Day
__version__ = '.'.join(__version_info__)


Expand Down

0 comments on commit a113223

Please sign in to comment.