mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Progress is being done
This commit is contained in:
parent
c925bf9360
commit
71076a39a9
12 changed files with 72 additions and 49 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
*.egg-info
|
*.egg-info
|
||||||
.idea/misc.xml
|
.idea/misc.xml
|
||||||
.idea/royalnet.iml
|
.idea/royalnet.iml
|
||||||
|
dist/
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 3 - Alpha",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.8",
|
||||||
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)"
|
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,6 @@ class PlayCommand(Command):
|
||||||
"guild_id": guild.id,
|
"guild_id": guild.id,
|
||||||
"url": url,
|
"url": url,
|
||||||
})
|
})
|
||||||
await data.reply(f"✅ !")
|
message = f"▶️ Added to [c]{response['bard']['type']}[/c]:\n"
|
||||||
|
message += "\n".join([ytd['title'] for ytd in response['added']])
|
||||||
|
await data.reply(message)
|
|
@ -3,6 +3,7 @@ from royalnet.commands import *
|
||||||
from royalnet.serf.discord import DiscordSerf
|
from royalnet.serf.discord import DiscordSerf
|
||||||
from royalnet.serf.discord.discordbard import YtdlDiscord, DiscordBard
|
from royalnet.serf.discord.discordbard import YtdlDiscord, DiscordBard
|
||||||
from royalnet.utils import asyncify
|
from royalnet.utils import asyncify
|
||||||
|
import pickle
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -52,4 +53,17 @@ class PlayEvent(Event):
|
||||||
await bard.add(ytd)
|
await bard.add(ytd)
|
||||||
# Run the bard
|
# Run the bard
|
||||||
log.debug(f"Running voice for: {guild}")
|
log.debug(f"Running voice for: {guild}")
|
||||||
await self.serf.voice_run(guild)
|
# FIXME: sure?
|
||||||
|
self.loop.create_task(self.serf.voice_run(guild))
|
||||||
|
# Return the results
|
||||||
|
log.debug(f"Sending results...")
|
||||||
|
results = {
|
||||||
|
"added": [{
|
||||||
|
"title": ytd.info.title,
|
||||||
|
"embed_pickle": pickle.dumps(ytd.embed())
|
||||||
|
} for ytd in ytdl],
|
||||||
|
"bard": {
|
||||||
|
"type": bard.__class__.__name__,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
It is pretty unstable, compared to the rest of the bot, but it *should* work."""
|
It is pretty unstable, compared to the rest of the bot, but it *should* work."""
|
||||||
|
|
||||||
from .createrichembed import create_rich_embed
|
|
||||||
from .escape import escape
|
from .escape import escape
|
||||||
from .discordserf import DiscordSerf
|
from .discordserf import DiscordSerf
|
||||||
from . import discordbard
|
from . import discordbard
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"create_rich_embed",
|
|
||||||
"escape",
|
"escape",
|
||||||
"DiscordSerf",
|
"DiscordSerf",
|
||||||
"discordbard",
|
"discordbard",
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
from discord import Embed, Colour
|
|
||||||
from discord.embeds import EmptyEmbed
|
|
||||||
from royalnet.bard import YtdlInfo
|
|
||||||
|
|
||||||
|
|
||||||
def create_rich_embed(yi: YtdlInfo) -> Embed:
|
|
||||||
"""Return this info as a :py:class:`discord.Embed`."""
|
|
||||||
colors = {
|
|
||||||
"youtube": 0xCC0000,
|
|
||||||
"soundcloud": 0xFF5400,
|
|
||||||
"Clyp": 0x3DBEB3,
|
|
||||||
"Bandcamp": 0x1DA0C3,
|
|
||||||
}
|
|
||||||
embed = Embed(title=yi.title,
|
|
||||||
colour=Colour(colors.get(yi.extractor, 0x4F545C)),
|
|
||||||
url=yi.webpage_url if (yi.webpage_url and yi.webpage_url.startswith("http")) else EmptyEmbed)
|
|
||||||
if yi.thumbnail:
|
|
||||||
embed.set_thumbnail(url=yi.thumbnail)
|
|
||||||
if yi.uploader:
|
|
||||||
embed.set_author(name=yi.uploader,
|
|
||||||
url=yi.uploader_url if yi.uploader_url is not None else EmptyEmbed)
|
|
||||||
# embed.set_footer(text="Source: youtube-dl", icon_url="https://i.imgur.com/TSvSRYn.png")
|
|
||||||
if yi.duration:
|
|
||||||
embed.add_field(name="Duration", value=str(yi.duration), inline=True)
|
|
||||||
if yi.upload_date:
|
|
||||||
embed.add_field(name="Published on", value=yi.upload_date.strftime("%d %b %Y"), inline=True)
|
|
||||||
return embed
|
|
4
royalnet/serf/discord/discordbard/createrichembed.py
Normal file
4
royalnet/serf/discord/discordbard/createrichembed.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from discord import Embed, Colour
|
||||||
|
from discord.embeds import EmptyEmbed
|
||||||
|
from royalnet.bard import YtdlInfo
|
||||||
|
|
|
@ -25,8 +25,11 @@ class DBQueue(DiscordBard):
|
||||||
except IndexError:
|
except IndexError:
|
||||||
yield None
|
yield None
|
||||||
else:
|
else:
|
||||||
async with ytd.spawn_audiosource() as fas:
|
try:
|
||||||
yield fas
|
async with ytd.spawn_audiosource() as fas:
|
||||||
|
yield fas
|
||||||
|
finally:
|
||||||
|
await ytd.delete_asap()
|
||||||
|
|
||||||
async def add(self, ytd: YtdlDiscord):
|
async def add(self, ytd: YtdlDiscord):
|
||||||
self.list.append(ytd)
|
self.list.append(ytd)
|
||||||
|
@ -40,3 +43,4 @@ class DBQueue(DiscordBard):
|
||||||
async def cleanup(self) -> None:
|
async def cleanup(self) -> None:
|
||||||
for ytd in self.list:
|
for ytd in self.list:
|
||||||
await ytd.delete_asap()
|
await ytd.delete_asap()
|
||||||
|
await self.stop()
|
||||||
|
|
|
@ -54,8 +54,10 @@ class DiscordBard:
|
||||||
self.now_playing = fas
|
self.now_playing = fas
|
||||||
return fas
|
return fas
|
||||||
|
|
||||||
async def cut(self):
|
async def stop(self):
|
||||||
"""Immediatly end the playback of the current file"""
|
"""Stop the playback of the current song."""
|
||||||
|
if self.now_playing is not None:
|
||||||
|
self.now_playing.stop()
|
||||||
|
|
||||||
async def add(self, ytd: YtdlDiscord) -> None:
|
async def add(self, ytd: YtdlDiscord) -> None:
|
||||||
"""Add a new :class:`YtdlDiscord` to the :class:`DiscordBard`, if possible.
|
"""Add a new :class:`YtdlDiscord` to the :class:`DiscordBard`, if possible.
|
||||||
|
@ -93,7 +95,3 @@ class DiscordBard:
|
||||||
UnsupportedError: If :meth:`.peek` is unsupported."""
|
UnsupportedError: If :meth:`.peek` is unsupported."""
|
||||||
return len(await self.peek())
|
return len(await self.peek())
|
||||||
|
|
||||||
async def stop(self):
|
|
||||||
"""Stop the playback of the current song."""
|
|
||||||
if self.now_playing is not None:
|
|
||||||
self.now_playing.stop()
|
|
||||||
|
|
|
@ -5,23 +5,24 @@ import logging
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from royalnet.utils import asyncify, MultiLock
|
from royalnet.utils import asyncify, MultiLock
|
||||||
from royalnet.bard import YtdlInfo, YtdlFile
|
from royalnet.bard import YtdlInfo, YtdlFile
|
||||||
|
from .fileaudiosource import FileAudioSource
|
||||||
try:
|
|
||||||
from .fileaudiosource import FileAudioSource
|
|
||||||
except ImportError:
|
|
||||||
FileAudioSource = None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ffmpeg
|
import ffmpeg
|
||||||
except ImportError:
|
except ImportError:
|
||||||
ffmpeg = None
|
ffmpeg = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import discord
|
||||||
|
except ImportError:
|
||||||
|
discord = None
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class YtdlDiscord:
|
class YtdlDiscord:
|
||||||
"""A representation of a YtdlFile conversion to the :mod:`discord` PCM format."""
|
"""A representation of a YtdlFile conversion to the :mod:`discord` PCM format."""
|
||||||
|
|
||||||
def __init__(self, ytdl_file: YtdlFile):
|
def __init__(self, ytdl_file: YtdlFile):
|
||||||
self.ytdl_file: YtdlFile = ytdl_file
|
self.ytdl_file: YtdlFile = ytdl_file
|
||||||
self.pcm_filename: typing.Optional[str] = None
|
self.pcm_filename: typing.Optional[str] = None
|
||||||
|
@ -44,9 +45,9 @@ class YtdlDiscord:
|
||||||
log.debug(f"Converting to PCM: {self.ytdl_file.filename}")
|
log.debug(f"Converting to PCM: {self.ytdl_file.filename}")
|
||||||
await asyncify(
|
await asyncify(
|
||||||
ffmpeg.input(self.ytdl_file.filename)
|
ffmpeg.input(self.ytdl_file.filename)
|
||||||
.output(destination_filename, format="s16le", ac=2, ar="48000")
|
.output(destination_filename, format="s16le", ac=2, ar="48000")
|
||||||
.overwrite_output()
|
.overwrite_output()
|
||||||
.run
|
.run
|
||||||
)
|
)
|
||||||
self.pcm_filename = destination_filename
|
self.pcm_filename = destination_filename
|
||||||
|
|
||||||
|
@ -84,3 +85,29 @@ class YtdlDiscord:
|
||||||
with open(self.pcm_filename, "rb") as stream:
|
with open(self.pcm_filename, "rb") as stream:
|
||||||
fas = FileAudioSource(stream)
|
fas = FileAudioSource(stream)
|
||||||
yield fas
|
yield fas
|
||||||
|
|
||||||
|
def embed(self) -> "discord.Embed":
|
||||||
|
"""Return this info as a :py:class:`discord.Embed`."""
|
||||||
|
if discord is None:
|
||||||
|
raise ImportError("'discord' extra is not installed")
|
||||||
|
colors = {
|
||||||
|
"youtube": 0xCC0000,
|
||||||
|
"soundcloud": 0xFF5400,
|
||||||
|
"Clyp": 0x3DBEB3,
|
||||||
|
"Bandcamp": 0x1DA0C3,
|
||||||
|
"PeerTube": 0xF1680D,
|
||||||
|
}
|
||||||
|
embed = discord.Embed(title=self.info.title,
|
||||||
|
colour=discord.Colour(colors.get(self.info.extractor, 0x4F545C)),
|
||||||
|
url=self.info.webpage_url if (self.info.webpage_url and self.info.webpage_url.startswith("http")) else discord.embeds.EmptyEmbed)
|
||||||
|
if self.info.thumbnail:
|
||||||
|
embed.set_thumbnail(url=self.info.thumbnail)
|
||||||
|
if self.info.uploader:
|
||||||
|
embed.set_author(name=self.info.uploader,
|
||||||
|
url=self.info.uploader_url if self.info.uploader_url is not None else discord.embeds.EmptyEmbed)
|
||||||
|
# embed.set_footer(text="Source: youtube-dl", icon_url="https://i.imgur.com/TSvSRYn.png")
|
||||||
|
if self.info.duration:
|
||||||
|
embed.add_field(name="Duration", value=str(self.info.duration), inline=True)
|
||||||
|
if self.info.upload_date:
|
||||||
|
embed.add_field(name="Published on", value=self.info.upload_date.strftime("%d %b %Y"), inline=True)
|
||||||
|
return embed
|
||||||
|
|
|
@ -263,6 +263,8 @@ class DiscordSerf(Serf):
|
||||||
|
|
||||||
if bard.now_playing is None:
|
if bard.now_playing is None:
|
||||||
fas = await bard.next()
|
fas = await bard.next()
|
||||||
|
if fas is None:
|
||||||
|
return
|
||||||
# FIXME: possible race condition here, pls check
|
# FIXME: possible race condition here, pls check
|
||||||
bard = self.bards.get(guild)
|
bard = self.bards.get(guild)
|
||||||
if bard.voice_client is not None and bard.voice_client.is_connected():
|
if bard.voice_client is not None and bard.voice_client.is_connected():
|
||||||
|
|
|
@ -55,4 +55,4 @@ class MultiLock:
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<MultiLock {self._counter} " \
|
return f"<MultiLock {self._counter} " \
|
||||||
f"{'N' if self._normal_event.is_set() else '_'}{'E' if self._exclusive_event.is_set() else '_'}>"
|
f"{'_' if self._normal_event.is_set() else 'N'}{'_' if self._exclusive_event.is_set() else 'E'}>"
|
||||||
|
|
Loading…
Reference in a new issue