Skip to content

Commit

Permalink
Merge pull request #40 from TK-Entertainment/WIP/queue-rework
Browse files Browse the repository at this point in the history
m.20240318.5-s
  • Loading branch information
kevin0216 authored Aug 11, 2024
2 parents 241d52a + 8f24b8a commit 5f31761
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 65 deletions.
6 changes: 2 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
status = discord.Status.online
production_status = "s" # ce for cutting edge, s for stable
test_subject = "wl3.0_test"
bot_version = "m.20240318.4{}-{}".format(f".{test_subject}" if production_status != "s" else "", production_status)
bot_version = "m.20240318.5{}-{}".format(f".{test_subject}" if production_status != "s" else "", production_status)
else:
status = discord.Status.dnd
bot_version = f"LOCAL DEVELOPMENT / {branch} Branch\nMusic Function"
Expand All @@ -30,7 +30,7 @@
intents = discord.Intents.default()
intents.message_content = False
bot = commands.AutoShardedBot(
command_prefix=prefix, intents=intents, help_command=None, status=status
command_prefix=prefix, intents=intents, help_command=None, status=status, shard_count=10
)

from music_comp import *
Expand All @@ -50,7 +50,6 @@ async def precense_update():
await bot.change_presence(activity=precense)
await asyncio.sleep(10)


