mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-27 13:34:28 +00:00
With generic extractor, infer track name from id3 tags
This commit is contained in:
parent
b028fbe6cc
commit
0ab0c2cd76
5 changed files with 83 additions and 6 deletions
55
poetry.lock
generated
55
poetry.lock
generated
|
@ -158,6 +158,17 @@ pytz = "*"
|
||||||
regex = "*"
|
regex = "*"
|
||||||
tzlocal = "*"
|
tzlocal = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "A library to handle automated deprecations"
|
||||||
|
name = "deprecation"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
version = "2.0.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
packaging = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "A python wrapper for the Discord API"
|
description = "A python wrapper for the Discord API"
|
||||||
|
@ -182,6 +193,23 @@ optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
version = "0.16"
|
version = "0.16"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "Python audio data toolkit (ID3 and MP3)"
|
||||||
|
name = "eyed3"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
version = "0.9"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
deprecation = "*"
|
||||||
|
filetype = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
art-plugin = ["pylast", "requests", "pillow"]
|
||||||
|
display-plugin = ["grako"]
|
||||||
|
yaml-plugin = ["ruamel.yaml"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Python bindings for FFmpeg - with complex filtering support"
|
description = "Python bindings for FFmpeg - with complex filtering support"
|
||||||
|
@ -196,6 +224,14 @@ future = "*"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["future (0.17.1)", "numpy (1.16.4)", "pytest-mock (1.10.4)", "pytest (4.6.1)", "Sphinx (2.1.0)", "tox (3.12.1)"]
|
dev = ["future (0.17.1)", "numpy (1.16.4)", "pytest-mock (1.10.4)", "pytest (4.6.1)", "Sphinx (2.1.0)", "tox (3.12.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "Infer file type and MIME type of any file/buffer. No external dependencies."
|
||||||
|
name = "filetype"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
version = "1.0.5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Clean single-source support for Python 3 and 2"
|
description = "Clean single-source support for Python 3 and 2"
|
||||||
|
@ -377,7 +413,7 @@ python-versions = ">=3.5"
|
||||||
version = "4.7.4"
|
version = "4.7.4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "main"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -464,7 +500,7 @@ docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
||||||
tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"]
|
tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "main"
|
||||||
description = "Python parsing module"
|
description = "Python parsing module"
|
||||||
name = "pyparsing"
|
name = "pyparsing"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -889,7 +925,7 @@ sentry = ["sentry_sdk"]
|
||||||
telegram = ["python_telegram_bot"]
|
telegram = ["python_telegram_bot"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
content-hash = "6f14bbcfb695def8593da8e916e54a02a09d5a70852aa8ebd360aa03e33d3cd4"
|
content-hash = "e46d65bd8228040eb92de09eb31a8a0987a1afbc6f39e62656f9a306df049ba4"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
@ -1009,6 +1045,10 @@ dateparser = [
|
||||||
{file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"},
|
{file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"},
|
||||||
{file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"},
|
{file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"},
|
||||||
]
|
]
|
||||||
|
deprecation = [
|
||||||
|
{file = "deprecation-2.0.7-py2.py3-none-any.whl", hash = "sha256:dc9b4f252b7aca8165ce2764a71da92a653b5ffbf7a389461d7a640f6536ecb2"},
|
||||||
|
{file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"},
|
||||||
|
]
|
||||||
"discord.py" = [
|
"discord.py" = [
|
||||||
{file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"},
|
{file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"},
|
||||||
]
|
]
|
||||||
|
@ -1016,10 +1056,19 @@ docutils = [
|
||||||
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
|
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
|
||||||
{file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"},
|
{file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"},
|
||||||
]
|
]
|
||||||
|
eyed3 = [
|
||||||
|
{file = "eyeD3-0.9-py2.py3-none-any.whl", hash = "sha256:6015669333df2115809102ccf1b29585115b5c233cf4530d9f995ad562634819"},
|
||||||
|
{file = "eyeD3-0.9-py3.8.egg", hash = "sha256:8e3a7a2ce2932260f77c6234d624737807cdb4404f5bac3c5348c1f9da3d7250"},
|
||||||
|
{file = "eyeD3-0.9.tar.gz", hash = "sha256:8874762fd4fd93fa64676185ccaa77ea8b3396aea65ba86bca7325f1136f9c8a"},
|
||||||
|
]
|
||||||
ffmpeg-python = [
|
ffmpeg-python = [
|
||||||
{file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"},
|
{file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"},
|
||||||
{file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"},
|
{file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"},
|
||||||
]
|
]
|
||||||
|
filetype = [
|
||||||
|
{file = "filetype-1.0.5-py2.py3-none-any.whl", hash = "sha256:4967124d982a71700d94a08c49c4926423500e79382a92070f5ab248d44fe461"},
|
||||||
|
{file = "filetype-1.0.5.tar.gz", hash = "sha256:17a3b885f19034da29640b083d767e0f13c2dcb5dcc267945c8b6e5a5a9013c7"},
|
||||||
|
]
|
||||||
future = [
|
future = [
|
||||||
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
||||||
]
|
]
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
# bard
|
# bard
|
||||||
ffmpeg_python = {version="~0.2.0", optional=true}
|
ffmpeg_python = {version="~0.2.0", optional=true}
|
||||||
youtube_dl = {version="*", optional=true}
|
youtube_dl = {version="*", optional=true}
|
||||||
|
eyed3 = {version="^0.9", optional=true}
|
||||||
|
|
||||||
# alchemy
|
# alchemy
|
||||||
sqlalchemy = {version="^1.3.10", optional=true}
|
sqlalchemy = {version="^1.3.10", optional=true}
|
||||||
|
@ -72,7 +73,7 @@
|
||||||
matrix = ["matrix-nio"]
|
matrix = ["matrix-nio"]
|
||||||
alchemy_easy = ["sqlalchemy", "psycopg2_binary"]
|
alchemy_easy = ["sqlalchemy", "psycopg2_binary"]
|
||||||
alchemy_hard = ["sqlalchemy", "psycopg2"]
|
alchemy_hard = ["sqlalchemy", "psycopg2"]
|
||||||
bard = ["ffmpeg_python", "youtube_dl"]
|
bard = ["ffmpeg_python", "youtube_dl", "eyed3"]
|
||||||
constellation = ["starlette", "uvicorn", "python-multipart"]
|
constellation = ["starlette", "uvicorn", "python-multipart"]
|
||||||
sentry = ["sentry_sdk"]
|
sentry = ["sentry_sdk"]
|
||||||
herald = ["websockets"]
|
herald = ["websockets"]
|
||||||
|
|
|
@ -105,6 +105,7 @@ class YtdlDiscord:
|
||||||
"Clyp": 0x3DBEB3,
|
"Clyp": 0x3DBEB3,
|
||||||
"Bandcamp": 0x1DA0C3,
|
"Bandcamp": 0x1DA0C3,
|
||||||
"PeerTube": 0xF1680D,
|
"PeerTube": 0xF1680D,
|
||||||
|
"generic": 0x4F545C,
|
||||||
}
|
}
|
||||||
embed = discord.Embed(title=self.info.title,
|
embed = discord.Embed(title=self.info.title,
|
||||||
colour=discord.Colour(colors.get(self.info.extractor, 0x4F545C)),
|
colour=discord.Colour(colors.get(self.info.extractor, 0x4F545C)),
|
||||||
|
@ -114,9 +115,14 @@ class YtdlDiscord:
|
||||||
if self.info.uploader:
|
if self.info.uploader:
|
||||||
embed.set_author(name=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)
|
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")
|
elif self.info.artist:
|
||||||
|
embed.set_author(name=self.info.artist,
|
||||||
|
url=discord.embeds.EmptyEmbed)
|
||||||
|
if self.info.album:
|
||||||
|
embed.add_field(name="Album", value=self.info.album, inline=True)
|
||||||
if self.info.duration:
|
if self.info.duration:
|
||||||
embed.add_field(name="Duration", value=str(self.info.duration), inline=True)
|
embed.add_field(name="Duration", value=str(self.info.duration), inline=True)
|
||||||
if self.info.upload_date:
|
if self.info.extractor != "generic" and self.info.upload_date:
|
||||||
embed.add_field(name="Published on", value=self.info.upload_date.strftime("%d %b %Y"), inline=True)
|
embed.add_field(name="Published on", value=self.info.upload_date.strftime("%d %b %Y"), inline=True)
|
||||||
|
# embed.set_footer(text="Source: youtube-dl", icon_url="https://i.imgur.com/TSvSRYn.png")
|
||||||
return embed
|
return embed
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import eyed3
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from typing import *
|
from typing import *
|
||||||
from royalnet.utils import *
|
from royalnet.utils import *
|
||||||
|
@ -96,6 +97,24 @@ class YtdlFile:
|
||||||
async with self.lock.exclusive():
|
async with self.lock.exclusive():
|
||||||
log.debug(f"Downloading with youtube-dl: {self}")
|
log.debug(f"Downloading with youtube-dl: {self}")
|
||||||
await asyncify(download, loop=self._loop)
|
await asyncify(download, loop=self._loop)
|
||||||
|
if self.info.extractor == "generic":
|
||||||
|
log.debug(f"Generic extractor detected, updating info from the downloaded file: {self}")
|
||||||
|
self.set_ytdlinfo_from_id3_tags()
|
||||||
|
|
||||||
|
def set_ytdlinfo_from_id3_tags(self):
|
||||||
|
tag_file = eyed3.load(self.filename)
|
||||||
|
if not tag_file:
|
||||||
|
log.debug(f"No ID3 tags found: {self}")
|
||||||
|
tag: eyed3.core.Tag = tag_file.tag
|
||||||
|
if tag.title:
|
||||||
|
log.debug(f"Found title: {self}")
|
||||||
|
self.info.title = tag.title
|
||||||
|
if tag.album:
|
||||||
|
log.debug(f"Found album: {self}")
|
||||||
|
self.info.album = tag.album
|
||||||
|
if tag.artist:
|
||||||
|
log.debug(f"Found artist: {self}")
|
||||||
|
self.info.artist = tag.artist
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def aopen(self):
|
async def aopen(self):
|
||||||
|
|
|
@ -86,6 +86,8 @@ class YtdlInfo:
|
||||||
self.acodec: Optional[str] = info.get("acodec")
|
self.acodec: Optional[str] = info.get("acodec")
|
||||||
self.abr: Optional[int] = info.get("abr")
|
self.abr: Optional[int] = info.get("abr")
|
||||||
self.ext: Optional[str] = info.get("ext")
|
self.ext: Optional[str] = info.get("ext")
|
||||||
|
# Additional custom information
|
||||||
|
self.album: Optional[str] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def from_url(cls, url, loop: Optional[AbstractEventLoop] = None, **ytdl_args) -> List["YtdlInfo"]:
|
async def from_url(cls, url, loop: Optional[AbstractEventLoop] = None, **ytdl_args) -> List["YtdlInfo"]:
|
||||||
|
|
Loading…
Reference in a new issue