支持同步收藏夹到频道

This commit is contained in:
xtaodada 2023-08-18 21:28:16 +08:00
parent a93093ea80
commit 6a23509ae3
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
20 changed files with 349 additions and 43 deletions

View File

@ -2,9 +2,6 @@
api_id = ID_HERE api_id = ID_HERE
api_hash = HASH_HERE api_hash = HASH_HERE
[plugins]
root = modules
[proxy] [proxy]
enabled = False enabled = False
hostname = 127.0.0.1 hostname = 127.0.0.1
@ -19,8 +16,12 @@ lofter_channel = 0
lofter_channel_username = username lofter_channel_username = username
splash_channel = 0 splash_channel = 0
splash_channel_username = username splash_channel_username = username
bilifav_id = 0
bilifav_channel = 0
bilifav_channel_username = username
[api] [api]
amap_key = ABCD amap_key = ABCD
bili_cookie = ABCD bili_cookie = ABCD
bili_auth_user = 777000,111000 bili_auth_user = 777000,111000
bili_auth_chat = 777000,111000

View File

@ -217,7 +217,9 @@ async def take_screenshot(info: Dict) -> Optional[BytesIO]:
return None return None
async def audio_download(a: Audio, m: Message): async def audio_download(
a: Audio, m: Message, push_id: int = None
) -> Optional[Message]:
try: try:
info = await a.get_info() info = await a.get_info()
download_url_data = await a.get_download_url() download_url_data = await a.get_download_url()
@ -243,12 +245,12 @@ async def audio_download(a: Audio, m: Message):
text = f"<b>{info['title']}</b>\n\n简介过长,无法显示\n\nhttps://www.bilibili.com/audio/au{a.get_auid()}" text = f"<b>{info['title']}</b>\n\n简介过长,无法显示\n\nhttps://www.bilibili.com/audio/au{a.get_auid()}"
else: else:
text = f"<b>{info['title']}</b>\n\nhttps://www.bilibili.com/audio/au{a.get_auid()}" text = f"<b>{info['title']}</b>\n\nhttps://www.bilibili.com/audio/au{a.get_auid()}"
await bot.send_audio( msg = await bot.send_audio(
chat_id=m.chat.id, chat_id=push_id or m.chat.id,
audio=media, audio=media,
caption=text, caption=text,
parse_mode=ParseMode.HTML, parse_mode=ParseMode.HTML,
reply_to_message_id=m.reply_to_message_id, reply_to_message_id=m.reply_to_message_id if not push_id else None,
thumb=thumb, thumb=thumb,
title=info.get("title"), title=info.get("title"),
duration=info.get("duration"), duration=info.get("duration"),
@ -256,12 +258,17 @@ async def audio_download(a: Audio, m: Message):
) )
except BilibiliDownloaderError as e: except BilibiliDownloaderError as e:
await fail_edit(m, e.MSG) await fail_edit(m, e.MSG)
return
except Exception as e: except Exception as e:
logger.exception("Downloading audio failed") logger.exception("Downloading audio failed")
await fail_edit(m, f"下载/上传失败:{e}") await fail_edit(m, f"下载/上传失败:{e}")
return
with contextlib.suppress(Exception):
await m.delete()
return msg
async def go_download(v: Video, p_num: int, m: Message): async def go_download(v: Video, p_num: int, m: Message, task: bool = True):
video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4" video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4"
safe_remove(video_path) safe_remove(video_path)
flv_temp_path = cache_dir / f"{v.get_aid()}_{p_num}_temp.flv" flv_temp_path = cache_dir / f"{v.get_aid()}_{p_num}_temp.flv"
@ -298,7 +305,8 @@ async def go_download(v: Video, p_num: int, m: Message):
) )
if result != 0: if result != 0:
raise FFmpegError raise FFmpegError
bot.loop.create_task(go_upload(v, p_num, m)) if task:
bot.loop.create_task(go_upload(v, p_num, m))
except BilibiliDownloaderError as e: except BilibiliDownloaderError as e:
await fail_edit(m, e.MSG) await fail_edit(m, e.MSG)
except Exception as e: except Exception as e:
@ -328,7 +336,9 @@ async def go_upload_progress(current: int, total: int, m: Message):
await message_edit(total, current, chunk, chunk_time, m, "上传") await message_edit(total, current, chunk, chunk_time, m, "上传")
async def go_upload(v: Video, p_num: int, m: Message): async def go_upload(
v: Video, p_num: int, m: Message, push_id: int = None
) -> Optional[Message]:
video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4" video_path = cache_dir / f"{v.get_aid()}_{p_num}.mp4"
if not video_path.exists(): if not video_path.exists():
await fail_edit(m, "视频文件不存在") await fail_edit(m, "视频文件不存在")
@ -346,8 +356,8 @@ async def go_upload(v: Video, p_num: int, m: Message):
video_jpg = None video_jpg = None
caption = f"https://b23.tv/{v.get_bvid()}" caption = f"https://b23.tv/{v.get_bvid()}"
logger.info(f"Uploading {video_path}") logger.info(f"Uploading {video_path}")
await bot.send_video( msg = await bot.send_video(
chat_id=m.chat.id, chat_id=push_id or m.chat.id,
video=str(video_path), video=str(video_path),
caption=caption, caption=caption,
parse_mode=ParseMode.HTML, parse_mode=ParseMode.HTML,
@ -358,7 +368,7 @@ async def go_upload(v: Video, p_num: int, m: Message):
supports_streaming=True, supports_streaming=True,
progress=go_upload_progress, progress=go_upload_progress,
progress_args=(m,), progress_args=(m,),
reply_to_message_id=m.reply_to_message_id, reply_to_message_id=m.reply_to_message_id if not push_id else None,
) )
logger.info(f"Upload {video_path} success") logger.info(f"Upload {video_path} success")
except BilibiliDownloaderError as e: except BilibiliDownloaderError as e:
@ -376,3 +386,4 @@ async def go_upload(v: Video, p_num: int, m: Message):
del UPLOAD_MESSAGE_MAP[m.id] del UPLOAD_MESSAGE_MAP[m.id]
with contextlib.suppress(Exception): with contextlib.suppress(Exception):
await m.delete() await m.delete()
return msg

