create upload bot
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
name: Deploy Music Bot
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: backup-runner # <-- Используем ваш label для доступа к сокету Docker
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build and Deploy Bot
|
||||||
|
run: |
|
||||||
|
# Запускаем сборку и деплой прямо через сокет хоста
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
- name: Clean up old images
|
||||||
|
run: docker image prune -f
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.14" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.14" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.14" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/auto_dj.iml" filepath="$PROJECT_DIR$/.idea/auto_dj.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# Берем легкий образ питона
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Устанавливаем ffmpeg (он критически нужен yt-dlp для извлечения mp3)
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y ffmpeg && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Создаем рабочую папку
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Копируем зависимости и устанавливаем их
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Копируем весь остальной код
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Запускаем бота
|
||||||
|
CMD ["python", "bot.py"]
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
"python@3.11",
|
||||||
|
"ffmpeg@latest"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"VENV_DIR": ".venv"
|
||||||
|
},
|
||||||
|
"shell": {
|
||||||
|
"init_hook": [
|
||||||
|
"python -m venv $VENV_DIR",
|
||||||
|
"source $VENV_DIR/bin/activate",
|
||||||
|
"pip install -r requirements.txt"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"start": "python bot.py"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
services:
|
||||||
|
music-bot:
|
||||||
|
build: .
|
||||||
|
container_name: navidrome_bot
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- TG_BOT_TOKEN=8849605262:AAGMJWr-02uaFI-cD4UBxg1pSB0swDH_dUc
|
||||||
|
- ADMIN_ID=812709121
|
||||||
|
- MUSIC_DIR=/music
|
||||||
|
volumes:
|
||||||
|
# Слева — путь к музыке на сервере, справа — внутри контейнера бота
|
||||||
|
- /home/redjinald/navidrome/music:/music
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import os
|
||||||
|
import asyncio
|
||||||
|
from aiogram import Bot, Dispatcher, types, F
|
||||||
|
from aiogram.filters import Command
|
||||||
|
import yt_dlp
|
||||||
|
|
||||||
|
TOKEN = os.getenv("TG_BOT_TOKEN")
|
||||||
|
MUSIC_DIR = os.getenv("MUSIC_DIR", "./music")
|
||||||
|
# Читаем ваш ID из переменных среды (по умолчанию 0)
|
||||||
|
ADMIN_ID = int(os.getenv("ADMIN_ID", 0))
|
||||||
|
|
||||||
|
bot = Bot(token=TOKEN)
|
||||||
|
dp = Dispatcher()
|
||||||
|
|
||||||
|
def download_youtube(url: str):
|
||||||
|
ydl_opts = {
|
||||||
|
'format': 'bestaudio/best',
|
||||||
|
'postprocessors': [{
|
||||||
|
'key': 'FFmpegExtractAudio',
|
||||||
|
'preferredcodec': 'mp3',
|
||||||
|
'preferredquality': '192',
|
||||||
|
}],
|
||||||
|
'outtmpl': f'{MUSIC_DIR}/Youtube/%(uploader)s/%(title)s.%(ext)s',
|
||||||
|
'noplaylist': False,
|
||||||
|
'quiet': False
|
||||||
|
}
|
||||||
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
|
ydl.download([url])
|
||||||
|
|
||||||
|
# Создаем удобный фильтр: "сообщение от админа"
|
||||||
|
is_admin = F.from_user.id == ADMIN_ID
|
||||||
|
|
||||||
|
# --- ОБРАБОТЧИКИ ТОЛЬКО ДЛЯ ВАС (работают, если is_admin == True) ---
|
||||||
|
|
||||||
|
@dp.message(is_admin, Command("start"))
|
||||||
|
async def start_cmd(message: types.Message):
|
||||||
|
await message.reply("Привет, хозяин! Скинь ссылку на YouTube или аудиофайл, и я закину его в Navidrome.")
|
||||||
|
|
||||||
|
@dp.message(is_admin, F.text.regexp(r'https?://(?:www\.)?youtu'))
|
||||||
|
async def handle_youtube(message: types.Message):
|
||||||
|
msg = await message.reply("⏳ Начинаю скачивание...")
|
||||||
|
try:
|
||||||
|
await asyncio.to_thread(download_youtube, message.text)
|
||||||
|
await msg.edit_text("✅ Успешно скачано и добавлено в Navidrome!")
|
||||||
|
except Exception as e:
|
||||||
|
await msg.edit_text(f"❌ Ошибка:\n{str(e)[:500]}")
|
||||||
|
|
||||||
|
@dp.message(is_admin, F.audio)
|
||||||
|
async def handle_audio(message: types.Message):
|
||||||
|
msg = await message.reply("📥 Сохраняю трек...")
|
||||||
|
try:
|
||||||
|
file_name = message.audio.file_name or f"track_{message.message_id}.mp3"
|
||||||
|
destination = os.path.join(MUSIC_DIR, "Telegram", file_name)
|
||||||
|
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
||||||
|
await bot.download(message.audio, destination=destination)
|
||||||
|
await msg.edit_text("✅ Трек добавлен в Navidrome!")
|
||||||
|
except Exception as e:
|
||||||
|
await msg.edit_text(f"❌ Ошибка:\n{str(e)[:500]}")
|
||||||
|
|
||||||
|
# --- ОБРАБОТЧИК ДЛЯ ЧУЖАКОВ ---
|
||||||
|
# Сработает, если ни один из верхних обработчиков не подошел (например, другой ID)
|
||||||
|
@dp.message()
|
||||||
|
async def reject_stranger(message: types.Message):
|
||||||
|
await message.reply(f"⛔ Извините, этот бот приватный.\n\nВаш Telegram ID: <code>{message.from_user.id}</code>", parse_mode="HTML")
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
print("Бот запущен...")
|
||||||
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
aiogram==3.4.1
|
||||||
|
yt-dlp==2024.3.10
|
||||||
|
mutagen
|
||||||
Reference in New Issue
Block a user