feat:订阅统计

This commit is contained in:
jxxghp 2024-05-06 11:19:41 +08:00
parent 73bdca282c
commit dd5c0de7b1
4 changed files with 155 additions and 6 deletions

View File

@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
from app import schemas from app import schemas
from app.chain.subscribe import SubscribeChain from app.chain.subscribe import SubscribeChain
from app.core.config import settings from app.core.config import settings
from app.core.context import MediaInfo
from app.core.metainfo import MetaInfo from app.core.metainfo import MetaInfo
from app.core.security import verify_token, verify_uri_token from app.core.security import verify_token, verify_uri_token
from app.db import get_db from app.db import get_db
@ -14,6 +15,7 @@ from app.db.models.subscribe import Subscribe
from app.db.models.subscribehistory import SubscribeHistory from app.db.models.subscribehistory import SubscribeHistory
from app.db.models.user import User from app.db.models.user import User
from app.db.userauth import get_current_active_user from app.db.userauth import get_current_active_user
from app.helper.subscribe import SubscribeHelper
from app.scheduler import Scheduler from app.scheduler import Scheduler
from app.schemas.types import MediaType from app.schemas.types import MediaType
@ -334,6 +336,38 @@ def delete_subscribe(
return schemas.Response(success=True) return schemas.Response(success=True)
@router.get("/popular", summary="热门订阅(基于用户共享数据)", response_model=List[schemas.MediaInfo])
def popular_subscribes(
stype: str,
page: int = 1,
count: int = 30,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
查询热门订阅
"""
subscribes = SubscribeHelper().get_statistic(stype=stype, page=page, count=count)
if subscribes:
ret_medias = []
for sub in subscribes:
media = MediaInfo()
media.type = MediaType(sub.get("type"))
media.title = sub.get("name")
media.year = sub.get("year")
media.tmdb_id = sub.get("tmdbid")
media.douban_id = sub.get("doubanid")
media.bangumi_id = sub.get("bangumiid")
media.tvdb_id = sub.get("tvdbid")
media.imdb_id = sub.get("imdbid")
media.season = sub.get("season")
media.overview = sub.get("description")
media.vote_average = sub.get("vote")
media.poster_path = sub.get("poster")
media.backdrop_path = sub.get("backdrop")
ret_medias.append(media)
return [media.to_dict() for media in ret_medias]
return []
@router.get("/{subscribe_id}", summary="订阅详情", response_model=schemas.Subscribe) @router.get("/{subscribe_id}", summary="订阅详情", response_model=schemas.Subscribe)
def read_subscribe( def read_subscribe(
subscribe_id: int, subscribe_id: int,

View File

@ -19,6 +19,7 @@ from app.db.subscribe_oper import SubscribeOper
from app.db.subscribehistory_oper import SubscribeHistoryOper from app.db.subscribehistory_oper import SubscribeHistoryOper
from app.db.systemconfig_oper import SystemConfigOper from app.db.systemconfig_oper import SystemConfigOper
from app.helper.message import MessageHelper from app.helper.message import MessageHelper
from app.helper.subscribe import SubscribeHelper
from app.helper.torrent import TorrentHelper from app.helper.torrent import TorrentHelper
from app.log import logger from app.log import logger
from app.schemas import NotExistMediaInfo, Notification from app.schemas import NotExistMediaInfo, Notification
@ -36,6 +37,7 @@ class SubscribeChain(ChainBase):
self.searchchain = SearchChain() self.searchchain = SearchChain()
self.subscribeoper = SubscribeOper() self.subscribeoper = SubscribeOper()
self.subscribehistoryoper = SubscribeHistoryOper() self.subscribehistoryoper = SubscribeHistoryOper()
self.subscribehelper = SubscribeHelper()
self.torrentschain = TorrentsChain() self.torrentschain = TorrentsChain()
self.mediachain = MediaChain() self.mediachain = MediaChain()
self.message = MessageHelper() self.message = MessageHelper()
@ -122,6 +124,9 @@ class SubscribeChain(ChainBase):
kwargs.update({ kwargs.update({
'lack_episode': kwargs.get('total_episode') 'lack_episode': kwargs.get('total_episode')
}) })
else:
# 避免season为0的问题
season = None
# 更新媒体图片 # 更新媒体图片
self.obtain_images(mediainfo=mediainfo) self.obtain_images(mediainfo=mediainfo)
# 合并信息 # 合并信息
@ -153,6 +158,7 @@ class SubscribeChain(ChainBase):
text=f"{err_msg}", text=f"{err_msg}",
image=mediainfo.get_message_image(), image=mediainfo.get_message_image(),
userid=userid)) userid=userid))
return None, err_msg
elif message: elif message:
logger.info(f'{mediainfo.title_year} {metainfo.season} 添加订阅成功') logger.info(f'{mediainfo.title_year} {metainfo.season} 添加订阅成功')
if username: if username:
@ -164,12 +170,28 @@ class SubscribeChain(ChainBase):
title=f"{mediainfo.title_year} {metainfo.season} 已添加订阅", title=f"{mediainfo.title_year} {metainfo.season} 已添加订阅",
text=text, text=text,
image=mediainfo.get_message_image())) image=mediainfo.get_message_image()))
# 发送事件 # 发送事件
EventManager().send_event(EventType.SubscribeAdded, { EventManager().send_event(EventType.SubscribeAdded, {
"subscribe_id": sid, "subscribe_id": sid,
"username": username, "username": username,
"mediainfo": mediainfo.to_dict(), "mediainfo": mediainfo.to_dict(),
}) })
# 统计订阅
self.subscribehelper.sub_reg_async({
"name": title,
"year": year,
"type": metainfo.type.value,
"tmdbid": mediainfo.tmdb_id,
"imdbid": mediainfo.imdb_id,
"tvdbid": mediainfo.tvdb_id,
"doubanid": mediainfo.douban_id,
"bangumiid": mediainfo.bangumi_id,
"season": metainfo.begin_season,
"poster": mediainfo.get_poster_image(),
"backdrop": mediainfo.get_backdrop_image(),
"vote": mediainfo.vote_average,
"description": mediainfo.overview
})
# 返回结果 # 返回结果
return sid, "" return sid, ""

91
app/helper/subscribe.py Normal file
View File

@ -0,0 +1,91 @@
from threading import Thread
from typing import List
from cachetools import TTLCache, cached
from app.db.subscribe_oper import SubscribeOper
from app.db.systemconfig_oper import SystemConfigOper
from app.schemas.types import SystemConfigKey
from app.utils.http import RequestUtils
from app.utils.singleton import Singleton
class SubscribeHelper(metaclass=Singleton):
"""
订阅数据统计
"""
_sub_reg = "https://movie-pilot.org/subscribe/add"
_sub_report = "https://movie-pilot.org/subscribe/report"
_sub_statistic = "https://movie-pilot.org/subscribe/statistic"
def __init__(self):
self.systemconfig = SystemConfigOper()
if not self.systemconfig.get(SystemConfigKey.SubscribeReport):
if self.sub_report():
self.systemconfig.set(SystemConfigKey.SubscribeReport, "1")
@cached(cache=TTLCache(maxsize=10, ttl=1800))
def get_statistic(self, stype: str, page: int = 1, count: int = 30) -> List[dict]:
"""
获取订阅统计数据
"""
res = RequestUtils(timeout=15).get_res(self._sub_statistic, params={
"stype": stype,
"page": page,
"count": count
})
if res and res.status_code == 200:
return res.json()
return []
def sub_reg(self, sub: dict) -> bool:
"""
新增订阅统计
"""
res = RequestUtils(timeout=5, headers={
"Content-Type": "application/json"
}).post_res(self._sub_reg, json=sub)
if res and res.status_code == 200:
return True
return False
def sub_reg_async(self, sub: dict) -> bool:
"""
异步新增订阅统计
"""
# 开新线程处理
Thread(target=self.sub_reg, args=(sub,)).start()
return True
def sub_report(self) -> bool:
"""
上报存量订阅统计
"""
subscribes = SubscribeOper().list()
if not subscribes:
return True
res = RequestUtils(content_type="application/json",
timeout=10).post(self._sub_report,
json={
"subscribes": [
{
"name": sub.name,
"year": sub.year,
"type": sub.type,
"tmdbid": sub.tmdbid,
"imdbid": sub.imdbid,
"tvdbid": sub.tvdbid,
"doubanid": sub.doubanid,
"bangumiid": sub.bangumiid,
"season": sub.season,
"poster": sub.poster,
"backdrop": sub.backdrop,
"vote": sub.vote,
"description": sub.description
} for sub in subscribes
]
})
return True if res else False

View File

@ -82,6 +82,8 @@ class SystemConfigKey(Enum):
TransferExcludeWords = "TransferExcludeWords" TransferExcludeWords = "TransferExcludeWords"
# 插件安装统计 # 插件安装统计
PluginInstallReport = "PluginInstallReport" PluginInstallReport = "PluginInstallReport"
# 订阅统计
SubscribeReport = "SubscribeReport"
# 处理进度Key字典 # 处理进度Key字典