104
defs/bilibili_fav.py Normal file
View File

@ -0,0 +1,104 @@
import time
from enum import Enum
from typing import Optional
from bilibili_api.favorite_list import FavoriteList
from pydantic import BaseModel, ValidationError
from pyrogram.types import Message
from defs.bilibili import credential, create_video, create_audio
from defs.bilibili_download import go_download, go_upload, audio_download
from defs.glover import bilifav_id, bilifav_channel
from models.models.bilifav import BiliFav
from models.services.bilifav import BiliFavAction
from init import logger
fav = FavoriteList(media_id=bilifav_id, credential=credential)
class BilibiliFavException(Exception):
pass
class MediaType(int, Enum):
video = 2
audio = 12
class Media(BaseModel):
id: int
bvid: str
type: MediaType
title: str
cover: Optional[str]
""" 封面 """
intro: Optional[str]
""" 简介 """
async def process_video(data: Media, m: Message):
"""处理视频"""
video = create_video(data.bvid)
await go_download(video, 0, m, task=False)
msg = await go_upload(video, 0, m, push_id=bilifav_channel)
if not msg:
raise BilibiliFavException
video_db = BiliFav(
id=data.id,
bv_id=data.bvid.lower(),
type=data.type.value,
title=data.title,
cover=data.cover,
message_id=msg.id,
file_id=msg.video.file_id,
timestamp=int(time.time()),
)
await BiliFavAction.add_bili_fav(video_db)
async def process_audio(data: Media, m: Message):
"""处理音频"""
audio = create_audio(f"au{data.id}")
msg = await audio_download(audio, m, push_id=bilifav_channel)
if not msg:
raise BilibiliFavException
audio_db = BiliFav(
id=data.id,
bv_id=data.bvid.lower(),
type=data.type.value,
title=data.title,
cover=data.cover,
message_id=msg.id,
file_id=msg.audio.file_id,
timestamp=int(time.time()),
)
await BiliFavAction.add_bili_fav(audio_db)
async def check_update(m: Message):
"""检查收藏夹是否更新"""
logger.info("Check bilibili favorite list")
try:
info = await fav.get_content()
except Exception as e:
logger.exception("Check bilibili favorite list failed")
await m.edit(f"获取收藏夹信息失败:{e}")
return
for media in info.get("medias", [])[::-1]:
try:
data = Media(**media)
except ValidationError as _:
logger.exception("Validate media failed")
continue
if await BiliFavAction.get_by_bv_id(data.bvid):
continue
n = await m.reply(f"处理 {data.type.name} {data.bvid} 中...")
try:
if data.type == MediaType.video:
await process_video(data, n)
elif data.type == MediaType.audio:
await process_audio(data, n)
except BilibiliFavException:
continue
await m.edit("收藏夹数据获取完毕")
logger.info("Check bilibili favorite list success")

