Merge branch 'jxxghp:main' into main
This commit is contained in:
commit
261f5fc0c6
@ -219,6 +219,14 @@ location / {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
- 反代使用ssl时,需要开启`http2`,否则会导致日志加载时间过长或不可用。以`Nginx`为例:
|
||||||
|
```nginx configuration
|
||||||
|
server{
|
||||||
|
listen 443 ssl;
|
||||||
|
http2 on;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
- 新建的企业微信应用需要固定公网IP的代理才能收到消息,代理添加以下代码:
|
- 新建的企业微信应用需要固定公网IP的代理才能收到消息,代理添加以下代码:
|
||||||
```nginx configuration
|
```nginx configuration
|
||||||
location /cgi-bin/gettoken {
|
location /cgi-bin/gettoken {
|
||||||
|
@ -90,7 +90,7 @@ def movie_top250(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
浏览豆瓣剧集信息
|
浏览豆瓣剧集信息
|
||||||
"""
|
"""
|
||||||
movies = DoubanChain().movie_top250(page=page, count=count)
|
movies = DoubanChain().movie_top250(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
|
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ def tv_weekly_chinese(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
中国每周剧集口碑榜
|
中国每周剧集口碑榜
|
||||||
"""
|
"""
|
||||||
tvs = DoubanChain().tv_weekly_chinese(page=page, count=count)
|
tvs = DoubanChain().tv_weekly_chinese(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
||||||
|
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ def tv_weekly_global(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
全球每周剧集口碑榜
|
全球每周剧集口碑榜
|
||||||
"""
|
"""
|
||||||
tvs = DoubanChain().tv_weekly_global(page=page, count=count)
|
tvs = DoubanChain().tv_weekly_global(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
||||||
|
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ def tv_animation(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
热门动画剧集
|
热门动画剧集
|
||||||
"""
|
"""
|
||||||
tvs = DoubanChain().tv_animation(page=page, count=count)
|
tvs = DoubanChain().tv_animation(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
||||||
|
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ def movie_hot(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
热门电影
|
热门电影
|
||||||
"""
|
"""
|
||||||
movies = DoubanChain().movie_hot(page=page, count=count)
|
movies = DoubanChain().movie_hot(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
|
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ def tv_hot(page: int = 1,
|
|||||||
"""
|
"""
|
||||||
热门电视剧
|
热门电视剧
|
||||||
"""
|
"""
|
||||||
tvs = DoubanChain().tv_hot(page=page, count=count)
|
tvs = DoubanChain().tv_hot(page=page, count=count) or []
|
||||||
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,20 +113,6 @@ def media_info(mediaid: str, type_name: str,
|
|||||||
doubanid = mediaid[7:]
|
doubanid = mediaid[7:]
|
||||||
if not tmdbid and not doubanid:
|
if not tmdbid and not doubanid:
|
||||||
return schemas.MediaInfo()
|
return schemas.MediaInfo()
|
||||||
if settings.RECOGNIZE_SOURCE == "themoviedb":
|
|
||||||
if not tmdbid and doubanid:
|
|
||||||
tmdbinfo = MediaChain().get_tmdbinfo_by_doubanid(doubanid=doubanid, mtype=mtype)
|
|
||||||
if tmdbinfo:
|
|
||||||
tmdbid = tmdbinfo.get("id")
|
|
||||||
else:
|
|
||||||
return schemas.MediaInfo()
|
|
||||||
else:
|
|
||||||
if not doubanid and tmdbid:
|
|
||||||
doubaninfo = MediaChain().get_doubaninfo_by_tmdbid(tmdbid=tmdbid, mtype=mtype)
|
|
||||||
if doubaninfo:
|
|
||||||
doubanid = doubaninfo.get("id")
|
|
||||||
else:
|
|
||||||
return schemas.MediaInfo()
|
|
||||||
mediainfo = MediaChain().recognize_media(tmdbid=tmdbid, doubanid=doubanid, mtype=mtype)
|
mediainfo = MediaChain().recognize_media(tmdbid=tmdbid, doubanid=doubanid, mtype=mtype)
|
||||||
if mediainfo:
|
if mediainfo:
|
||||||
MediaChain().obtain_images(mediainfo)
|
MediaChain().obtain_images(mediainfo)
|
||||||
|
@ -8,11 +8,13 @@ from app import schemas
|
|||||||
from app.chain.message import MessageChain
|
from app.chain.message import MessageChain
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.core.security import verify_token
|
from app.core.security import verify_token
|
||||||
|
from app.db.models import User
|
||||||
from app.db.systemconfig_oper import SystemConfigOper
|
from app.db.systemconfig_oper import SystemConfigOper
|
||||||
|
from app.db.userauth import get_current_active_superuser
|
||||||
from app.log import logger
|
from app.log import logger
|
||||||
from app.modules.wechat.WXBizMsgCrypt3 import WXBizMsgCrypt
|
from app.modules.wechat.WXBizMsgCrypt3 import WXBizMsgCrypt
|
||||||
from app.schemas import NotificationSwitch
|
from app.schemas import NotificationSwitch
|
||||||
from app.schemas.types import SystemConfigKey, NotificationType
|
from app.schemas.types import SystemConfigKey, NotificationType, MessageChannel
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@ -36,6 +38,20 @@ async def user_message(background_tasks: BackgroundTasks, request: Request):
|
|||||||
return schemas.Response(success=True)
|
return schemas.Response(success=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/web", summary="接收WEB消息", response_model=schemas.Response)
|
||||||
|
async def web_message(text: str, current_user: User = Depends(get_current_active_superuser)):
|
||||||
|
"""
|
||||||
|
WEB消息响应
|
||||||
|
"""
|
||||||
|
MessageChain().handle_message(
|
||||||
|
channel=MessageChannel.Web,
|
||||||
|
userid=current_user.id,
|
||||||
|
username=current_user.name,
|
||||||
|
text=text
|
||||||
|
)
|
||||||
|
return schemas.Response(success=True)
|
||||||
|
|
||||||
|
|
||||||
def wechat_verify(echostr: str, msg_signature: str,
|
def wechat_verify(echostr: str, msg_signature: str,
|
||||||
timestamp: Union[str, int], nonce: str) -> Any:
|
timestamp: Union[str, int], nonce: str) -> Any:
|
||||||
"""
|
"""
|
||||||
@ -103,7 +119,7 @@ def read_switchs(_: schemas.TokenPayload = Depends(verify_token)) -> Any:
|
|||||||
def set_switchs(switchs: List[NotificationSwitch],
|
def set_switchs(switchs: List[NotificationSwitch],
|
||||||
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
|
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
|
||||||
"""
|
"""
|
||||||
查询通知消息渠道开关
|
设置通知消息渠道开关
|
||||||
"""
|
"""
|
||||||
switch_list = []
|
switch_list = []
|
||||||
for switch in switchs:
|
for switch in switchs:
|
||||||
|
@ -138,7 +138,7 @@ def set_setting(key: str, value: Union[list, dict, bool, int, str] = None,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/message", summary="实时消息")
|
@router.get("/message", summary="实时消息")
|
||||||
def get_message(token: str):
|
def get_message(token: str, role: str = "sys"):
|
||||||
"""
|
"""
|
||||||
实时获取系统消息,返回格式为SSE
|
实时获取系统消息,返回格式为SSE
|
||||||
"""
|
"""
|
||||||
@ -152,7 +152,7 @@ def get_message(token: str):
|
|||||||
|
|
||||||
def event_generator():
|
def event_generator():
|
||||||
while True:
|
while True:
|
||||||
detail = message.get()
|
detail = message.get(role)
|
||||||
yield 'data: %s\n\n' % (detail or '')
|
yield 'data: %s\n\n' % (detail or '')
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ from app.core.context import MediaInfo, TorrentInfo
|
|||||||
from app.core.event import EventManager
|
from app.core.event import EventManager
|
||||||
from app.core.meta import MetaBase
|
from app.core.meta import MetaBase
|
||||||
from app.core.module import ModuleManager
|
from app.core.module import ModuleManager
|
||||||
|
from app.db.message_oper import MessageOper
|
||||||
|
from app.helper.message import MessageHelper
|
||||||
from app.log import logger
|
from app.log import logger
|
||||||
from app.schemas import TransferInfo, TransferTorrent, ExistMediaInfo, DownloadingTorrent, CommingMessage, Notification, \
|
from app.schemas import TransferInfo, TransferTorrent, ExistMediaInfo, DownloadingTorrent, CommingMessage, Notification, \
|
||||||
WebhookEventInfo, TmdbEpisode
|
WebhookEventInfo, TmdbEpisode
|
||||||
@ -33,6 +35,8 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
"""
|
"""
|
||||||
self.modulemanager = ModuleManager()
|
self.modulemanager = ModuleManager()
|
||||||
self.eventmanager = EventManager()
|
self.eventmanager = EventManager()
|
||||||
|
self.messageoper = MessageOper()
|
||||||
|
self.messagehelper = MessageHelper()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_cache(filename: str) -> Any:
|
def load_cache(filename: str) -> Any:
|
||||||
@ -403,6 +407,10 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
:param message: 消息体
|
:param message: 消息体
|
||||||
:return: 成功或失败
|
:return: 成功或失败
|
||||||
"""
|
"""
|
||||||
|
logger.info(f"发送消息:channel={message.channel},"
|
||||||
|
f"title={message.title}, "
|
||||||
|
f"text={message.text},"
|
||||||
|
f"userid={message.userid}")
|
||||||
# 发送事件
|
# 发送事件
|
||||||
self.eventmanager.send_event(etype=EventType.NoticeMessage,
|
self.eventmanager.send_event(etype=EventType.NoticeMessage,
|
||||||
data={
|
data={
|
||||||
@ -413,10 +421,13 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
"image": message.image,
|
"image": message.image,
|
||||||
"userid": message.userid,
|
"userid": message.userid,
|
||||||
})
|
})
|
||||||
logger.info(f"发送消息:channel={message.channel},"
|
# 保存消息
|
||||||
f"title={message.title}, "
|
self.messagehelper.put(message, role="user")
|
||||||
f"text={message.text},"
|
self.messageoper.add(channel=message.channel, mtype=message.mtype,
|
||||||
f"userid={message.userid}")
|
title=message.title, text=message.text,
|
||||||
|
image=message.image, link=message.link,
|
||||||
|
userid=message.userid, action=1)
|
||||||
|
# 发送
|
||||||
self.run_module("post_message", message=message)
|
self.run_module("post_message", message=message)
|
||||||
|
|
||||||
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> Optional[bool]:
|
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> Optional[bool]:
|
||||||
|
@ -12,9 +12,11 @@ from app.core.config import settings
|
|||||||
from app.core.context import MediaInfo, Context
|
from app.core.context import MediaInfo, Context
|
||||||
from app.core.event import EventManager
|
from app.core.event import EventManager
|
||||||
from app.core.meta import MetaBase
|
from app.core.meta import MetaBase
|
||||||
|
from app.db.message_oper import MessageOper
|
||||||
|
from app.helper.message import MessageHelper
|
||||||
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 Notification, NotExistMediaInfo
|
from app.schemas import Notification, NotExistMediaInfo, CommingMessage
|
||||||
from app.schemas.types import EventType, MessageChannel, MediaType
|
from app.schemas.types import EventType, MessageChannel, MediaType
|
||||||
from app.utils.string import StringUtils
|
from app.utils.string import StringUtils
|
||||||
|
|
||||||
@ -43,6 +45,8 @@ class MessageChain(ChainBase):
|
|||||||
self.mediachain = MediaChain()
|
self.mediachain = MediaChain()
|
||||||
self.eventmanager = EventManager()
|
self.eventmanager = EventManager()
|
||||||
self.torrenthelper = TorrentHelper()
|
self.torrenthelper = TorrentHelper()
|
||||||
|
self.messagehelper = MessageHelper()
|
||||||
|
self.messageoper = MessageOper()
|
||||||
|
|
||||||
def __get_noexits_info(
|
def __get_noexits_info(
|
||||||
self,
|
self,
|
||||||
@ -100,10 +104,8 @@ class MessageChain(ChainBase):
|
|||||||
|
|
||||||
def process(self, body: Any, form: Any, args: Any) -> None:
|
def process(self, body: Any, form: Any, args: Any) -> None:
|
||||||
"""
|
"""
|
||||||
识别消息内容,执行操作
|
调用模块识别消息内容
|
||||||
"""
|
"""
|
||||||
# 申明全局变量
|
|
||||||
global _current_page, _current_meta, _current_media
|
|
||||||
# 获取消息内容
|
# 获取消息内容
|
||||||
info = self.message_parser(body=body, form=form, args=args)
|
info = self.message_parser(body=body, form=form, args=args)
|
||||||
if not info:
|
if not info:
|
||||||
@ -122,10 +124,35 @@ class MessageChain(ChainBase):
|
|||||||
if not text:
|
if not text:
|
||||||
logger.debug(f'未识别到消息内容::{body}{form}{args}')
|
logger.debug(f'未识别到消息内容::{body}{form}{args}')
|
||||||
return
|
return
|
||||||
|
# 处理消息
|
||||||
|
self.handle_message(channel=channel, userid=userid, username=username, text=text)
|
||||||
|
|
||||||
|
def handle_message(self, channel: MessageChannel, userid: Union[str, int], username: str, text: str) -> None:
|
||||||
|
"""
|
||||||
|
识别消息内容,执行操作
|
||||||
|
"""
|
||||||
|
# 申明全局变量
|
||||||
|
global _current_page, _current_meta, _current_media
|
||||||
# 加载缓存
|
# 加载缓存
|
||||||
user_cache: Dict[str, dict] = self.load_cache(self._cache_file) or {}
|
user_cache: Dict[str, dict] = self.load_cache(self._cache_file) or {}
|
||||||
# 处理消息
|
# 处理消息
|
||||||
logger.info(f'收到用户消息内容,用户:{userid},内容:{text}')
|
logger.info(f'收到用户消息内容,用户:{userid},内容:{text}')
|
||||||
|
# 保存消息
|
||||||
|
self.messagehelper.put(
|
||||||
|
CommingMessage(
|
||||||
|
userid=userid,
|
||||||
|
username=username,
|
||||||
|
channel=channel,
|
||||||
|
text=text
|
||||||
|
), role="user")
|
||||||
|
self.messageoper.add(
|
||||||
|
channel=channel,
|
||||||
|
userid=userid,
|
||||||
|
username=username,
|
||||||
|
text=text,
|
||||||
|
action=0
|
||||||
|
)
|
||||||
|
# 处理消息
|
||||||
if text.startswith('/'):
|
if text.startswith('/'):
|
||||||
# 执行命令
|
# 执行命令
|
||||||
self.eventmanager.send_event(
|
self.eventmanager.send_event(
|
||||||
|
@ -124,14 +124,12 @@ class SearchChain(ChainBase):
|
|||||||
if keyword:
|
if keyword:
|
||||||
keywords = [keyword]
|
keywords = [keyword]
|
||||||
else:
|
else:
|
||||||
keywords = list(
|
# 去重去空,但要保持顺序
|
||||||
{
|
keywords = list(dict.fromkeys([k for k in [mediainfo.title,
|
||||||
mediainfo.title,
|
|
||||||
mediainfo.original_title,
|
mediainfo.original_title,
|
||||||
mediainfo.en_title,
|
mediainfo.en_title,
|
||||||
mediainfo.sg_title
|
mediainfo.sg_title] if k]))
|
||||||
} - {None}
|
|
||||||
)
|
|
||||||
# 执行搜索
|
# 执行搜索
|
||||||
torrents: List[TorrentInfo] = self.__search_all_sites(
|
torrents: List[TorrentInfo] = self.__search_all_sites(
|
||||||
mediainfo=mediainfo,
|
mediainfo=mediainfo,
|
||||||
|
@ -302,6 +302,8 @@ class SiteChain(ChainBase):
|
|||||||
if not site_info:
|
if not site_info:
|
||||||
return False, f"站点【{url}】不存在"
|
return False, f"站点【{url}】不存在"
|
||||||
|
|
||||||
|
# 模拟登录
|
||||||
|
try:
|
||||||
# 特殊站点测试
|
# 特殊站点测试
|
||||||
if self.special_site_test.get(domain):
|
if self.special_site_test.get(domain):
|
||||||
return self.special_site_test[domain](site_info)
|
return self.special_site_test[domain](site_info)
|
||||||
@ -314,8 +316,7 @@ class SiteChain(ChainBase):
|
|||||||
public = site_info.public
|
public = site_info.public
|
||||||
proxies = settings.PROXY if site_info.proxy else None
|
proxies = settings.PROXY if site_info.proxy else None
|
||||||
proxy_server = settings.PROXY_SERVER if site_info.proxy else None
|
proxy_server = settings.PROXY_SERVER if site_info.proxy else None
|
||||||
# 模拟登录
|
|
||||||
try:
|
|
||||||
# 访问链接
|
# 访问链接
|
||||||
if render:
|
if render:
|
||||||
page_source = PlaywrightHelper().get_page_source(url=site_url,
|
page_source = PlaywrightHelper().get_page_source(url=site_url,
|
||||||
|
57
app/db/message_oper.py
Normal file
57
app/db/message_oper.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import time
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.db import DbOper
|
||||||
|
from app.db.models.message import Message
|
||||||
|
from app.schemas import MessageChannel, NotificationType
|
||||||
|
|
||||||
|
|
||||||
|
class MessageOper(DbOper):
|
||||||
|
"""
|
||||||
|
消息数据管理
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, db: Session = None):
|
||||||
|
super().__init__(db)
|
||||||
|
|
||||||
|
def add(self,
|
||||||
|
channel: MessageChannel = None,
|
||||||
|
mtype: NotificationType = None,
|
||||||
|
title: str = None,
|
||||||
|
text: str = None,
|
||||||
|
image: str = None,
|
||||||
|
link: str = None,
|
||||||
|
userid: str = None,
|
||||||
|
action: int = 1,
|
||||||
|
**kwargs):
|
||||||
|
"""
|
||||||
|
新增媒体服务器数据
|
||||||
|
:param channel: 消息渠道
|
||||||
|
:param mtype: 消息类型
|
||||||
|
:param title: 标题
|
||||||
|
:param text: 文本内容
|
||||||
|
:param image: 图片
|
||||||
|
:param link: 链接
|
||||||
|
:param userid: 用户ID
|
||||||
|
:param action: 消息方向:0-接收息,1-发送消息
|
||||||
|
"""
|
||||||
|
kwargs.update({
|
||||||
|
"channel": channel.value if channel else '',
|
||||||
|
"mtype": mtype.value if mtype else '',
|
||||||
|
"title": title,
|
||||||
|
"text": text,
|
||||||
|
"image": image,
|
||||||
|
"link": link,
|
||||||
|
"userid": userid,
|
||||||
|
"action": action,
|
||||||
|
"reg_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
|
})
|
||||||
|
Message(**kwargs).create(self._db)
|
||||||
|
|
||||||
|
def list_by_page(self, page: int = 1, count: int = 30) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取媒体服务器数据ID
|
||||||
|
"""
|
||||||
|
return Message.list_by_page(self._db, page, count)
|
@ -200,6 +200,7 @@ class DownloadFiles(Base):
|
|||||||
result = db.query(DownloadFiles).filter(DownloadFiles.savepath == savepath).all()
|
result = db.query(DownloadFiles).filter(DownloadFiles.savepath == savepath).all()
|
||||||
return list(result)
|
return list(result)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
@db_update
|
@db_update
|
||||||
def delete_by_fullpath(db: Session, fullpath: str):
|
def delete_by_fullpath(db: Session, fullpath: str):
|
||||||
db.query(DownloadFiles).filter(DownloadFiles.fullpath == fullpath,
|
db.query(DownloadFiles).filter(DownloadFiles.fullpath == fullpath,
|
||||||
|
36
app/db/models/message.py
Normal file
36
app/db/models/message.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from sqlalchemy import Column, Integer, String, Sequence
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.db import db_query, Base
|
||||||
|
|
||||||
|
|
||||||
|
class Message(Base):
|
||||||
|
"""
|
||||||
|
消息表
|
||||||
|
"""
|
||||||
|
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
||||||
|
# 消息渠道
|
||||||
|
channel = Column(String, nullable=False)
|
||||||
|
# 消息类型
|
||||||
|
mtype = Column(String, nullable=False)
|
||||||
|
# 标题
|
||||||
|
title = Column(String)
|
||||||
|
# 文本内容
|
||||||
|
text = Column(String)
|
||||||
|
# 图片
|
||||||
|
image = Column(String)
|
||||||
|
# 链接
|
||||||
|
link = Column(String)
|
||||||
|
# 用户ID
|
||||||
|
userid = Column(String)
|
||||||
|
# 登记时间
|
||||||
|
reg_time = Column(String)
|
||||||
|
# 消息方向:0-接收息,1-发送消息
|
||||||
|
action = Column(Integer)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@db_query
|
||||||
|
def list_by_page(db: Session, page: int = 1, count: int = 30):
|
||||||
|
result = db.query(Message).order_by(Message.reg_time.desc()).offset((page - 1) * count).limit(
|
||||||
|
count).all()
|
||||||
|
return list(result)
|
@ -1,19 +1,41 @@
|
|||||||
|
import json
|
||||||
import queue
|
import queue
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
from app.utils.singleton import Singleton
|
from app.utils.singleton import Singleton
|
||||||
|
|
||||||
|
|
||||||
class MessageHelper(metaclass=Singleton):
|
class MessageHelper(metaclass=Singleton):
|
||||||
"""
|
"""
|
||||||
消息队列管理器
|
消息队列管理器,包括系统消息和用户消息
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.queue = queue.Queue()
|
self.sys_queue = queue.Queue()
|
||||||
|
self.user_queue = queue.Queue()
|
||||||
|
|
||||||
def put(self, message: str):
|
def put(self, message: Any, role: str = "sys"):
|
||||||
self.queue.put(message)
|
"""
|
||||||
|
存消息
|
||||||
|
:param message: 消息
|
||||||
|
:param role: 消息通道 sys/user
|
||||||
|
"""
|
||||||
|
if role == "sys":
|
||||||
|
self.sys_queue.put(message)
|
||||||
|
else:
|
||||||
|
if isinstance(message, str):
|
||||||
|
self.user_queue.put(message)
|
||||||
|
elif hasattr(message, "dict"):
|
||||||
|
self.user_queue.put(json.dumps(message.dict()))
|
||||||
|
|
||||||
def get(self):
|
def get(self, role: str = "sys") -> Optional[str]:
|
||||||
if not self.queue.empty():
|
"""
|
||||||
return self.queue.get(block=False)
|
取消息
|
||||||
|
:param role: 消息通道 sys/user
|
||||||
|
"""
|
||||||
|
if role == "sys":
|
||||||
|
if not self.sys_queue.empty():
|
||||||
|
return self.sys_queue.get(block=False)
|
||||||
|
else:
|
||||||
|
if not self.user_queue.empty():
|
||||||
|
return self.user_queue.get(block=False)
|
||||||
return None
|
return None
|
||||||
|
@ -57,7 +57,11 @@ class DoubanModule(_ModuleBase):
|
|||||||
:param cache: 是否使用缓存
|
:param cache: 是否使用缓存
|
||||||
:return: 识别的媒体信息,包括剧集信息
|
:return: 识别的媒体信息,包括剧集信息
|
||||||
"""
|
"""
|
||||||
if settings.RECOGNIZE_SOURCE != "douban":
|
if not doubanid and not meta:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if meta and not doubanid \
|
||||||
|
and settings.RECOGNIZE_SOURCE != "douban":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not meta:
|
if not meta:
|
||||||
|
@ -38,12 +38,12 @@ class FileTransferModule(_ModuleBase):
|
|||||||
for path in [settings.DOWNLOAD_PATH,
|
for path in [settings.DOWNLOAD_PATH,
|
||||||
settings.DOWNLOAD_MOVIE_PATH,
|
settings.DOWNLOAD_MOVIE_PATH,
|
||||||
settings.DOWNLOAD_TV_PATH,
|
settings.DOWNLOAD_TV_PATH,
|
||||||
settings.DWONLOAD_ANIME_PATH]:
|
settings.DOWNLOAD_ANIME_PATH]:
|
||||||
if not path:
|
if not path:
|
||||||
continue
|
continue
|
||||||
download_path = Path(path)
|
download_path = Path(path)
|
||||||
if not download_path.exists():
|
if not download_path.exists():
|
||||||
return False, f"目录 {download_path} 不存在"
|
return False, f"下载目录 {download_path} 不存在"
|
||||||
download_paths.append(path)
|
download_paths.append(path)
|
||||||
# 下载目录的设备ID
|
# 下载目录的设备ID
|
||||||
download_devids = [Path(path).stat().st_dev for path in download_paths]
|
download_devids = [Path(path).stat().st_dev for path in download_paths]
|
||||||
@ -54,7 +54,7 @@ class FileTransferModule(_ModuleBase):
|
|||||||
for path in settings.LIBRARY_PATHS:
|
for path in settings.LIBRARY_PATHS:
|
||||||
library_path = Path(path)
|
library_path = Path(path)
|
||||||
if not library_path.exists():
|
if not library_path.exists():
|
||||||
return False, f"目录不存在:{library_path}"
|
return False, f"媒体库目录不存在:{library_path}"
|
||||||
if settings.DOWNLOADER_MONITOR and settings.TRANSFER_TYPE == "link":
|
if settings.DOWNLOADER_MONITOR and settings.TRANSFER_TYPE == "link":
|
||||||
if library_path.stat().st_dev not in download_devids:
|
if library_path.stat().st_dev not in download_devids:
|
||||||
return False, f"媒体库目录 {library_path} " \
|
return False, f"媒体库目录 {library_path} " \
|
||||||
|
@ -67,7 +67,11 @@ class TheMovieDbModule(_ModuleBase):
|
|||||||
:param cache: 是否使用缓存
|
:param cache: 是否使用缓存
|
||||||
:return: 识别的媒体信息,包括剧集信息
|
:return: 识别的媒体信息,包括剧集信息
|
||||||
"""
|
"""
|
||||||
if settings.RECOGNIZE_SOURCE != "themoviedb":
|
if not tmdbid and not meta:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if meta and not tmdbid \
|
||||||
|
and settings.RECOGNIZE_SOURCE != "themoviedb":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not meta:
|
if not meta:
|
||||||
@ -182,7 +186,7 @@ class TheMovieDbModule(_ModuleBase):
|
|||||||
:param season: 季号
|
:param season: 季号
|
||||||
"""
|
"""
|
||||||
# 搜索
|
# 搜索
|
||||||
logger.info(f"开始使用 名称:{name}、年份:{year} 匹配TMDB信息 ...")
|
logger.info(f"开始使用 名称:{name} 年份:{year} 匹配TMDB信息 ...")
|
||||||
info = self.tmdb.match(name=name,
|
info = self.tmdb.match(name=name,
|
||||||
year=year,
|
year=year,
|
||||||
mtype=mtype,
|
mtype=mtype,
|
||||||
|
@ -189,9 +189,16 @@ class TmdbHelper:
|
|||||||
season_year,
|
season_year,
|
||||||
season_number)
|
season_number)
|
||||||
if not info:
|
if not info:
|
||||||
|
year_range = [year]
|
||||||
|
if year:
|
||||||
|
year_range.append(str(int(year) + 1))
|
||||||
|
year_range.append(str(int(year) - 1))
|
||||||
|
for year in year_range:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"正在识别{mtype.value}:{name}, 年份={year} ...")
|
f"正在识别{mtype.value}:{name}, 年份={year} ...")
|
||||||
info = self.__search_tv_by_name(name, year)
|
info = self.__search_tv_by_name(name, year)
|
||||||
|
if info:
|
||||||
|
break
|
||||||
if info:
|
if info:
|
||||||
info['media_type'] = MediaType.TV
|
info['media_type'] = MediaType.TV
|
||||||
# 返回
|
# 返回
|
||||||
|
@ -18,6 +18,18 @@ class CommingMessage(BaseModel):
|
|||||||
# 消息体
|
# 消息体
|
||||||
text: Optional[str] = None
|
text: Optional[str] = None
|
||||||
|
|
||||||
|
def dict(self):
|
||||||
|
"""
|
||||||
|
转换为字典
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"userid": self.userid,
|
||||||
|
"username": self.username,
|
||||||
|
"channel": self.channel.value if self.channel else None,
|
||||||
|
"text": self.text,
|
||||||
|
"action": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Notification(BaseModel):
|
class Notification(BaseModel):
|
||||||
"""
|
"""
|
||||||
@ -38,6 +50,18 @@ class Notification(BaseModel):
|
|||||||
# 用户ID
|
# 用户ID
|
||||||
userid: Optional[Union[str, int]] = None
|
userid: Optional[Union[str, int]] = None
|
||||||
|
|
||||||
|
def dict(self):
|
||||||
|
return {
|
||||||
|
"channel": self.channel.value if self.channel else None,
|
||||||
|
"mtype": self.mtype.value if self.mtype else None,
|
||||||
|
"title": self.title,
|
||||||
|
"text": self.text,
|
||||||
|
"image": self.image,
|
||||||
|
"link": self.link,
|
||||||
|
"userid": self.userid,
|
||||||
|
"action": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NotificationSwitch(BaseModel):
|
class NotificationSwitch(BaseModel):
|
||||||
"""
|
"""
|
||||||
|
@ -117,3 +117,4 @@ class MessageChannel(Enum):
|
|||||||
Slack = "Slack"
|
Slack = "Slack"
|
||||||
SynologyChat = "SynologyChat"
|
SynologyChat = "SynologyChat"
|
||||||
VoceChat = "VoceChat"
|
VoceChat = "VoceChat"
|
||||||
|
Web = "Web"
|
||||||
|
@ -1 +1 @@
|
|||||||
APP_VERSION = 'v1.7.1'
|
APP_VERSION = 'v1.7.2'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user