Added and updated repositories 2026-04-12 13:56:57

This commit is contained in:
github-actions[bot]
2026-04-12 13:56:57 +00:00
parent 7555ea280e
commit 17ae450f8f
19 changed files with 6309 additions and 953 deletions

View File

@@ -1,11 +1,9 @@
__version__ = (3, 1, 1)
__version__ = (3, 2, 0)
# meta banner: https://raw.githubusercontent.com/kamekuro/hikka-mods/main/banners/yamusic.png
# packurl: https://raw.githubusercontent.com/coddrago/assets/refs/heads/main/modules/yamusic.yml
# meta banner: https://raw.githubusercontent.com/coddrago/modules/refs/heads/main/banner.png
# packurl: https://raw.githubusercontent.com/coddrago/modules/refs/heads/dev/translations/yamusic.yml
# meta developer: @codrago_m
# old meta dev: @kamekuro xuesos
# scope: heroku_only
# scope: heroku_min 1.7.2
# scope: heroku_min 2.0.0
# requires: aiohttp asyncio pillow>=10.0.0 git+https://github.com/MarshalX/yandex-music-api
import aiohttp
@@ -17,6 +15,7 @@ import random
import string
import typing
import time
import uuid
from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont
import telethon
@@ -171,7 +170,6 @@ class Banners:
current_y += 80
bar_width = 800
bar_height = 6
font_time = get_font(40)
bar_start_x = center_x - (bar_width // 2)
@@ -180,11 +178,12 @@ class Banners:
total_mins = self.duration // 1000 // 60
total_secs = (self.duration // 1000) % 60
total_time_str = f"{total_mins}:{total_secs:02d}"
total_time_str = f"{total_mins:02d}:{total_secs:02d}"
cur_mins = self.progress // 1000 // 60
cur_secs = (self.progress // 1000) % 60
cur_time_str = f"{cur_mins}:{cur_secs:02d}"
cur_time_str = f"{cur_mins:02d}:{cur_secs:02d}"
draw_text_shadow(
cur_time_str, (bar_start_x - 30, bar_y), font_time, anchor="rm"
@@ -193,34 +192,44 @@ class Banners:
total_time_str, (bar_end_x + 30, bar_y), font_time, anchor="lm"
)
draw.line(
[(bar_start_x, bar_y), (bar_end_x, bar_y)],
fill=(255, 255, 255, 80),
width=bar_height,
)
old_state = random.getstate()
random.seed(self.title + str(self.duration))
num_bars = 65
bar_spacing = bar_width / num_bars
bar_w = max(4, int(bar_spacing * 0.5))
max_h = 50
min_h = 6
if self.duration > 0:
progress_ratio = self.progress / self.duration
else:
progress_ratio = 0
progress_px = int(bar_width * progress_ratio)
if progress_px > bar_width:
progress_px = bar_width
active_bars = int(num_bars * progress_ratio)
draw.line(
[(bar_start_x, bar_y), (bar_start_x + progress_px, bar_y)],
fill="white",
width=bar_height + 5,
)
draw.ellipse(
(
bar_start_x + progress_px - 10,
bar_y - 10,
bar_start_x + progress_px + 10,
bar_y + 10,
),
fill="white",
)
for i in range(num_bars):
base_h = random.randint(min_h, max_h)
edge_factor = 1.0 - abs((i - num_bars / 2) / (num_bars / 2))
h = int(base_h * 0.4 + max_h * edge_factor * 0.6)
h = max(min_h, h)
x_center = bar_start_x + i * bar_spacing
left = x_center - (bar_w / 2)
right = x_center + (bar_w / 2)
top = bar_y - (h / 2)
bottom = bar_y + (h / 2)
color = (255, 255, 255, 255) if i < active_bars else (80, 80, 80, 100)
draw.rounded_rectangle(
(left, top, right, bottom),
radius=int(bar_w / 2),
fill=color
)
random.setstate(old_state)
current_y += 80
@@ -312,13 +321,7 @@ class YaMusicMod(loader.Module):
"""The module for Yandex.Music streaming service"""
strings = {
"name": "YaMusic",
"iguide": '📜 <b><a href="https://yandex-music.rtfd.io/en/main/token.html">Guide for obtaining access token for Yandex.Music</a></b>',
}
strings_ru = {
"_cls_doc": "Модуль для стримингового сервиса Яндекс.Музыка",
"iguide": '📜 <b><a href="https://yandex-music.rtfd.io/en/main/token.html">Гайд по получению токена Яндекс.Музыки</a></b>',
"name": "YaMusic"
}
def __init__(self):
@@ -373,11 +376,10 @@ class YaMusicMod(loader.Module):
self._client: telethon.TelegramClient = client
self._db = db
#utils.register_placeholder(
#"now_play", self._now_play_placeholder, "placeholder for nowplay music"
# Heroku 2.0.0 feature
#)
#utils.register_placeholder("duration", self._duration_placeholder, "progress bar")
utils.register_placeholder(
"now_play", self._now_play_placeholder, "placeholder for nowplay music"
)
utils.register_placeholder("duration", self._duration_placeholder, "progress bar")
if not self.get("guide_sent", False):
await self.inline.bot.send_message(self._tg_id, self.strings("iguide"))
@@ -423,7 +425,7 @@ class YaMusicMod(loader.Module):
me = await self._client.get_me()
self._premium = me.premium if hasattr(me, "premium") else False
@loader.loop(15)
@loader.loop(30)
async def autobio(self):
if not self.config["token"]:
self.autobio.stop()
@@ -543,7 +545,7 @@ class YaMusicMod(loader.Module):
now = await self.__get_now_playing()
if not now or now.get("paused"):
return "<code>Not Playing</code>"
duration = now.get("duration_ms", 0)
progress = now.get("progress_ms", 0)
@@ -632,13 +634,14 @@ class YaMusicMod(loader.Module):
)
async def ynowcmd(self, message: telethon.types.Message):
"""👉 Get the banner of the track playing right now"""
await utils.answer(message, self.strings("uploading_banner"))
ym_client = await self._get_ym_client()
if not ym_client:
return await utils.answer(
message, self.strings("errors")["no_token_or_invalid"]
)
await utils.answer(message, self.strings("uploading_banner"))
now = await self.__get_now_playing()
if not now or now.get("paused"):
@@ -694,10 +697,6 @@ class YaMusicMod(loader.Module):
.format(playlist_name),
link=f"<a href=\"https://music.yandex.ru/track/{now['playable_id']}\">Яндекс.Музыка</a>",
)
try:
await utils.answer(message, out + self.strings("uploading_banner"))
except Exception:
pass
album_obj = track_object.albums[0] if track_object.albums else None
@@ -823,10 +822,6 @@ class YaMusicMod(loader.Module):
.format(playlist_name),
link=f"<a href=\"https://music.yandex.ru/track/{now['playable_id']}\">Яндекс.Музыка</a>",
)
try:
await utils.answer(message, out + self.strings("downloading_track"))
except Exception:
pass
await utils.answer(
message=message,
@@ -954,6 +949,7 @@ class YaMusicMod(loader.Module):
),
)
async def __download_track(
self,
client: yandex_music.ClientAsync,
@@ -977,7 +973,7 @@ class YaMusicMod(loader.Module):
await asyncio.sleep(1)
continue
raise e
async def __get_ynison(self):
async def create_ws(token, ws_proto):
async with aiohttp.ClientSession() as session:

View File

@@ -0,0 +1,116 @@
en:
iguide: "<emoji document_id=5956561916573782596>📜</emoji> <b><a href=\"https://yandex-music.rtfd.io/en/main/token.html\">Guide for obtaining access token for Yandex.Music</a></b>"
search: "<emoji document_id=5474304919651491706>🎧</emoji> <b>{performer} — {title}</b>\n<emoji document_id=5242574232688298747>🎵</emoji> <b><a href=\"https://music.yandex.ru/track/{track_id}\">Yandex.Music</a> | <a href=\"https://song.link/ya/{track_id}\">song.link</a></b>"
downloading_track: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>Downloading audio…</i>"
uploading_banner: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>Uploading banner…</i>"
lyrics: "<emoji document_id=5956561916573782596>📜</emoji> <b>Lyrics of the <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> track:</b>\n<blockquote expandable>{text}</blockquote>\n\n<emoji document_id=5776287149724798198>©️</emoji> <b>Writers:</b> {writers}"
no_lyrics: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Track <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> has no lyrics!</b>"
errors:
no_query: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Specify the search query first!</b>"
no_token_or_invalid: "<emoji document_id=5872829476143894491>🚫</emoji> <b>You specified an invalid access token or didn't specified it at all!</b>"
not_found: "<emoji document_id=5872829476143894491>🚫</emoji> <b>No results found.</b>"
no_playing: "<emoji document_id=5872829476143894491>🚫</emoji> <b>You don't listening to anything right now.</b>"
autobio:
enabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Autobio was enabled.</b>"
disabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Autobio was disabled.</b>"
likes:
liked: "<emoji document_id=5899833370052923106>❤️</emoji> <b>Track <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> was liked.</b>"
unliked: "<emoji document_id=5992453811510186287>🖤</emoji> <b>Track <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> was unliked.</b>"
disliked: "<emoji document_id=5952055319059239589>💔</emoji> <b>Track <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> was disliked.</b>"
_entity_types:
VARIOUS: "Your queue"
RADIO: "«My Vibe»"
PLAYLIST: "Playlist «{}»"
ALBUM: "«{}»"
ARTIST: "Popular tracks by {}"
_cfg:
token: "The access token for Yandex.Music."
now_playing_text: "The caption for .ynow and .ynowt commands. May contain {performer}, {title}, {device}, {volume}, {playing_from}, {link}, {track_id}, {album_id} keywords."
autobio_text: "The text for automatically changing «Bio». May contains {performer} and {title}."
no_playing_bio_text: "The text for changing «Bio» when there is no playing tracks."
banner_version: "Banner version"
repeat_on: "🔁 <b>Repeat enabled</b>"
repeat_off: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>Repeat disabled</b>"
next_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>Next track</b>"
prev_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>Previous track</b>"
volume_set: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>Volume set to {vol}%</b>"
volume_invalid: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>Volume must be between 0 and 100</b>"
ynison_error: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>Failed to send command to Yandex.Music (Ynison)</b>"
ru:
iguide: "<emoji document_id=5956561916573782596>📜</emoji> <b><a href=\"https://yandex-music.rtfd.io/en/main/token.html\">Гайд по получению токена Яндекс.Музыки</a></b>"
search: "<emoji document_id=5474304919651491706>🎧</emoji> <b>{performer} — {title}</b>\n<emoji document_id=5242574232688298747>🎵</emoji> <b><a href=\"https://music.yandex.ru/track/{track_id}\">Яндекс.Музыка</a> | <a href=\"https://song.link/ya/{track_id}\">song.link</a></b>"
downloading_track: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>Загрузка трека…</i>"
uploading_banner: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>Загрузка баннера…</i>"
lyrics: "<emoji document_id=5956561916573782596>📜</emoji> <b>Текст трека <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a>:</b>\n<blockquote expandable>{text}</blockquote>\n\n<emoji document_id=5776287149724798198>©️</emoji> <b>Авторы:</b> {writers}"
no_lyrics: "<emoji document_id=5872829476143894491>🚫</emoji> <b>У трека <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> нет текста!</b>"
errors:
no_query: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Укажите поисковый запрос!</b>"
no_token_or_invalid: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Вы указали невалидный токен или не указали его вообще!</b>"
not_found: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Результаты не найдены.</b>"
no_playing: "<emoji document_id=5872829476143894491>🚫</emoji> <b>Вы ничего не слушаете сейчас.</b>"
autobio:
enabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Автобио теперь включено.</b>"
disabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Автобио теперь выключено.</b>"
likes:
liked: "<emoji document_id=5899833370052923106>❤️</emoji> <b>Трек <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> был лайкнут.</b>"
unliked: "<emoji document_id=5992453811510186287>🖤</emoji> <b>С трека <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> был снят лайк.</b>"
disliked: "<emoji document_id=5952055319059239589>💔</emoji> <b>Трек <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> был дизлайкнут.</b>"
_entity_types:
VARIOUS: "Ваша очередь"
RADIO: "«Моя волна»"
PLAYLIST: "Плейлист «{}»"
ALBUM: "«{}»"
ARTIST: "Популярные треки {}"
_cfg:
token: "Токен для Яндекс.Музыки."
now_playing_text: "Текст, использующийся в подписи к файлу в командах .ynow и .ynowt. Может содержать {performer}, {title}, {device}, {volume}, {playing_from}, {link}, {track_id} и {album_id}"
autobio_text: "Текст, использующийся при автоматическом изменении «О себе». Может содержать {performer} и {title}."
no_playing_bio_text: "Текст, использующийся при изменении «О себе», когда ничего не играет."
banner_version: "Версия баннера"
repeat_on: "🔁 <b>Повтор включен (Один трек)</b>"
repeat_off: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>Повтор выключен</b>"
next_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>Следующий трек</b>"
prev_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>Предыдущий трек</b>"
volume_set: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>Громкость установлена на {vol}%</b>"
volume_invalid: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>Громкость должна быть от 0 до 100</b>"
ynison_error: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>Не удалось отправить команду в Яндекс.Музыку (Ynison)</b>"
jp:
iguide: "<emoji document_id=5956561916573782596>📜</emoji> <b><a href=\"https://yandex-music.rtfd.io/en/main/token.html\">Yandex.Music アクセストークン取得ガイド</a></b>"
search: "<emoji document_id=5474304919651491706>🎧</emoji> <b>{performer} — {title}</b>\n<emoji document_id=5242574232688298747>🎵</emoji> <b><a href=\"https://music.yandex.ru/track/{track_id}\">Yandex.Music</a> | <a href=\"https://song.link/ya/{track_id}\">song.link</a></b>"
downloading_track: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>オーディオをダウンロード中…</i>"
uploading_banner: "\n\n<emoji document_id=5841359499146825803>🕔</emoji> <i>バナーをアップロード中…</i>"
lyrics: "<emoji document_id=5956561916573782596>📜</emoji> <b>トラック <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> の歌詞:</b>\n<blockquote expandable>{text}</blockquote>\n\n<emoji document_id=5776287149724798198>©️</emoji> <b>作詞・作曲:</b> {writers}"
no_lyrics: "<emoji document_id=5872829476143894491>🚫</emoji> <b>トラック <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> には歌詞がありません!</b>"
errors:
no_query: "<emoji document_id=5872829476143894491>🚫</emoji> <b>最初に検索クエリを指定してください!</b>"
no_token_or_invalid: "<emoji document_id=5872829476143894491>🚫</emoji> <b>無効なアクセストークンを指定したか、指定されていません!</b>"
not_found: "<emoji document_id=5872829476143894491>🚫</emoji> <b>結果が見つかりません。</b>"
no_playing: "<emoji document_id=5872829476143894491>🚫</emoji> <b>現在何も再生していません。</b>"
autobio:
enabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Autobio自動プロフィールが有効になりました。</b>"
disabled: "<emoji document_id=5242574232688298747>🎧</emoji> <b>Autobioが無効になりました。</b>"
likes:
liked: "<emoji document_id=5899833370052923106>❤️</emoji> <b>トラック <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> に「いいね」しました。</b>"
unliked: "<emoji document_id=5992453811510186287>🖤</emoji> <b>トラック <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> の「いいね」を取り消しました。</b>"
disliked: "<emoji document_id=5952055319059239589>💔</emoji> <b>トラック <a href=\"https://music.yandex.ru/track/{track_id}\">{track}</a> に「低評価」しました。</b>"
_entity_types:
VARIOUS: "あなたのキュー"
RADIO: "«My Vibe»"
PLAYLIST: "プレイリスト «{}»"
ALBUM: "«{}»"
ARTIST: "{} の人気トラック"
_cfg:
token: "Yandex.Musicのアクセストークン。"
now_playing_text: ".ynow および .ynowt コマンド用のキャプション。{performer}, {title}, {device}, {volume}, {playing_from}, {link}, {track_id}, {album_id} のキーワードを含めることができます。"
autobio_text: "«Bio»自己紹介を自動変更するためのテキスト。{performer} と {title} を含めることができます。"
no_playing_bio_text: "何も再生されていない時に «Bio» を変更するためのテキスト。"
banner_version: "バナーのバージョン"
repeat_on: "🔁 <b>リピート有効</b>"
repeat_off: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>リピート無効</b>"
next_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>次のトラック</b>"
prev_track: "<tg-emoji emoji-id=5873204392429096339>⏭</tg-emoji> <b>前のトラック</b>"
volume_set: "<tg-emoji emoji-id=5873146865637133757>➡️</tg-emoji> <b>音量を {vol}% に設定しました</b>"
volume_invalid: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>音量は0から100の間で指定してください</b>"
ynison_error: "<tg-emoji emoji-id=5465665476971471368>❌</tg-emoji> <b>Yandex.Music (Ynison) へのコマンド送信に失敗しました</b>"