Files
archived-MoviePilot-Plugins/plugins.v2/homepage/__init__.py
2024-10-21 15:36:21 +08:00

649 lines
30 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
from app.chain.dashboard import DashboardChain
from app.core.config import settings
from app.db.subscribe_oper import SubscribeOper
from app.helper.directory import DirectoryHelper
from app.plugins import _PluginBase
from typing import Any, List, Dict, Tuple, Optional
from app.schemas import NotificationType
from app import schemas
from app.utils.string import StringUtils
from app.utils.system import SystemUtils
class HomePage(_PluginBase):
# 插件名称
plugin_name = "HomePage"
# 插件描述
plugin_desc = "HomePage自定义API。"
# 插件图标
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/homepage.png"
# 插件版本
plugin_version = "1.3"
# 插件作者
plugin_author = "thsrite"
# 作者主页
author_url = "https://github.com/thsrite"
# 插件配置项ID前缀
plugin_config_prefix = "homepage_"
# 加载顺序
plugin_order = 30
# 可使用的用户级别
auth_level = 1
# 任务执行间隔
_enabled = False
def init_plugin(self, config: dict = None):
if config:
self._enabled = config.get("enabled")
def get_state(self) -> bool:
return self._enabled
def statistic(self, apikey: str) -> Any:
"""
订阅、剩余空间等信息
"""
if apikey != settings.API_TOKEN:
return schemas.Response(success=False, message="API密钥错误")
# 媒体统计
movie_count = 0
tv_count = 0
episode_count = 0
user_count = 0
media_statistics: Optional[List[schemas.Statistic]] = DashboardChain().media_statistic()
if media_statistics:
# 汇总各媒体库统计信息
for media_statistic in media_statistics:
movie_count += media_statistic.movie_count
tv_count += media_statistic.tv_count
episode_count += media_statistic.episode_count
user_count += media_statistic.user_count
# 磁盘统计
library_dirs = DirectoryHelper().get_download_dirs()
total_storage, free_storage = SystemUtils.space_usage([Path(d.download_path) for d in library_dirs if d.download_path])
# 订阅统计
movie_subscribes = 0
tv_subscribes = 0
subscribes = SubscribeOper().list()
for subscribe in subscribes:
if str(subscribe.type) == '电影':
movie_subscribes += 1
else:
tv_subscribes += 1
return {
'movie_count': movie_count,
'tv_count': tv_count,
'episode_count': episode_count,
'user_count': user_count,
'total_storage': StringUtils.str_filesize(total_storage),
'free_storage': StringUtils.str_filesize(free_storage),
'used_storage': StringUtils.str_filesize(total_storage - free_storage),
'movie_subscribes': movie_subscribes,
'tv_subscribes': tv_subscribes,
}
@staticmethod
def get_command() -> List[Dict[str, Any]]:
pass
def get_api(self) -> List[Dict[str, Any]]:
"""
获取插件API
[{
"path": "/xx",
"endpoint": self.xxx,
"methods": ["GET", "POST"],
"summary": "API说明"
}]
"""
return [{
"path": "/statistic",
"endpoint": self.statistic,
"methods": ["GET"],
"summary": "数据统计",
"description": "订阅数量等统计数量",
}]
def get_form(self) -> Tuple[List[dict], Dict[str, Any]]:
"""
拼装插件配置页面需要返回两块数据1、页面配置2、数据结构
"""
# 编历 NotificationType 枚举,生成消息类型选项
MsgTypeOptions = []
for item in NotificationType:
MsgTypeOptions.append({
"title": item.value,
"value": item.name
})
return [
{
'component': 'VForm',
'content': [
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'enabled',
'label': '启用插件',
}
}
]
},
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
},
'content': [
{
'component': 'VAlert',
'props': {
'type': 'success',
'variant': 'tonal'
},
'content': [
{
'component': 'span',
'text': '配置教程请参考:'
},
{
'component': 'a',
'props': {
'href': 'https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/docs/HomePage.md',
'target': '_blank'
},
'text': 'https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/docs/HomePage.md'
}
]
}
]
}
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
},
'content': [
{
'component': 'VAlert',
'props': {
'type': 'info',
'variant': 'tonal',
'text': '如安装完启用插件后HomePage提示404重启MoviePilot即可。'
}
}
]
}
]
}
]
}
], {
"enabled": False,
}
def get_page(self) -> List[dict]:
dict = self.statistic(settings.API_TOKEN)
# 拼装页面
return [
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '电影订阅'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('movie_subscribes')
}
]
}
]
}
]
}
]
},
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '电视剧订阅'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('tv_subscribes')
}
]
}
]
}
]
}
]
},
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '总空间'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('total_storage')
}
]
}
]
}
]
}
]
},
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '剩余空间'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('free_storage')
}
]
}
]
}
]
}
]
},
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '电影数量'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('movie_count')
}
]
}
]
}
]
}
]
},
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '电视剧数量'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('tv_count')
}
]
}
]
}
]
}
]
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '电影剧集数量'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('episode_count')
}
]
}
]
}
]
}
]
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3,
'sm': 6
},
'content': [
{
'component': 'VCard',
'props': {
'variant': 'tonal',
},
'content': [
{
'component': 'VCardText',
'props': {
'class': 'd-flex align-center',
},
'content': [
{
'component': 'div',
'content': [
{
'component': 'span',
'props': {
'class': 'text-caption'
},
'text': '用户数量'
},
{
'component': 'div',
'props': {
'class': 'd-flex align-center flex-wrap'
},
'content': [
{
'component': 'span',
'props': {
'class': 'text-h6'
},
'text': dict.get('user_count')
}
]
}
]
}
]
}
]
}
]
}
]
}]
def stop_service(self):
"""
退出插件
"""
pass