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