mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
refactor: own subscription create transactions
This commit is contained in:
+166
-92
@@ -3,6 +3,7 @@ import json
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any, Callable, Dict, List, Optional, Union, Tuple
|
||||
|
||||
@@ -88,6 +89,24 @@ SystemConfigOper = get_configured_system_config
|
||||
_DEFAULT_SYSTEM_CONFIG_PROVIDER = get_configured_system_config
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class _SubscribePostCommitContext:
|
||||
"""订阅提交后副作用所需的不可变业务快照。"""
|
||||
|
||||
title: str
|
||||
year: str
|
||||
metainfo: MetaBase
|
||||
mediainfo: MediaInfo
|
||||
media_source: Optional[MediaSource]
|
||||
media_id: Optional[str]
|
||||
season: Optional[int]
|
||||
channel: Optional[NotificationChannel]
|
||||
source: Optional[str]
|
||||
userid: Optional[str]
|
||||
username: Optional[str]
|
||||
message: bool
|
||||
|
||||
|
||||
def _system_config():
|
||||
"""返回配置端口,并兼容旧测试对本地别名的替换。"""
|
||||
if SystemConfigOper is not _DEFAULT_SYSTEM_CONFIG_PROVIDER:
|
||||
@@ -851,6 +870,98 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
})
|
||||
return defaults
|
||||
|
||||
@staticmethod
|
||||
def __subscribe_added_link(mtype: MediaType) -> str:
|
||||
"""返回订阅类型对应的前端详情入口。"""
|
||||
if mtype == MediaType.TV:
|
||||
return settings.MP_DOMAIN('#/subscribe/tv?tab=mysub')
|
||||
if mtype == MediaType.MUSIC:
|
||||
return settings.MP_DOMAIN('#/subscribe/music?tab=mysub')
|
||||
return settings.MP_DOMAIN('#/subscribe/movie?tab=mysub')
|
||||
|
||||
@staticmethod
|
||||
def __subscribe_report_payload(context: _SubscribePostCommitContext) -> dict:
|
||||
"""构造保持旧字段和值语义的订阅统计上报。"""
|
||||
mediainfo = context.mediainfo
|
||||
music_type = getattr(mediainfo, "music_type", None)
|
||||
return {
|
||||
"name": context.title,
|
||||
"year": context.year,
|
||||
"type": context.metainfo.type.value,
|
||||
"media_source": context.media_source,
|
||||
"media_id": context.media_id,
|
||||
"music_type": music_type,
|
||||
"total_tracks": getattr(mediainfo, "total_tracks", None)
|
||||
if music_type == MUSIC_ENTITY_ALBUM else None,
|
||||
"season": context.season,
|
||||
"poster": mediainfo.get_poster_image(),
|
||||
"backdrop": mediainfo.get_backdrop_image(),
|
||||
"vote": mediainfo.vote_average,
|
||||
"description": mediainfo.overview,
|
||||
}
|
||||
|
||||
def __post_subscribe_added(
|
||||
self,
|
||||
subscribe_id: int,
|
||||
context: _SubscribePostCommitContext,
|
||||
) -> None:
|
||||
"""同步执行提交后消息、事件和统计,异常不再触碰数据库事务。"""
|
||||
if context.message:
|
||||
self.post_message(
|
||||
_SchemaMessage(
|
||||
channel=context.channel,
|
||||
source=context.source,
|
||||
mtype=MessageType.Subscribe,
|
||||
ctype=ContentType.SubscribeAdded,
|
||||
image=context.mediainfo.get_message_image(),
|
||||
link=self.__subscribe_added_link(context.mediainfo.type),
|
||||
userid=context.userid,
|
||||
username=context.username,
|
||||
),
|
||||
meta=context.metainfo,
|
||||
mediainfo=context.mediainfo,
|
||||
username=context.username,
|
||||
)
|
||||
eventmanager.send_event(EventType.SubscribeAdded, {
|
||||
"subscribe_id": subscribe_id,
|
||||
"username": context.username,
|
||||
"mediainfo": context.mediainfo.to_dict(),
|
||||
})
|
||||
MoviePilotServerHelper.sub_reg_async(
|
||||
self.__subscribe_report_payload(context)
|
||||
)
|
||||
|
||||
async def __async_post_subscribe_added(
|
||||
self,
|
||||
subscribe_id: int,
|
||||
context: _SubscribePostCommitContext,
|
||||
) -> None:
|
||||
"""异步执行提交后消息、事件和统计,保持与同步入口相同顺序。"""
|
||||
if context.message:
|
||||
await self.async_post_message(
|
||||
_SchemaMessage(
|
||||
channel=context.channel,
|
||||
source=context.source,
|
||||
mtype=MessageType.Subscribe,
|
||||
ctype=ContentType.SubscribeAdded,
|
||||
image=context.mediainfo.get_message_image(),
|
||||
link=self.__subscribe_added_link(context.mediainfo.type),
|
||||
userid=context.userid,
|
||||
username=context.username,
|
||||
),
|
||||
meta=context.metainfo,
|
||||
mediainfo=context.mediainfo,
|
||||
username=context.username,
|
||||
)
|
||||
await eventmanager.async_send_event(EventType.SubscribeAdded, {
|
||||
"subscribe_id": subscribe_id,
|
||||
"username": context.username,
|
||||
"mediainfo": context.mediainfo.to_dict(),
|
||||
})
|
||||
await MoviePilotServerHelper.async_sub_reg(
|
||||
self.__subscribe_report_payload(context)
|
||||
)
|
||||
|
||||
def add(self, title: str, year: str,
|
||||
mtype: MediaType = None,
|
||||
episode_group: Optional[str] = None,
|
||||
@@ -992,8 +1103,33 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
# 添加订阅
|
||||
kwargs.update(self.__get_default_kwargs(mediainfo.type, **kwargs))
|
||||
|
||||
post_commit_context = _SubscribePostCommitContext(
|
||||
title=title,
|
||||
year=year,
|
||||
metainfo=metainfo,
|
||||
mediainfo=mediainfo,
|
||||
media_source=media_source,
|
||||
media_id=media_id,
|
||||
season=season,
|
||||
channel=channel,
|
||||
source=source,
|
||||
userid=userid,
|
||||
username=username,
|
||||
message=bool(message),
|
||||
)
|
||||
|
||||
def _after_commit(subscribe_id: int) -> None:
|
||||
"""把同步提交后的副作用委托给单一顺序实现。"""
|
||||
self.__post_subscribe_added(subscribe_id, post_commit_context)
|
||||
|
||||
# 操作数据库
|
||||
sid, err_msg = add_subscribe(mediainfo=mediainfo, season=season, username=username, **kwargs)
|
||||
sid, err_msg = add_subscribe(
|
||||
mediainfo=mediainfo,
|
||||
season=season,
|
||||
username=username,
|
||||
after_commit=_after_commit,
|
||||
**kwargs,
|
||||
)
|
||||
if not sid:
|
||||
logger.error(f'{mediainfo.title_year} {err_msg}')
|
||||
if not exist_ok and message:
|
||||
@@ -1007,51 +1143,6 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
image=mediainfo.get_message_image(),
|
||||
userid=userid))
|
||||
return None, err_msg
|
||||
elif message:
|
||||
if mediainfo.type == MediaType.TV:
|
||||
link = settings.MP_DOMAIN('#/subscribe/tv?tab=mysub')
|
||||
elif mediainfo.type == MediaType.MUSIC:
|
||||
link = settings.MP_DOMAIN('#/subscribe/music?tab=mysub')
|
||||
else:
|
||||
link = settings.MP_DOMAIN('#/subscribe/movie?tab=mysub')
|
||||
# 订阅成功按规则发送消息
|
||||
self.post_message(
|
||||
_SchemaMessage(
|
||||
channel=channel,
|
||||
source=source,
|
||||
mtype=MessageType.Subscribe,
|
||||
ctype=ContentType.SubscribeAdded,
|
||||
image=mediainfo.get_message_image(),
|
||||
link=link,
|
||||
userid=userid,
|
||||
username=username
|
||||
),
|
||||
meta=metainfo,
|
||||
mediainfo=mediainfo,
|
||||
username=username
|
||||
)
|
||||
# 发送事件
|
||||
eventmanager.send_event(EventType.SubscribeAdded, {
|
||||
"subscribe_id": sid,
|
||||
"username": username,
|
||||
"mediainfo": mediainfo.to_dict(),
|
||||
})
|
||||
# 统计订阅
|
||||
MoviePilotServerHelper.sub_reg_async({
|
||||
"name": title,
|
||||
"year": year,
|
||||
"type": metainfo.type.value,
|
||||
"media_source": media_source,
|
||||
"media_id": media_id,
|
||||
"music_type": getattr(mediainfo, "music_type", None),
|
||||
"total_tracks": getattr(mediainfo, "total_tracks", None)
|
||||
if getattr(mediainfo, "music_type", None) == MUSIC_ENTITY_ALBUM else None,
|
||||
"season": season,
|
||||
"poster": mediainfo.get_poster_image(),
|
||||
"backdrop": mediainfo.get_backdrop_image(),
|
||||
"vote": mediainfo.vote_average,
|
||||
"description": mediainfo.overview
|
||||
})
|
||||
# 返回结果
|
||||
return sid, err_msg
|
||||
|
||||
@@ -1196,8 +1287,36 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
# 列新默认参数
|
||||
kwargs.update(self.__get_default_kwargs(mediainfo.type, **kwargs))
|
||||
|
||||
post_commit_context = _SubscribePostCommitContext(
|
||||
title=title,
|
||||
year=year,
|
||||
metainfo=metainfo,
|
||||
mediainfo=mediainfo,
|
||||
media_source=media_source,
|
||||
media_id=media_id,
|
||||
season=season,
|
||||
channel=channel,
|
||||
source=source,
|
||||
userid=userid,
|
||||
username=username,
|
||||
message=bool(message),
|
||||
)
|
||||
|
||||
async def _after_commit(subscribe_id: int) -> None:
|
||||
"""把异步提交后的副作用委托给单一顺序实现。"""
|
||||
await self.__async_post_subscribe_added(
|
||||
subscribe_id,
|
||||
post_commit_context,
|
||||
)
|
||||
|
||||
# 操作数据库
|
||||
sid, err_msg = await async_add_subscribe(mediainfo=mediainfo, season=season, username=username, **kwargs)
|
||||
sid, err_msg = await async_add_subscribe(
|
||||
mediainfo=mediainfo,
|
||||
season=season,
|
||||
username=username,
|
||||
after_commit=_after_commit,
|
||||
**kwargs,
|
||||
)
|
||||
if not sid:
|
||||
logger.error(f'{mediainfo.title_year} {err_msg}')
|
||||
if not exist_ok and message:
|
||||
@@ -1211,51 +1330,6 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
image=mediainfo.get_message_image(),
|
||||
userid=userid))
|
||||
return None, err_msg
|
||||
elif message:
|
||||
if mediainfo.type == MediaType.TV:
|
||||
link = settings.MP_DOMAIN('#/subscribe/tv?tab=mysub')
|
||||
elif mediainfo.type == MediaType.MUSIC:
|
||||
link = settings.MP_DOMAIN('#/subscribe/music?tab=mysub')
|
||||
else:
|
||||
link = settings.MP_DOMAIN('#/subscribe/movie?tab=mysub')
|
||||
# 订阅成功按规则发送消息
|
||||
await self.async_post_message(
|
||||
_SchemaMessage(
|
||||
channel=channel,
|
||||
source=source,
|
||||
mtype=MessageType.Subscribe,
|
||||
ctype=ContentType.SubscribeAdded,
|
||||
image=mediainfo.get_message_image(),
|
||||
link=link,
|
||||
userid=userid,
|
||||
username=username
|
||||
),
|
||||
meta=metainfo,
|
||||
mediainfo=mediainfo,
|
||||
username=username
|
||||
)
|
||||
# 发送事件
|
||||
await eventmanager.async_send_event(EventType.SubscribeAdded, {
|
||||
"subscribe_id": sid,
|
||||
"username": username,
|
||||
"mediainfo": mediainfo.to_dict(),
|
||||
})
|
||||
# 统计订阅
|
||||
await MoviePilotServerHelper.async_sub_reg({
|
||||
"name": title,
|
||||
"year": year,
|
||||
"type": metainfo.type.value,
|
||||
"media_source": media_source,
|
||||
"media_id": media_id,
|
||||
"music_type": getattr(mediainfo, "music_type", None),
|
||||
"total_tracks": getattr(mediainfo, "total_tracks", None)
|
||||
if getattr(mediainfo, "music_type", None) == MUSIC_ENTITY_ALBUM else None,
|
||||
"season": season,
|
||||
"poster": mediainfo.get_poster_image(),
|
||||
"backdrop": mediainfo.get_backdrop_image(),
|
||||
"vote": mediainfo.vote_average,
|
||||
"description": mediainfo.overview
|
||||
})
|
||||
# 返回结果
|
||||
return sid, err_msg
|
||||
|
||||
|
||||
Reference in New Issue
Block a user