async def count_total():
total_count = 0
for guild in bot.guilds:
Expand Down Expand Up @@ -103,7 +102,6 @@ async def on_wavelink_node_ready(payload: wavelink.NodeReadyEventPayload):
"""
)


try:
bot.run(TOKEN)
except AttributeError:
Expand Down
51 changes: 43 additions & 8 deletions music_comp/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import asyncio, os
import dotenv
import validators
import random

import discord
from discord.ext import commands
Expand Down Expand Up @@ -33,6 +34,7 @@ async def _create_daemon(self):
# Env value setup
# Wavelink needed value
TW_HOST = os.getenv("WAVELINK_TW_HOST")
BILI_HOST = os.getenv("WAVELINK_BILI_HOST")
LOCAL_SEARCH_HOST_1 = os.getenv("WAVELINK_SEARCH_HOST_1")
LOCAL_SEARCH_HOST_2 = os.getenv("WAVELINK_SEARCH_HOST_2")
PORT = os.getenv("WAVELINK_PORT")
Expand All @@ -46,6 +48,11 @@ async def _create_daemon(self):
uri=f"http://{TW_HOST}:{PORT}",
password=PASSWORD,
)
bilibili_host = wavelink.Node(
identifier="BilibiliNode",
uri=f"http://{BILI_HOST}:{PORT}",
password=PASSWORD,
)
searchhost_1 = wavelink.Node(
identifier="SearchNode_1",
uri=f"http://{LOCAL_SEARCH_HOST_1}:{SEARCH_PORT_1}",
Expand All @@ -59,7 +66,7 @@ async def _create_daemon(self):

# Wavelink connection establishing
await wavelink.Pool.connect(
nodes=[mainplayhost, searchhost_1, searchhost_2],
nodes=[mainplayhost, bilibili_host, searchhost_1, searchhost_2],
cache_capacity=100,
client=self.bot,
)
Expand All @@ -71,7 +78,7 @@ async def _join(self, channel: discord.VoiceChannel):
voice_client = channel.guild.voice_client
mainplayhost = wavelink.Pool.get_node("TW_PlayBackNode")
if voice_client is None:
player = wavelink.Player()
player = wavelink.Player(nodes=[mainplayhost])
player.inactive_timeout = 600
await channel.connect(cls=player)

Expand Down Expand Up @@ -158,6 +165,12 @@ async def _play(self, guild: discord.Guild, channel: discord.TextChannel):
self[guild.id].text_channel = channel
voice_client: wavelink.Player = guild.voice_client

if self._playlist[guild.id].current() is not None and self._playlist[guild.id].current().source == "http":
voice_client.switch_node(wavelink.Pool.get_node("BilibiliNode"))
else:
if voice_client.node.identifier != "TW_PlayBackNode":
voice_client.switch_node(wavelink.Pool.get_node("TW_PlayBackNode"))

if (not voice_client.paused) and (voice_client.current is None) and (len(self._playlist[guild.id].order) > 0):
await voice_client.play(self._playlist[guild.id].current())

Expand Down Expand Up @@ -580,7 +593,7 @@ async def _i_play(self, interaction: discord.Interaction, search: str):
return
else:
tracks = await self.track_helper.get_track(interaction, search)
if isinstance(tracks, Exception) or tracks is None:
if isinstance(tracks, Exception) or tracks is [None] or tracks is None:
await self.ui.Search.SearchFailed(interaction, search)
await self.play(interaction, tracks)
else:
Expand Down Expand Up @@ -647,10 +660,10 @@ async def on_wavelink_track_end(self, payload: wavelink.TrackEndEventPayload):
await self.ui.PlayerControl.DonePlaying(self[guild.id].text_channel)
return
else:
await self.track_helper.process_suggestion(guild, self.ui_guild_info(guild.id)),

player: wavelink.Player = guild.voice_client

self.bot.loop.create_task(self.track_helper.process_suggestion(guild, self.ui_guild_info(guild.id)))

song = self._playlist[guild.id].current()
try:
await player.play(song)
Expand All @@ -659,6 +672,19 @@ async def on_wavelink_track_end(self, payload: wavelink.TrackEndEventPayload):
await self.ui.PlayerControl.PlayingError(self[guild.id].text_channel, e)
pass

@commands.Cog.listener()
async def on_wavelink_node_disconnected(self, payload: wavelink.NodeDisconnectedEventPayload) -> None:
node: wavelink.Node = payload.node
new_node: wavelink.Node = wavelink.Pool.get_node() # You can get a specific node if you want...
if not new_node:
return

players: dict[int, wavelink.Player] = node.players
for guild_id, player in players.items():
try:
await player.switch_node(new_node)
except RuntimeError:
await player.disconnect()

# Error handler
@commands.Cog.listener()
Expand Down Expand Up @@ -692,8 +718,14 @@ async def _pause_on_being_alone(
):
try:
voice_client: wavelink.Player = member.guild.voice_client
if len(voice_client.channel.members) == 1 and member != self.bot.user:
await self.ui._InfoGenerator._UpdateSongInfo(member.guild.id)
if len(voice_client.channel.members) == 1 and member != self.bot.user \
and len(self._playlist[member.guild.id].order) > 0:

if not self.ui_guild_info(member.guild.id).playinfo is None:
await self.ui._InfoGenerator._UpdateSongInfo(member.guild.id)
else:
await self.ui.PlayerControl.PlayingMsg(self[member.guild.id].text_channel)

self.ui_guild_info(member.guild.id).playinfo_view.playorpause.emoji = discord.PartialEmoji.from_str("▶️")
self.ui_guild_info(member.guild.id).playinfo_view.playorpause.disabled = True
self.ui_guild_info(member.guild.id).playinfo_view.playorpause.style = discord.ButtonStyle.gray
Expand All @@ -714,7 +746,10 @@ async def _pause_on_being_alone(
and member != self.bot.user
and self.ui_guild_info(member.guild.id).playinfo_view.playorpause.disabled
):
await self.ui._InfoGenerator._UpdateSongInfo(member.guild.id)
if not self.ui_guild_info(member.guild.id).playinfo is None:
await self.ui._InfoGenerator._UpdateSongInfo(member.guild.id)
else:
await self.ui.PlayerControl.PlayingMsg(self[member.guild.id].text_channel)

self.ui_guild_info(member.guild.id).playinfo_view.playorpause.disabled = False
self.ui_guild_info(member.guild.id).playinfo_view.playorpause.style = discord.ButtonStyle.blurple
Expand Down
11 changes: 6 additions & 5 deletions music_comp/ui_comp/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def ChangeLogsDefine(self) -> None:

# Define if this version is inherit from specfic test version
self.inherit_from_version = ""
self.picture = "https://cdn.discordapp.com/attachments/642704558996586496/1262838299735621684/image.png?ex=66980d51&is=6696bbd1&hm=0443c66aa4de144678a868d73eb39936a27de92e5fe8aa65d204aa3b75762eea&"
self.picture = ""
self.emergency_build = False

self.github_link = "https://github.com/TK-Entertainment/tkablent_music/releases/tag/m.20240318-s"
Expand All @@ -40,10 +40,11 @@ def ChangeLogsDefine(self) -> None:
# Index 1 means changelog summary
# Index 2 means changelog description
self.changelogs = [
["+", "【新增】新增群組最愛點播/近期點播選項 (可參圖)", "=> 在上次意見回饋中,我們發現有些群組希望能夠快速點播最愛或近期點播過的歌曲\n=> 現在您可以在點播選單中選擇「這群ㄉ最愛!」或「最近播放」來點播\n=> 請注意,最愛歌曲的結果會在該群組點播歌曲至一定數量時出現 (不含自動播放)"],
["+", "【新增】全新新增歌曲介面 (由播放介面進入)", "=> 現在最愛點播/近期點播選項也在點選介面上可用!\n=> 使用手機的你也可以點播最愛點播/近期點播的歌了"],
["!", "【修復】修復上個版本無法透過介面暫停的問題", "=> 此版本已修復此問題"],
["!", "【改進】一些有的沒的穩定性及可靠性修復", "=> 我也不知道修了啥,但應該是有的 (*°∀°)"],
["!", "【改進】針對一些嚴重影響播放的問題進行穩定性改進", "=> 此版本已修復此問題"],
["!", "【修復】嘗試改進快速搜尋推薦的速度", "=> 此版本嘗試改善此問題導致的部分群組無法使用的問題"],
["(!)", "【緊急修復】嘗試修復因近期 API 限制影響,造成機器人當機的問題", "=> 此版本嘗試修復此問題,若仍舊發生請至支援群組回報"],
["(!)", "【緊急修復】修復因近期 API 限制影響,有部分伺服器無法使用推薦候選功能", "=> 此版本已修復此問題,但可能造成部分歌曲不會列入選項內"],
["(!)", "【緊急修復】修復上個版本後,快速搜尋功能失效的問題", "=> 此版本已修復此問題"],
]

async def SendChangelogs(self, interaction: discord.Interaction) -> None:
Expand Down
9 changes: 6 additions & 3 deletions music_comp/ui_comp/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,16 @@ def _SongInfo(
)
and color_code != "red"
):
if self.guild_info(guild_id).skip or self.guild_info(guild_id).suggestion_processing:
if self.guild_info(guild_id).suggestion_failure:
queuelist += f"**推薦歌曲載入失敗**"
elif self.guild_info(guild_id).skip or self.guild_info(guild_id).suggestion_processing:
queuelist += f"**推薦歌曲載入中**"
else:
queuelist += f"**:bulb:** {playlist[1].title}"
embed.add_field(
name="{}即將播放".format(
f":hourglass: | " if self.guild_info(guild_id).skip or self.guild_info(guild_id).suggestion_processing else ""
f":hourglass: | " if self.guild_info(guild_id).skip or self.guild_info(guild_id).suggestion_processing
else ":x: | " if self.guild_info(guild_id).suggestion_failure else ""
),
value=queuelist,
inline=False,
Expand Down Expand Up @@ -389,7 +392,7 @@ def _PlaylistInfo(
)

if (playlist[0].uri is not None) and ("spotify" in playlist[0].uri):
embed.set_thumbnail(url=playlist.artwork)
embed.set_thumbnail(url=playlist[0].artwork)

embed = discord.Embed.from_dict(dict(**embed.to_dict(), **self.embed_opt))

Expand Down
5 changes: 4 additions & 1 deletion music_comp/ui_comp/leave.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ def __init__(self, exception_handler, info_generator):
self.musicbot = musicbot

async def refresh_and_reset(self, guild: discord.Guild):
guild_info = self.guild_info(guild.id)

await asyncio.sleep(3)
await self.info_generator._UpdateSongInfo(guild.id)
if not guild_info.playinfo is None:
await self.info_generator._UpdateSongInfo(guild.id)
self.reset_value(guild)

def reset_value(self, guild):
Expand Down
18 changes: 12 additions & 6 deletions music_comp/ui_comp/player_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,26 @@ def __init__(
break

if len(result[currentindex].title) > 100:
result[currentindex].title = (
title = (
result[currentindex].title[:95] + "..."
)
else:
title = result[currentindex].title

if len(result[currentindex].author) > 85:
result[currentindex].author = (
author = (
result[currentindex].author[:70] + "..."
)
else:
author = result[currentindex].author

length = _sec_to_hms(
seconds=(result[currentindex].length) / 1000, format="symbol"
)
self.add_option(
label=result[currentindex].title,
label=title,
value=currentindex,
description=f"{result[currentindex].author} / {length}",
description=f"{author} / {length}",
)

self.max_values = len(self.options)
Expand Down Expand Up @@ -427,7 +431,8 @@ async def on_timeout(self):

async def stop_refresh(self, guild):
await asyncio.sleep(3)
await self.info_generator._UpdateSongInfo(guild.id)
if not self.guild_info(guild.id).playinfo is None:
await self.info_generator._UpdateSongInfo(guild.id)
self.guild_info(guild.id).playinfo = None
self.guild_info(guild.id).playinfo_view = None
self.guild_info(guild.id).leaveoperation = False
Expand Down Expand Up @@ -550,7 +555,8 @@ async def suggestion_control(self, interaction, button):
).playinfo_view.skip.disabled = False
else:
self.guild_info(channel.guild.id).suggestion_processing = True
await self.info_generator._UpdateSongInfo(interaction.guild.id)
if self.guild_info(channel.guild.id).playinfo is not None:
await self.info_generator._UpdateSongInfo(interaction.guild.id)
await interaction.response.edit_message(view=view)
await self.toggle(interaction, button, "done")
if self.guild_info(channel.guild.id).music_suggestion:
Expand Down
4 changes: 4 additions & 0 deletions music_comp/utils/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def __init__(self):
shutil.copyfile(self._bak_cache_path, self._cache_path)

async def update_cache(self, new_data: dict) -> None:
await asyncio.sleep(2)
"""update database"""
try:
with open(self._cache_path, "rb") as f:
Expand All @@ -49,7 +50,10 @@ async def update_cache(self, new_data: dict) -> None:
shutil.copyfile(self._bak_cache_path, self._cache_path)
if debug: print("[DEBUG | Cache Module] Overwriting main cache file with backup")

await asyncio.sleep(0.02)

for identifier in new_data.keys():
await asyncio.sleep(0.02)
if debug: print(f"[DEBUG | Cache Module] Fetched {identifier}")
if data.get(identifier) is not None:
if debug: print(f"[DEBUG | Cache Module] Updating {identifier}")
Expand Down
16 changes: 10 additions & 6 deletions music_comp/utils/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import json
import os
import wavelink
from msgspec.json import decode as json_decode
from msgspec import DecodeError
from msgspec.json import encode as json_encode

class GuildInfo:
def __init__(self, guild_id):
Expand Down Expand Up @@ -101,8 +104,8 @@ def changelogs_latestversion(self, value: str):

def fetch(self, key: str) -> None:
"""fetch from database"""
with open(self._database, "r") as f:
data: dict = json.load(f)
with open(self._database, "rb") as f:
data: dict = json_decode(f.read())
if (
data.get(str(self.guild_id)) is None
or data[str(self.guild_id)].get(key) is None
Expand All @@ -113,13 +116,13 @@ def fetch(self, key: str) -> None:
def update(self, key: str, value: str) -> None:
"""update database"""

with open(self._database, "r") as f:
data: dict = json.load(f)
with open(self._database, "rb") as f:
data: dict = json_decode(f.read())
if data.get(str(self.guild_id)) is None:
data[str(self.guild_id)] = dict()
data[str(self.guild_id)][key] = value
with open(self._database, "w") as f:
json.dump(data, f)
with open(self._database, "wb") as f:
f.write(json_encode(data))

class GuildUIInfo:
def __init__(self, guild_id):
Expand All @@ -146,6 +149,7 @@ def __init__(self, guild_id):
# Indicate that the suggestion is under processing
# Will be reseted to False after process is done
self.suggestion_processing: bool = False
self.suggestion_failure: bool = False

self.lasterrorinfo: dict = {}

Expand Down
Loading

0 comments on commit 5f31761

Please sign in to comment.