View File

@ -5,7 +5,7 @@ from typing import Optional
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from init import request from init import request
from models.fragment import ( from models.services.fragment import (
AuctionStatus, AuctionStatus,
UserName, UserName,
TON_TO_USD_RATE, TON_TO_USD_RATE,

View File

@ -13,9 +13,13 @@ lofter_channel: int = 0
lofter_channel_username: str = "" lofter_channel_username: str = ""
splash_channel: int = 0 splash_channel: int = 0
splash_channel_username: str = "" splash_channel_username: str = ""
bilifav_id: int = 0
bilifav_channel: int = 0
bilifav_channel_username: str = ""
# [api] # [api]
amap_key: str = "" amap_key: str = ""
bili_auth_user_str: str = "" bili_auth_user_str: str = ""
bili_auth_chat_str: str = ""
config = RawConfigParser() config = RawConfigParser()
config.read("config.ini") config.read("config.ini")
api_id = config.getint("pyrogram", "api_id", fallback=api_id) api_id = config.getint("pyrogram", "api_id", fallback=api_id)
@ -30,12 +34,20 @@ splash_channel = config.getint("post", "splash_channel", fallback=splash_channel
splash_channel_username = config.get( splash_channel_username = config.get(
"post", "splash_channel_username", fallback=splash_channel_username "post", "splash_channel_username", fallback=splash_channel_username
) )
bilifav_id = config.getint("post", "bilifav_id", fallback=bilifav_id)
bilifav_channel = config.getint("post", "bilifav_channel", fallback=bilifav_channel)
bilifav_channel_username = config.get(
"post", "bilifav_channel_username", fallback=bilifav_channel_username
)
amap_key = config.get("api", "amap_key", fallback=amap_key) amap_key = config.get("api", "amap_key", fallback=amap_key)
bili_auth_user_str = config.get("api", "bili_auth_user", fallback=bili_auth_user_str) bili_auth_user_str = config.get("api", "bili_auth_user", fallback=bili_auth_user_str)
bili_auth_chat_str = config.get("api", "bili_auth_chat", fallback=bili_auth_chat_str)
try: try:
bili_auth_user: List[int] = list(map(int, bili_auth_user_str.split(","))) bili_auth_user: List[int] = list(map(int, bili_auth_user_str.split(",")))
bili_auth_chat: List[int] = list(map(int, bili_auth_chat_str.split(",")))
except ValueError: except ValueError:
bili_auth_user: List[int] = [] bili_auth_user: List[int] = []
bili_auth_chat: List[int] = []
try: try:
ipv6 = bool(strtobool(ipv6)) ipv6 = bool(strtobool(ipv6))
except ValueError: except ValueError:

View File

@ -17,7 +17,7 @@ from pyrogram.types import (
) )
from defs.glover import lofter_channel_username from defs.glover import lofter_channel_username
from models.lofter import LofterPost as LofterPostModel from models.services.lofter import LofterPost as LofterPostModel
from init import request from init import request

View File

@ -12,7 +12,7 @@ from pyrogram.types import Message
from defs.glover import lofter_channel from defs.glover import lofter_channel
from defs.lofter import lofter_link from defs.lofter import lofter_link
from models.lofter import LofterPost as LofterPostModel from models.services.lofter import LofterPost as LofterPostModel
from models.models.lofter import Lofter as LofterModel from models.models.lofter import Lofter as LofterModel
from init import request, bot from init import request, bot

View File

@ -12,7 +12,7 @@ from defs.request import cache_file
from init import bot, request, logger from init import bot, request, logger
from models.models.splash import Splash as SplashModel from models.models.splash import Splash as SplashModel
from models.apis.splash import Splash as SplashApi from models.apis.splash import Splash as SplashApi
from models.splash import SplashService from models.services.splash import SplashService
async def get_splash() -> List[SplashApi]: async def get_splash() -> List[SplashApi]:

View File

14
models/models/bilifav.py Normal file
View File

@ -0,0 +1,14 @@
from sqlmodel import SQLModel, Field
class BiliFav(SQLModel, table=True):
__table_args__ = dict(mysql_charset="utf8mb4", mysql_collate="utf8mb4_general_ci")
id: int = Field(primary_key=True)
bv_id: str = Field()
type: int = Field(default=2)
title: str = Field()
cover: str = Field()
message_id: int = Field(default=0)
file_id: str = Field()
timestamp: int = Field(default=0)

View File

View File

@ -0,0 +1,42 @@
from typing import cast, Optional
from sqlalchemy import select
from sqlmodel.ext.asyncio.session import AsyncSession
from init import sqlite
from models.models.bilifav import BiliFav
class BiliFavAction:
@staticmethod
async def get_by_id(id_: int) -> Optional[BiliFav]:
async with sqlite.session() as session:
session = cast(AsyncSession, session)
statement = select(BiliFav).where(BiliFav.id == id_)
results = await session.exec(statement)
return post[0] if (post := results.first()) else None
@staticmethod
async def get_by_bv_id(bv_id: str) -> Optional[BiliFav]:
if not bv_id:
return None
async with sqlite.session() as session:
session = cast(AsyncSession, session)
statement = select(BiliFav).where(BiliFav.bv_id == bv_id.lower())
results = await session.exec(statement)
return post[0] if (post := results.first()) else None
@staticmethod
async def add_bili_fav(bili_fav: BiliFav):
async with sqlite.session() as session:
session = cast(AsyncSession, session)
session.add(bili_fav)
await session.commit()
@staticmethod
async def update_bili_fav(bili_fav: BiliFav):
async with sqlite.session() as session:
session = cast(AsyncSession, session)
session.add(bili_fav)
await session.commit()
await session.refresh(bili_fav)

View File

@ -99,7 +99,7 @@ class FragmentSubText(Enum):
class FragmentSub: class FragmentSub:
@staticmethod @staticmethod
async def subscribe(cid: int, username: str): async def subscribe(cid: int, username: str):
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
data = Fragment(cid=cid, username=username) data = Fragment(cid=cid, username=username)
session.add(data) session.add(data)
@ -107,14 +107,14 @@ class FragmentSub:
@staticmethod @staticmethod
async def unsubscribe(data: Fragment): async def unsubscribe(data: Fragment):
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
await session.delete(data) await session.delete(data)
await session.commit() await session.commit()
@staticmethod @staticmethod
async def get_by_cid_and_username(cid: int, username: str) -> Optional[Fragment]: async def get_by_cid_and_username(cid: int, username: str) -> Optional[Fragment]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
statement = ( statement = (
select(Fragment) select(Fragment)
@ -126,7 +126,7 @@ class FragmentSub:
@staticmethod @staticmethod
async def get_by_cid(cid: int) -> List[Fragment]: async def get_by_cid(cid: int) -> List[Fragment]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
statement = select(Fragment).where(Fragment.cid == cid) statement = select(Fragment).where(Fragment.cid == cid)
results = await session.exec(statement) results = await session.exec(statement)
@ -134,7 +134,7 @@ class FragmentSub:
@staticmethod @staticmethod
async def get_all() -> List[Fragment]: async def get_all() -> List[Fragment]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
statement = select(Fragment) statement = select(Fragment)
results = await session.exec(statement) results = await session.exec(statement)

View File

@ -10,7 +10,7 @@ from models.models.lofter import Lofter
class LofterPost: class LofterPost:
@staticmethod @staticmethod
async def get_by_post_and_user_id(user_id: str, post_id: str) -> Optional[Lofter]: async def get_by_post_and_user_id(user_id: str, post_id: str) -> Optional[Lofter]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
if user_id != "0": if user_id != "0":
check = Lofter.post_id == post_id and Lofter.user_id == user_id check = Lofter.post_id == post_id and Lofter.user_id == user_id
@ -26,7 +26,7 @@ class LofterPost:
@staticmethod @staticmethod
async def add_post(post: Lofter): async def add_post(post: Lofter):
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
session.add(post) session.add(post)
await session.commit() await session.commit()

View File

@ -10,7 +10,7 @@ from models.models.splash import Splash
class SplashService: class SplashService:
@staticmethod @staticmethod
async def get_by_splash_id(splash_id: int) -> Optional[Splash]: async def get_by_splash_id(splash_id: int) -> Optional[Splash]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
check = Splash.id == splash_id check = Splash.id == splash_id
statement = select(Splash).where(check) statement = select(Splash).where(check)
@ -19,7 +19,7 @@ class SplashService:
@staticmethod @staticmethod
async def get_all_splashes() -> List[Optional[Splash]]: async def get_all_splashes() -> List[Optional[Splash]]:
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
statement = select(Splash) statement = select(Splash)
results = await session.exec(statement) results = await session.exec(statement)
@ -27,14 +27,14 @@ class SplashService:
@staticmethod @staticmethod
async def add_splash(splash: Splash): async def add_splash(splash: Splash):
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
session.add(splash) session.add(splash)
await session.commit() await session.commit()
@staticmethod @staticmethod
async def update_splash(splash: Splash): async def update_splash(splash: Splash):
async with sqlite.Session() as session: async with sqlite.session() as session:
session = cast(AsyncSession, session) session = cast(AsyncSession, session)
session.add(splash) session.add(splash)
await session.commit() await session.commit()

View File

@ -1,9 +1,11 @@
from sqlmodel import SQLModel from sqlmodel import SQLModel
from models.models.bilifav import BiliFav
from models.models.lofter import Lofter from models.models.lofter import Lofter
from models.models.fragment import Fragment from models.models.fragment import Fragment
from models.models.splash import Splash
__all__ = ["Lofter", "Fragment", "Sqlite"] __all__ = ["BiliFav", "Lofter", "Fragment", "Splash", "Sqlite"]
from sqlalchemy.ext.asyncio import create_async_engine from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
@ -13,15 +15,11 @@ from sqlmodel.ext.asyncio.session import AsyncSession
class Sqlite: class Sqlite:
def __init__(self): def __init__(self):
self.engine = create_async_engine("sqlite+aiosqlite:///data/data.db") self.engine = create_async_engine("sqlite+aiosqlite:///data/data.db")
self.Session = sessionmaker(bind=self.engine, class_=AsyncSession) self.session = sessionmaker(bind=self.engine, class_=AsyncSession)
async def create_db_and_tables(self): async def create_db_and_tables(self):
async with self.engine.begin() as session: async with self.engine.begin() as session:
await session.run_sync(SQLModel.metadata.create_all) await session.run_sync(SQLModel.metadata.create_all)
async def get_session(self):
async with self.Session() as session:
yield session
def stop(self): def stop(self):
self.Session.close_all() self.session.close_all()

View File

@ -12,7 +12,7 @@ from defs.bilibili import (
check_and_refresh_credential, check_and_refresh_credential,
) )
from defs.button import gen_button, Button from defs.button import gen_button, Button
from defs.glover import bili_auth_user from defs.glover import bili_auth_user, bili_auth_chat
from init import bot from init import bot
from scheduler import scheduler from scheduler import scheduler
@ -21,7 +21,7 @@ from scheduler import scheduler
filters.incoming filters.incoming
& filters.text & filters.text
& filters.regex(r"av(\d{1,12})|BV(1[A-Za-z0-9]{2}4.1.7[A-Za-z0-9]{2})|b23.tv") & filters.regex(r"av(\d{1,12})|BV(1[A-Za-z0-9]{2}4.1.7[A-Za-z0-9]{2})|b23.tv")
& ~(filters.command(["download"]) & filters.user(bili_auth_user)) & ~(filters.command(["download", "bilibili_fav"]) & filters.user(bili_auth_user))
) )
async def bili_resolve(_: Client, message: Message): async def bili_resolve(_: Client, message: Message):
""" """
@ -37,7 +37,9 @@ async def bili_resolve(_: Client, message: Message):
if video_info: if video_info:
image = await binfo_image_create(video_info) image = await binfo_image_create(video_info)
buttons = [Button(0, "Link", "https://b23.tv/" + video_info["bvid"])] buttons = [Button(0, "Link", "https://b23.tv/" + video_info["bvid"])]
if message.from_user and message.from_user.id in bili_auth_user: if (message.from_user and message.from_user.id in bili_auth_user) or (
message.chat and message.chat.id in bili_auth_chat
):
buttons.append(Button(1, "Download", "download_" + video_info["bvid"])) buttons.append(Button(1, "Download", "download_" + video_info["bvid"]))
await message.reply_photo( await message.reply_photo(
image, image,

View File

@ -5,14 +5,15 @@ from pyrogram.types import Message, CallbackQuery
from defs.bilibili import b23_extract, create_video, create_audio from defs.bilibili import b23_extract, create_video, create_audio
from defs.bilibili_download import go_download, audio_download from defs.bilibili_download import go_download, audio_download
from defs.glover import bili_auth_user from defs.glover import bili_auth_user, bilifav_channel_username, bili_auth_chat
from init import bot from init import bot
from models.services.bilifav import BiliFavAction
@bot.on_message( @bot.on_message(
filters.incoming filters.incoming
& filters.text & filters.text
& filters.user(bili_auth_user) & (filters.user(bili_auth_user) | filters.chat(bili_auth_chat))
& filters.command(["download"]) & filters.command(["download"])
) )
async def bili_download_resolve(_: Client, message: Message): async def bili_download_resolve(_: Client, message: Message):
@ -29,6 +30,13 @@ async def bili_download_resolve(_: Client, message: Message):
p_num = p_.search(message.text) p_num = p_.search(message.text)
p_num = int(p_num[0][2:]) if p_num else 0 p_num = int(p_num[0][2:]) if p_num else 0
video = create_video(video_number) video = create_video(video_number)
if video_db := await BiliFavAction.get_by_bv_id(video.get_bvid()):
await message.reply_video(
video_db.file_id,
caption=f"详细信息https://t.me/{bilifav_channel_username}/{video_db.message_id}",
quote=True,
)
raise ContinuePropagation
m = await message.reply("开始获取视频数据", quote=True) m = await message.reply("开始获取视频数据", quote=True)
bot.loop.create_task(go_download(video, p_num, m)) bot.loop.create_task(go_download(video, p_num, m))
@ -51,11 +59,22 @@ async def bili_download_resolve_cb(_: Client, callback_query: CallbackQuery):
if not callback_query.from_user: if not callback_query.from_user:
await callback_query.answer("请私聊机器人") await callback_query.answer("请私聊机器人")
return return
if callback_query.from_user.id not in bili_auth_user: if (
await callback_query.answer("你没有权限使用此功能") callback_query.message.chat.id not in bili_auth_chat
and callback_query.from_user.id not in bili_auth_user
):
await callback_query.answer("你没有权限")
return return
video_number = callback_query.matches[0].group(1) video_number = callback_query.matches[0].group(1)
video = create_video(video_number) video = create_video(video_number)
if video_db := await BiliFavAction.get_by_bv_id(video.get_bvid()):
await callback_query.answer("找到缓存")
await callback_query.message.reply_video(
video_db.file_id,
caption=f"详细信息https://t.me/{bilifav_channel_username}/{video_db.message_id}",
quote=True,
)
raise ContinuePropagation
m = await callback_query.message.reply("开始获取视频数据", quote=True) m = await callback_query.message.reply("开始获取视频数据", quote=True)
bot.loop.create_task(go_download(video, 0, m)) bot.loop.create_task(go_download(video, 0, m))
await callback_query.answer("开始下载") await callback_query.answer("开始下载")

103
modules/bilibili_fav.py Normal file
View File

@ -0,0 +1,103 @@
import re
import time
from pyrogram import filters, Client, ContinuePropagation
from pyrogram.types import Message, CallbackQuery
from defs.bilibili import b23_extract, create_video, create_audio
from defs.bilibili_download import go_download, go_upload, audio_download
from defs.bilibili_fav import check_update
from defs.glover import admin, bilifav_channel
from init import bot, logger
from models.models.bilifav import BiliFav
from models.services.bilifav import BiliFavAction
async def process_audio(video_number: str, message: Message):
id_ = int(video_number[2:])
if await BiliFavAction.get_by_id(id_):
await message.reply("该音频已经存在")
raise ContinuePropagation
audio = create_audio(video_number)
info = await audio.get_info()
m = await message.reply("开始获取音频数据", quote=True)
msg = await audio_download(audio, m, push_id=bilifav_channel)
if not msg:
raise ContinuePropagation
audio_db = BiliFav(
id=id_,
bv_id=info.get("bvid", "").lower(),
type=12,
title=info.get("title", ""),
cover=info.get("cover", ""),
message_id=msg.id,
file_id=msg.audio.file_id,
timestamp=int(time.time()),
)
await BiliFavAction.add_bili_fav(audio_db)
async def process_video(video_number: str, p_num: int, message: Message):
video = create_video(video_number)
if await BiliFavAction.get_by_bv_id(video.get_bvid()):
await message.edit("该视频已经存在")
raise ContinuePropagation
info = await video.get_info()
id_ = info.get("aid", 0)
if not id_:
await message.edit("未找到视频 AV 号")
raise ContinuePropagation
m = await message.reply("开始获取视频数据", quote=True)
await go_download(video, p_num, m, task=False)
msg = await go_upload(video, p_num, m, push_id=bilifav_channel)
if not msg:
raise ContinuePropagation
audio_db = BiliFav(
id=id_,
bv_id=info.get("bvid", "").lower(),
type=2,
title=info.get("title", ""),
cover=info.get("pic", ""),
message_id=msg.id,
file_id=msg.video.file_id,
timestamp=int(time.time()),
)
await BiliFavAction.add_bili_fav(audio_db)
@bot.on_message(
filters.incoming
& filters.text
& filters.user(admin)
& filters.command(["bilibili_fav"])
)
async def bilibili_fav_parse(_: Client, message: Message):
if len(message.command) <= 1:
m = await message.reply("正在获取收藏夹数据", quote=True)
await check_update(m)
return
if "b23.tv" in message.text:
message.text = await b23_extract(message.text)
p = re.compile(r"av(\d{1,12})|BV(1[A-Za-z0-9]{2}4.1.7[A-Za-z0-9]{2})|au(\d{1,12})")
video_number = p.search(message.text)
if video_number:
video_number = video_number[0]
else:
await message.reply("未找到视频 BV 号、 AV 或 AU 号")
raise ContinuePropagation
p_ = re.compile(r"p=(\d{1,3})")
p_num = p_.search(message.text)
p_num = int(p_num[0][2:]) if p_num else 0
m = await message.reply("开始获取数据", quote=True)
try:
if video_number.startswith("au"):
await process_audio(video_number, m)
else:
await process_video(video_number, p_num, m)
except ContinuePropagation:
raise ContinuePropagation
except Exception as e:
logger.exception("Processing bilibili favorite single push failed")
await m.edit(f"处理失败: {e}")
await m.edit("处理完成")
raise ContinuePropagation

View File

@ -12,7 +12,7 @@ from pyrogram.types import (
Message, Message,
) )
from models.fragment import FragmentSubText, FragmentSub, AuctionStatus from models.services.fragment import FragmentSubText, FragmentSub, AuctionStatus
from defs.fragment import parse_fragment, NotAvailable, parse_sub from defs.fragment import parse_fragment, NotAvailable, parse_sub
from init import bot from init import bot
from scheduler import scheduler, add_delete_message_job from scheduler import scheduler, add_delete_message_job