mirror of
https://github.com/wushuo894/ani-rss.git
synced 2026-03-15 01:20:23 +00:00
初步优化通知
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||

|
||||
[](https://github.com/wushuo894/ani-rss/releases/latest)
|
||||
[](https://docs.wushuo.top/history)
|
||||
[](https://t.me/ani_rss)
|
||||
[](https://t.me/ani_rss)
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -131,12 +131,6 @@ verify_install() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# sleep 10
|
||||
# if ! ss -tulnp | grep -q ":$PORT"; then
|
||||
# echo -e "${RED}端口 $PORT 未监听${NC}"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
echo -e "${GREEN}验证通过,服务运行正常${NC}"
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class BgmAction implements BaseAction {
|
||||
case "getAniBySubjectId" -> {
|
||||
String id = request.getParam("id");
|
||||
BgmInfo bgmInfo = BgmUtil.getBgmInfo(id, true);
|
||||
Ani ani = BgmUtil.toAni(bgmInfo, Ani.bulidAni());
|
||||
Ani ani = BgmUtil.toAni(bgmInfo, Ani.createAni());
|
||||
ani
|
||||
.setCustomDownloadPath(true);
|
||||
resultSuccess(ani);
|
||||
|
||||
@@ -7,7 +7,6 @@ import ani.rss.util.AniUtil;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.util.FilePathUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
|
||||
@@ -12,7 +12,6 @@ import cn.hutool.http.server.HttpServerResponse;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ package ani.rss.action;
|
||||
|
||||
import ani.rss.annotation.Auth;
|
||||
import ani.rss.annotation.Path;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.EmbyViews;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.util.EmbyUtil;
|
||||
import cn.hutool.http.server.HttpServerRequest;
|
||||
import cn.hutool.http.server.HttpServerResponse;
|
||||
@@ -21,18 +20,17 @@ public class EmbyAction implements BaseAction {
|
||||
|
||||
@Override
|
||||
public void doAction(HttpServerRequest request, HttpServerResponse response) throws IOException {
|
||||
Config config = getBody(Config.class);
|
||||
ConfigUtil.format(config);
|
||||
NotificationConfig notificationConfig = getBody(NotificationConfig.class);
|
||||
String type = request.getParam("type");
|
||||
|
||||
if (type.equals("getViews")) {
|
||||
List<EmbyViews> views = EmbyUtil.getViews(config);
|
||||
List<EmbyViews> views = EmbyUtil.getViews(notificationConfig);
|
||||
resultSuccess(views);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.equals("refresh")) {
|
||||
EmbyUtil.refresh(config);
|
||||
EmbyUtil.refresh(notificationConfig);
|
||||
resultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,14 @@ import ani.rss.annotation.Auth;
|
||||
import ani.rss.annotation.Path;
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.BgmInfo;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.entity.Tmdb;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.msg.Message;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.NotificationTypeEnum;
|
||||
import ani.rss.notification.BaseNotification;
|
||||
import ani.rss.util.AniUtil;
|
||||
import ani.rss.util.BgmUtil;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.server.HttpServerRequest;
|
||||
import cn.hutool.http.server.HttpServerResponse;
|
||||
|
||||
@@ -24,20 +22,32 @@ import java.util.Date;
|
||||
* 通知
|
||||
*/
|
||||
@Auth
|
||||
@Path("/message")
|
||||
public class MessageAction implements BaseAction {
|
||||
@Path("/notification")
|
||||
public class NotificationAction implements BaseAction {
|
||||
@Override
|
||||
public void doAction(HttpServerRequest request, HttpServerResponse response) throws IOException {
|
||||
String s = request.getParam("type");
|
||||
if (StrUtil.isBlank(s)) {
|
||||
resultError();
|
||||
String type = request.getParam("type");
|
||||
if ("test".equals(type)) {
|
||||
test();
|
||||
return;
|
||||
}
|
||||
Config config = getBody(Config.class);
|
||||
ConfigUtil.format(config);
|
||||
Class<Object> loadClass = ClassUtil.loadClass("ani.rss.msg." + s);
|
||||
Message message = (Message) ReflectUtil.newInstance(loadClass);
|
||||
Ani ani = Ani.bulidAni();
|
||||
|
||||
if ("add".equals(type)) {
|
||||
add();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void add() {
|
||||
NotificationConfig notificationConfig = NotificationConfig.createNotificationConfig();
|
||||
resultSuccess(notificationConfig);
|
||||
}
|
||||
|
||||
private void test() {
|
||||
NotificationConfig notificationConfig = getBody(NotificationConfig.class);
|
||||
NotificationTypeEnum notificationType = notificationConfig.getNotificationType();
|
||||
BaseNotification baseNotification = ReflectUtil.newInstance(notificationType.getAClass());
|
||||
Ani ani = Ani.createAni();
|
||||
ani.setBgmUrl("https://bgm.tv/subject/424883");
|
||||
BgmInfo bgmInfo = BgmUtil.getBgmInfo(ani);
|
||||
String image = bgmInfo.getImage();
|
||||
@@ -57,11 +67,12 @@ public class MessageAction implements BaseAction {
|
||||
.setName("不时用俄语小声说真心话的邻桌艾莉同学")
|
||||
.setDate(new Date())
|
||||
);
|
||||
Boolean test = message.send(config, ani, "test", MessageEnum.DOWNLOAD_START);
|
||||
Boolean test = baseNotification.send(notificationConfig, ani, "test", NotificationStatusEnum.DOWNLOAD_START);
|
||||
if (test) {
|
||||
resultSuccess();
|
||||
return;
|
||||
}
|
||||
resultError();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,8 @@ package ani.rss.action;
|
||||
|
||||
import ani.rss.annotation.Auth;
|
||||
import ani.rss.annotation.Path;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.msg.Telegram;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.notification.TelegramNotification;
|
||||
import cn.hutool.http.server.HttpServerRequest;
|
||||
import cn.hutool.http.server.HttpServerResponse;
|
||||
|
||||
@@ -20,14 +19,12 @@ public class TelegramAction implements BaseAction {
|
||||
|
||||
@Override
|
||||
public void doAction(HttpServerRequest request, HttpServerResponse response) throws IOException {
|
||||
Config config = getBody(Config.class);
|
||||
ConfigUtil.format(config);
|
||||
NotificationConfig notificationConfig = getBody(NotificationConfig.class);
|
||||
String method = request.getParam("method");
|
||||
|
||||
if ("getUpdates".equals(method)) {
|
||||
Map<String, String> map = Telegram.getUpdates(config);
|
||||
Map<String, String> map = TelegramNotification.getUpdates(notificationConfig);
|
||||
resultSuccess(map);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.Item;
|
||||
import ani.rss.entity.TorrentsInfo;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.StringEnum;
|
||||
import ani.rss.util.*;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
@@ -252,9 +252,9 @@ public class Alist implements BaseDownload {
|
||||
"names", List.of(reName)
|
||||
))).then(HttpResponse::isOk);
|
||||
|
||||
MessageUtil.send(config, ani,
|
||||
NotificationUtil.send(config, ani,
|
||||
StrFormatter.format("{} 下载完成", item.getReName()),
|
||||
MessageEnum.DOWNLOAD_END
|
||||
NotificationStatusEnum.DOWNLOAD_END
|
||||
);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -216,7 +216,7 @@ public class Ani implements Serializable {
|
||||
*/
|
||||
private Boolean message;
|
||||
|
||||
public static Ani bulidAni() {
|
||||
public static Ani createAni() {
|
||||
Ani newAni = new Ani();
|
||||
Config config = ConfigUtil.CONFIG;
|
||||
return newAni
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ani.rss.entity;
|
||||
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@@ -228,26 +227,6 @@ public class Config implements Serializable {
|
||||
*/
|
||||
private Integer downloadCount;
|
||||
|
||||
/**
|
||||
* 邮箱是否开启
|
||||
*/
|
||||
private Boolean mail;
|
||||
|
||||
/**
|
||||
* 发件人
|
||||
*/
|
||||
private MyMailAccount mailAccount;
|
||||
|
||||
/**
|
||||
* 收件人
|
||||
*/
|
||||
private String mailAddressee;
|
||||
|
||||
/**
|
||||
* mail 发送图片
|
||||
*/
|
||||
private Boolean mailImage;
|
||||
|
||||
/**
|
||||
* 登录信息
|
||||
*/
|
||||
@@ -278,61 +257,6 @@ public class Config implements Serializable {
|
||||
*/
|
||||
private Boolean enabledExclude;
|
||||
|
||||
/**
|
||||
* telegram
|
||||
*/
|
||||
private Boolean telegram;
|
||||
|
||||
/**
|
||||
* telegram bot token
|
||||
*/
|
||||
private String telegramBotToken;
|
||||
|
||||
/**
|
||||
* telegram chat_id
|
||||
*/
|
||||
private String telegramChatId;
|
||||
|
||||
/**
|
||||
* telegram topic id
|
||||
*/
|
||||
private Integer telegramTopicId;
|
||||
|
||||
/**
|
||||
* telegram Api Host
|
||||
*/
|
||||
private String telegramApiHost;
|
||||
|
||||
/**
|
||||
* telegram 发送图片
|
||||
*/
|
||||
private Boolean telegramImage;
|
||||
|
||||
/**
|
||||
* telegram 格式
|
||||
*/
|
||||
private String telegramFormat;
|
||||
|
||||
/**
|
||||
* webHookMethod
|
||||
*/
|
||||
private String webHookMethod;
|
||||
|
||||
/**
|
||||
* webHookUrl
|
||||
*/
|
||||
private String webHookUrl;
|
||||
|
||||
/**
|
||||
* webHookBody
|
||||
*/
|
||||
private String webHookBody;
|
||||
|
||||
/**
|
||||
* webHook
|
||||
*/
|
||||
private Boolean webHook;
|
||||
|
||||
/**
|
||||
* BGM日文标题
|
||||
*/
|
||||
@@ -418,46 +342,11 @@ public class Config implements Serializable {
|
||||
*/
|
||||
private Boolean renameDelTmdbId;
|
||||
|
||||
/**
|
||||
* 通知类型
|
||||
*/
|
||||
private List<MessageEnum> messageList;
|
||||
|
||||
/**
|
||||
* 校验登录IP
|
||||
*/
|
||||
private Boolean verifyLoginIp;
|
||||
|
||||
/**
|
||||
* server酱类型:server酱和server酱3
|
||||
*/
|
||||
private String serverChanType;
|
||||
|
||||
/**
|
||||
* server酱 sendKey
|
||||
*/
|
||||
private String serverChanSendKey;
|
||||
|
||||
/**
|
||||
* server酱3 apiUrl
|
||||
*/
|
||||
private String serverChan3ApiUrl;
|
||||
|
||||
/**
|
||||
* server酱 标题事件
|
||||
*/
|
||||
private Boolean serverChanTitleAction;
|
||||
|
||||
/**
|
||||
* server酱 开关
|
||||
*/
|
||||
private Boolean serverChan;
|
||||
|
||||
/**
|
||||
* 系统通知
|
||||
*/
|
||||
private Boolean systemMsg;
|
||||
|
||||
/**
|
||||
* 自动更新 trackers
|
||||
*/
|
||||
@@ -471,7 +360,7 @@ public class Config implements Serializable {
|
||||
/**
|
||||
* 消息模版
|
||||
*/
|
||||
private String messageTemplate;
|
||||
private String notificationTemplate;
|
||||
|
||||
/**
|
||||
* 自动更新
|
||||
@@ -588,31 +477,6 @@ public class Config implements Serializable {
|
||||
*/
|
||||
private Boolean tryOut;
|
||||
|
||||
/**
|
||||
* emby扫描媒体库
|
||||
*/
|
||||
private Boolean embyRefresh;
|
||||
|
||||
/**
|
||||
* emby地址
|
||||
*/
|
||||
private String embyHost;
|
||||
|
||||
/**
|
||||
* emby api密钥
|
||||
*/
|
||||
private String embyApiKey;
|
||||
|
||||
/**
|
||||
* emby扫描媒体库
|
||||
*/
|
||||
private List<String> embyRefreshViewIds;
|
||||
|
||||
/**
|
||||
* emby延迟扫描
|
||||
*/
|
||||
private Long embyDelayed;
|
||||
|
||||
/**
|
||||
* 摸鱼
|
||||
*/
|
||||
@@ -697,4 +561,9 @@ public class Config implements Serializable {
|
||||
* 番剧完结迁移位置
|
||||
*/
|
||||
private String completedPathTemplate;
|
||||
|
||||
/**
|
||||
* 通知
|
||||
*/
|
||||
private List<NotificationConfig> notificationConfigList;
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package ani.rss.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 邮箱通知的配置
|
||||
* <p>
|
||||
* 具体注释见
|
||||
*
|
||||
* @see cn.hutool.extra.mail.MailAccount
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class MyMailAccount implements Serializable {
|
||||
private String host;
|
||||
private Integer port;
|
||||
private String from;
|
||||
private String pass;
|
||||
private Boolean sslEnable;
|
||||
private Boolean starttlsEnable;
|
||||
}
|
||||
219
src/main/java/ani/rss/entity/NotificationConfig.java
Normal file
219
src/main/java/ani/rss/entity/NotificationConfig.java
Normal file
@@ -0,0 +1,219 @@
|
||||
package ani.rss.entity;
|
||||
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.NotificationTypeEnum;
|
||||
import ani.rss.enums.ServerChanTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class NotificationConfig implements Serializable {
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
private Boolean enable;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 通知模版
|
||||
*/
|
||||
private String notificationTemplate;
|
||||
|
||||
/**
|
||||
* 通知类型
|
||||
*/
|
||||
private NotificationTypeEnum notificationType;
|
||||
|
||||
/**
|
||||
* 邮箱 smtp
|
||||
*/
|
||||
private String mailSMTPHost;
|
||||
/**
|
||||
* 邮箱 端口
|
||||
*/
|
||||
private Integer mailSMTPPort;
|
||||
/**
|
||||
* 邮箱 发件人
|
||||
*/
|
||||
private String mailFrom;
|
||||
/**
|
||||
* 邮箱 密码
|
||||
*/
|
||||
private String mailPassword;
|
||||
/**
|
||||
* 邮箱 SSL
|
||||
*/
|
||||
private Boolean mailSSLEnable;
|
||||
/**
|
||||
* 邮箱 TLS
|
||||
*/
|
||||
private Boolean mailTLSEnable;
|
||||
/**
|
||||
* 邮箱 收件人
|
||||
*/
|
||||
private String mailAddressee;
|
||||
/**
|
||||
* 邮箱 发送图片
|
||||
*/
|
||||
private Boolean mailImage;
|
||||
|
||||
|
||||
/**
|
||||
* server酱类型:server酱和server酱3
|
||||
*/
|
||||
private ServerChanTypeEnum serverChanType;
|
||||
/**
|
||||
* server酱 sendKey
|
||||
*/
|
||||
private String serverChanSendKey;
|
||||
/**
|
||||
* server酱3 apiUrl
|
||||
*/
|
||||
private String serverChan3ApiUrl;
|
||||
/**
|
||||
* server酱 标题事件
|
||||
*/
|
||||
private Boolean serverChanTitleAction;
|
||||
|
||||
|
||||
/**
|
||||
* 系统通知
|
||||
*/
|
||||
private Boolean systemMsg;
|
||||
|
||||
|
||||
/**
|
||||
* telegram bot token
|
||||
*/
|
||||
private String telegramBotToken;
|
||||
/**
|
||||
* telegram chat_id
|
||||
*/
|
||||
private String telegramChatId;
|
||||
/**
|
||||
* telegram topic id
|
||||
*/
|
||||
private Integer telegramTopicId;
|
||||
/**
|
||||
* telegram Api Host
|
||||
*/
|
||||
private String telegramApiHost;
|
||||
/**
|
||||
* telegram 发送图片
|
||||
*/
|
||||
private Boolean telegramImage;
|
||||
/**
|
||||
* telegram 格式
|
||||
*/
|
||||
private String telegramFormat;
|
||||
|
||||
|
||||
/**
|
||||
* webHookMethod
|
||||
*/
|
||||
private String webHookMethod;
|
||||
/**
|
||||
* webHookUrl
|
||||
*/
|
||||
private String webHookUrl;
|
||||
/**
|
||||
* webHookBody
|
||||
*/
|
||||
private String webHookBody;
|
||||
|
||||
|
||||
/**
|
||||
* emby扫描媒体库
|
||||
*/
|
||||
private Boolean embyRefresh;
|
||||
/**
|
||||
* emby地址
|
||||
*/
|
||||
private String embyHost;
|
||||
/**
|
||||
* emby api密钥
|
||||
*/
|
||||
private String embyApiKey;
|
||||
/**
|
||||
* emby扫描媒体库
|
||||
*/
|
||||
private List<String> embyRefreshViewIds;
|
||||
/**
|
||||
* emby延迟扫描
|
||||
*/
|
||||
private Long embyDelayed;
|
||||
|
||||
|
||||
/**
|
||||
* 通知 状态
|
||||
*/
|
||||
private List<NotificationStatusEnum> statusList;
|
||||
|
||||
|
||||
public static NotificationConfig createNotificationConfig() {
|
||||
NotificationConfig notificationConfig = new NotificationConfig();
|
||||
|
||||
notificationConfig
|
||||
.setNotificationType(NotificationTypeEnum.TELEGRAM)
|
||||
.setNotificationTemplate("${notification}")
|
||||
.setComment("")
|
||||
.setStatusList(List.of(
|
||||
NotificationStatusEnum.DOWNLOAD_START,
|
||||
NotificationStatusEnum.OMIT,
|
||||
NotificationStatusEnum.ERROR
|
||||
));
|
||||
|
||||
// 邮箱
|
||||
notificationConfig
|
||||
.setMailSMTPHost("smtp.qq.com")
|
||||
.setMailSMTPPort(465)
|
||||
.setMailFrom("")
|
||||
.setMailPassword("")
|
||||
.setMailAddressee("")
|
||||
.setMailImage(true)
|
||||
.setMailSSLEnable(true)
|
||||
.setMailTLSEnable(false);
|
||||
|
||||
// telegram
|
||||
notificationConfig
|
||||
.setTelegramChatId("")
|
||||
.setTelegramBotToken("")
|
||||
.setTelegramApiHost("https://api.telegram.org")
|
||||
.setTelegramImage(true)
|
||||
.setTelegramTopicId(-1)
|
||||
.setTelegramFormat("");
|
||||
|
||||
// webhook
|
||||
notificationConfig
|
||||
.setWebHookBody("")
|
||||
.setWebHookUrl("")
|
||||
.setWebHookMethod("POST");
|
||||
|
||||
// server-chan
|
||||
notificationConfig
|
||||
.setServerChanType(ServerChanTypeEnum.SERVER_CHAN)
|
||||
.setServerChanSendKey("")
|
||||
.setServerChan3ApiUrl("")
|
||||
.setServerChanTitleAction(true);
|
||||
|
||||
// emby
|
||||
notificationConfig
|
||||
.setEmbyRefresh(false)
|
||||
.setEmbyApiKey("")
|
||||
.setEmbyRefreshViewIds(new ArrayList<>())
|
||||
.setEmbyDelayed(0L);
|
||||
|
||||
return notificationConfig;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package ani.rss.enums;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum MessageEnum {
|
||||
public enum NotificationStatusEnum {
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
@@ -36,7 +36,7 @@ public enum MessageEnum {
|
||||
private final String emoji;
|
||||
private final String action;
|
||||
|
||||
MessageEnum(String emoji, String action) {
|
||||
NotificationStatusEnum(String emoji, String action) {
|
||||
this.emoji = emoji;
|
||||
this.action = action;
|
||||
}
|
||||
18
src/main/java/ani/rss/enums/NotificationTypeEnum.java
Normal file
18
src/main/java/ani/rss/enums/NotificationTypeEnum.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package ani.rss.enums;
|
||||
|
||||
import ani.rss.notification.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum NotificationTypeEnum {
|
||||
EMBY_REFRESH(EmbyRefreshNotification.class),
|
||||
MAIL(MailNotification.class),
|
||||
SERVER_CHAN(ServerChanNotification.class),
|
||||
SYSTEM(SystemNotification.class),
|
||||
TELEGRAM(TelegramNotification.class),
|
||||
WEB_HOOK(WebHookNotification.class);
|
||||
|
||||
@Getter
|
||||
private final Class<? extends BaseNotification> aClass;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package ani.rss.msg;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.MyMailAccount;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.util.ExceptionUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import cn.hutool.extra.mail.MailUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@Slf4j
|
||||
public class Mail implements Message {
|
||||
@Override
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
String messageBody = replaceMessageTemplate(ani, config.getMessageTemplate(), text, messageEnum);
|
||||
Boolean mail = config.getMail();
|
||||
MyMailAccount myMailAccount = config.getMailAccount();
|
||||
String mailAddressee = config.getMailAddressee();
|
||||
|
||||
if (!mail) {
|
||||
return false;
|
||||
}
|
||||
String from = myMailAccount.getFrom();
|
||||
String host = myMailAccount.getHost();
|
||||
String pass = myMailAccount.getPass();
|
||||
Assert.notBlank(from, "发件人邮箱 为空");
|
||||
Assert.notBlank(host, "SMTP地址 为空");
|
||||
Assert.notBlank(pass, "密码 为空");
|
||||
Assert.notBlank(mailAddressee, "收件人 为空");
|
||||
|
||||
MailAccount mailAccount = new MailAccount();
|
||||
BeanUtil.copyProperties(myMailAccount, mailAccount, CopyOptions
|
||||
.create()
|
||||
.setIgnoreNullValue(true));
|
||||
mailAccount.setUser(from)
|
||||
.setFrom(StrFormatter.format("ani-rss <{}>", from))
|
||||
.setAuth(true);
|
||||
|
||||
messageBody = messageBody.replace("\n", "<br/>");
|
||||
|
||||
Boolean mailImage = config.getMailImage();
|
||||
if (mailImage) {
|
||||
String image = "https://docs.wushuo.top/null.png";
|
||||
|
||||
if (Objects.nonNull(ani)) {
|
||||
image = ani.getImage();
|
||||
}
|
||||
|
||||
messageBody += StrFormatter.format("<br/><img src=\"{}\"/>", image);
|
||||
}
|
||||
|
||||
try {
|
||||
MailUtil.send(mailAccount, List.of(mailAddressee), text.length() > 200 ? ani.getTitle() : text, messageBody, true);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
String message = ExceptionUtil.getMessage(e);
|
||||
log.error(message, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package ani.rss.msg;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.util.MenuUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* SystemMsg
|
||||
*/
|
||||
@Slf4j
|
||||
public class SystemMsg implements Message {
|
||||
@Override
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
text = replaceMessageTemplate(ani, config.getMessageTemplate(), text, messageEnum);
|
||||
if (!SystemTray.isSupported()) {
|
||||
log.error("SystemTray is not supported");
|
||||
return false;
|
||||
}
|
||||
TrayIcon trayIcon = MenuUtil.trayIcon;
|
||||
if (Objects.isNull(trayIcon)) {
|
||||
log.error("未开启系统托盘 添加--gui参数启动");
|
||||
return false;
|
||||
}
|
||||
TrayIcon.MessageType type = TrayIcon.MessageType.INFO;
|
||||
if (Objects.nonNull(messageEnum)) {
|
||||
if (messageEnum.name().equals(MessageEnum.ERROR.name())) {
|
||||
type = TrayIcon.MessageType.ERROR;
|
||||
}
|
||||
}
|
||||
trayIcon.displayMessage("ani-rss", text, type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package ani.rss.msg;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.util.HttpReq;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.Method;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* WebHook
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebHook implements Message {
|
||||
@Override
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
String messageTemplate = config.getMessageTemplate();
|
||||
messageTemplate = messageTemplate.replace("\n", "\\n");
|
||||
String message = replaceMessageTemplate(ani, messageTemplate, text, messageEnum);
|
||||
|
||||
String webHookMethod = config.getWebHookMethod();
|
||||
String webHookUrl = config.getWebHookUrl();
|
||||
String webHookBody = config.getWebHookBody();
|
||||
|
||||
webHookUrl = replaceMessageTemplate(ani, webHookUrl, text, messageEnum);
|
||||
webHookBody = replaceMessageTemplate(ani, webHookBody, text, messageEnum);
|
||||
|
||||
if (StrUtil.isBlank(webHookUrl)) {
|
||||
log.warn("webhook url is blank");
|
||||
return false;
|
||||
}
|
||||
|
||||
webHookUrl = webHookUrl.replace("${message}", message);
|
||||
webHookBody = webHookBody.replace("${message}", message);
|
||||
|
||||
String image = "https://docs.wushuo.top/null.png";
|
||||
|
||||
if (Objects.nonNull(ani) && StrUtil.isNotBlank(ani.getImage())) {
|
||||
image = ani.getImage();
|
||||
}
|
||||
|
||||
webHookUrl = webHookUrl.replace("${image}", image);
|
||||
webHookBody = webHookBody.replace("${image}", image);
|
||||
|
||||
HttpRequest httpRequest = HttpReq.get(webHookUrl, true)
|
||||
.method(Method.valueOf(webHookMethod));
|
||||
|
||||
if (StrUtil.isNotBlank(webHookBody)) {
|
||||
httpRequest.body(webHookBody);
|
||||
}
|
||||
return httpRequest.thenFunction(HttpResponse::isOk);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package ani.rss.msg;
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.entity.Tmdb;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.StringEnum;
|
||||
import ani.rss.util.FilePathUtil;
|
||||
import ani.rss.util.NumberFormatUtil;
|
||||
@@ -18,12 +18,12 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface Message {
|
||||
public interface BaseNotification {
|
||||
|
||||
Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum);
|
||||
Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum);
|
||||
|
||||
default String replaceMessageTemplate(Ani ani, String messageTemplate, String text, MessageEnum messageEnum) {
|
||||
messageTemplate = messageTemplate.replace("${text}", text);
|
||||
default String replaceNotificationTemplate(Ani ani, String notificationTemplate, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
notificationTemplate = notificationTemplate.replace("${text}", text);
|
||||
// 集数
|
||||
double episode = 1.0;
|
||||
if (ReUtil.contains(StringEnum.SEASON_REG, text)) {
|
||||
@@ -39,13 +39,13 @@ public interface Message {
|
||||
episodeFormat = episodeFormat + ".5";
|
||||
}
|
||||
|
||||
messageTemplate = messageTemplate.replace("${episode}",
|
||||
notificationTemplate = notificationTemplate.replace("${episode}",
|
||||
NumberFormatUtil.format(episode, 1, 0)
|
||||
);
|
||||
messageTemplate = messageTemplate.replace("${episodeFormat}", episodeFormat);
|
||||
notificationTemplate = notificationTemplate.replace("${episodeFormat}", episodeFormat);
|
||||
|
||||
if (Objects.isNull(ani)) {
|
||||
return messageTemplate;
|
||||
return notificationTemplate;
|
||||
}
|
||||
|
||||
List<Func1<Ani, Object>> list = List.of(
|
||||
@@ -64,38 +64,38 @@ public interface Message {
|
||||
|
||||
int season = ani.getSeason();
|
||||
String seasonFormat = String.format("%02d", season);
|
||||
messageTemplate = messageTemplate.replace("${seasonFormat}", seasonFormat);
|
||||
notificationTemplate = notificationTemplate.replace("${seasonFormat}", seasonFormat);
|
||||
|
||||
messageTemplate = RenameUtil.replaceField(messageTemplate, ani, list);
|
||||
notificationTemplate = RenameUtil.replaceField(notificationTemplate, ani, list);
|
||||
|
||||
String tmdbId = Optional.ofNullable(ani.getTmdb())
|
||||
.map(Tmdb::getId)
|
||||
.orElse("");
|
||||
messageTemplate = messageTemplate.replace("${tmdbid}", tmdbId);
|
||||
notificationTemplate = notificationTemplate.replace("${tmdbid}", tmdbId);
|
||||
|
||||
String tmdbUrl = "";
|
||||
if (StrUtil.isNotBlank(tmdbId)) {
|
||||
String type = ani.getOva() ? "movie" : "tv";
|
||||
tmdbUrl = StrFormatter.format("https://www.themoviedb.org/{}/{}", type, tmdbId);
|
||||
}
|
||||
messageTemplate = messageTemplate.replace("${tmdburl}", tmdbUrl);
|
||||
notificationTemplate = notificationTemplate.replace("${tmdburl}", tmdbUrl);
|
||||
|
||||
String emoji = messageEnum.getEmoji();
|
||||
String action = messageEnum.getAction();
|
||||
String emoji = notificationStatusEnum.getEmoji();
|
||||
String action = notificationStatusEnum.getAction();
|
||||
|
||||
messageTemplate = messageTemplate.replace("${emoji}", emoji);
|
||||
messageTemplate = messageTemplate.replace("${action}", action);
|
||||
notificationTemplate = notificationTemplate.replace("${emoji}", emoji);
|
||||
notificationTemplate = notificationTemplate.replace("${action}", action);
|
||||
|
||||
String downloadPath = FilePathUtil.getAbsolutePath(TorrentUtil.getDownloadPath(ani));
|
||||
messageTemplate = messageTemplate.replace("${downloadPath}", downloadPath);
|
||||
notificationTemplate = notificationTemplate.replace("${downloadPath}", downloadPath);
|
||||
|
||||
if (messageTemplate.contains("${jpTitle}")) {
|
||||
if (notificationTemplate.contains("${jpTitle}")) {
|
||||
String jpTitle = RenameUtil.getJpTitle(ani);
|
||||
messageTemplate = messageTemplate.replace("${jpTitle}", jpTitle);
|
||||
notificationTemplate = notificationTemplate.replace("${jpTitle}", jpTitle);
|
||||
}
|
||||
|
||||
messageTemplate = RenameUtil.replaceEpisodeTitle(messageTemplate, episode, ani);
|
||||
notificationTemplate = RenameUtil.replaceEpisodeTitle(notificationTemplate, episode, ani);
|
||||
|
||||
return messageTemplate.trim();
|
||||
return notificationTemplate.trim();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package ani.rss.msg;
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.util.AfdianUtil;
|
||||
import ani.rss.util.EmbyUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
@@ -12,17 +12,17 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
public class EmbyRefresh implements Message {
|
||||
public class EmbyRefreshNotification implements BaseNotification {
|
||||
@Override
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Assert.isTrue(AfdianUtil.verifyExpirationTime(), "未解锁捐赠, 无法使用Emby媒体库刷新");
|
||||
|
||||
Long embyDelayed = config.getEmbyDelayed();
|
||||
Long embyDelayed = notificationConfig.getEmbyDelayed();
|
||||
if (embyDelayed > 0) {
|
||||
ThreadUtil.sleep(embyDelayed, TimeUnit.SECONDS);
|
||||
}
|
||||
try {
|
||||
EmbyUtil.refresh(config);
|
||||
EmbyUtil.refresh(notificationConfig);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
78
src/main/java/ani/rss/notification/MailNotification.java
Normal file
78
src/main/java/ani/rss/notification/MailNotification.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.util.ExceptionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import cn.hutool.extra.mail.MailUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@Slf4j
|
||||
public class MailNotification implements BaseNotification {
|
||||
@Override
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Config config = ConfigUtil.CONFIG;
|
||||
String template = config.getNotificationTemplate();
|
||||
template = replaceNotificationTemplate(ani, template, text, notificationStatusEnum);
|
||||
|
||||
String notificationTemplate = notificationConfig.getNotificationTemplate();
|
||||
notificationTemplate = notificationTemplate.replace("${notification}", template);
|
||||
notificationTemplate = replaceNotificationTemplate(ani, notificationTemplate, text, notificationStatusEnum);
|
||||
|
||||
String mailFrom = notificationConfig.getMailFrom();
|
||||
String mailSMTPHost = notificationConfig.getMailSMTPHost();
|
||||
String mailPassword = notificationConfig.getMailPassword();
|
||||
Integer mailSMTPPort = notificationConfig.getMailSMTPPort();
|
||||
String mailAddressee = notificationConfig.getMailAddressee();
|
||||
Boolean mailImage = notificationConfig.getMailImage();
|
||||
Boolean mailSSLEnable = notificationConfig.getMailSSLEnable();
|
||||
Boolean mailTLSEnable = notificationConfig.getMailTLSEnable();
|
||||
|
||||
Assert.notBlank(mailFrom, "发件人邮箱 为空");
|
||||
Assert.notBlank(mailSMTPHost, "SMTP地址 为空");
|
||||
Assert.notBlank(mailPassword, "密码 为空");
|
||||
Assert.notBlank(mailAddressee, "收件人 为空");
|
||||
|
||||
MailAccount mailAccount = new MailAccount()
|
||||
.setUser(mailFrom)
|
||||
.setFrom(StrFormatter.format("ani-rss <{}>", mailFrom))
|
||||
.setPass(mailPassword)
|
||||
.setHost(mailSMTPHost)
|
||||
.setPort(mailSMTPPort)
|
||||
.setSslEnable(mailSSLEnable)
|
||||
.setStarttlsEnable(mailTLSEnable)
|
||||
.setAuth(true);
|
||||
|
||||
notificationTemplate = notificationTemplate.replace("\n", "<br/>");
|
||||
|
||||
if (mailImage) {
|
||||
String image = "https://docs.wushuo.top/null.png";
|
||||
|
||||
if (Objects.nonNull(ani)) {
|
||||
image = ani.getImage();
|
||||
}
|
||||
|
||||
notificationTemplate += StrFormatter.format("<br/><img src=\"{}\"/>", image);
|
||||
}
|
||||
|
||||
try {
|
||||
MailUtil.send(mailAccount, List.of(mailAddressee), text.length() > 200 ? ani.getTitle() : text, notificationTemplate, true);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
String message = ExceptionUtil.getMessage(e);
|
||||
log.error(message, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package ani.rss.msg;
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.ServerChanTypeEnum;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.util.GsonStatic;
|
||||
import ani.rss.util.HttpReq;
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
@@ -18,52 +20,62 @@ import java.util.Objects;
|
||||
* ServerChan
|
||||
*/
|
||||
@Slf4j
|
||||
public class ServerChan implements Message {
|
||||
public class ServerChanNotification implements BaseNotification {
|
||||
private static final String MARKDOWN_STRING = "# <message>\n\n";
|
||||
|
||||
@Override
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
text = replaceMessageTemplate(ani, config.getMessageTemplate(), text, messageEnum);
|
||||
text = text.replace("\n", "\n\n");
|
||||
String type = config.getServerChanType();
|
||||
String sendKey = config.getServerChanSendKey();
|
||||
String apiUrl = config.getServerChan3ApiUrl();
|
||||
Boolean serverChanTitleAction = config.getServerChanTitleAction();
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Config config = ConfigUtil.CONFIG;
|
||||
String template = config.getNotificationTemplate();
|
||||
template = replaceNotificationTemplate(ani, template, text, notificationStatusEnum);
|
||||
|
||||
String notificationTemplate = notificationConfig.getNotificationTemplate();
|
||||
notificationTemplate = notificationTemplate.replace("${notification}", template);
|
||||
notificationTemplate = replaceNotificationTemplate(ani, notificationTemplate, text, notificationStatusEnum);
|
||||
notificationTemplate = notificationTemplate.replace("\n", "\n\n");
|
||||
|
||||
ServerChanTypeEnum type = notificationConfig.getServerChanType();
|
||||
String sendKey = notificationConfig.getServerChanSendKey();
|
||||
String apiUrl = notificationConfig.getServerChan3ApiUrl();
|
||||
Boolean serverChanTitleAction = notificationConfig.getServerChanTitleAction();
|
||||
|
||||
Boolean flag = checkParam(type, sendKey, apiUrl);
|
||||
if (!flag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String title = "";
|
||||
String image = "https://docs.wushuo.top/null.png";
|
||||
|
||||
String title = text;
|
||||
if (Objects.nonNull(ani)) {
|
||||
if (StrUtil.isNotBlank(ani.getImage())) {
|
||||
image = ani.getImage();
|
||||
}
|
||||
title = truncateMessage(ani.getTitle(), serverChanTitleAction ? 10 : 15);
|
||||
if (serverChanTitleAction) {
|
||||
String action = messageEnum.getAction();
|
||||
title = StrFormatter.format("{}#{}", action, title);
|
||||
String action = notificationStatusEnum.getAction();
|
||||
title = StrFormatter.format("{}#{}", action, ani.getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
String serverChanUrl = "";
|
||||
String body = "";
|
||||
String desp = MARKDOWN_STRING.replace("<message>", text).replace("<image>", image);
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN.getType())) {
|
||||
String desp = MARKDOWN_STRING
|
||||
.replace("<message>", notificationTemplate)
|
||||
.replace("<image>", image);
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN)) {
|
||||
serverChanUrl = ServerChanTypeEnum.SERVER_CHAN.getUrl().replace("<sendKey>", sendKey);
|
||||
body = GsonStatic.toJson(Map.of(
|
||||
"title", title,
|
||||
"desp", desp
|
||||
));
|
||||
} else if (type.equals(ServerChanTypeEnum.SERVER_CHAN_3.getType())) {
|
||||
}
|
||||
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN_3)) {
|
||||
serverChanUrl = apiUrl;
|
||||
body = GsonStatic.toJson(Map.of(
|
||||
"title", title,
|
||||
"tags", "ass",
|
||||
"tags", "ani-rss",
|
||||
"desp", desp
|
||||
));
|
||||
}
|
||||
@@ -73,27 +85,19 @@ public class ServerChan implements Message {
|
||||
.thenFunction(HttpResponse::isOk);
|
||||
}
|
||||
|
||||
private static Boolean checkParam(String type, String sendKey, String apiUrl) {
|
||||
if (StrUtil.isBlank(type)) {
|
||||
log.warn("server酱类型不能为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN.getType())) {
|
||||
private static Boolean checkParam(ServerChanTypeEnum type, String sendKey, String apiUrl) {
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN)) {
|
||||
if (StrUtil.isBlank(sendKey)) {
|
||||
log.warn("sendKey 不能为空");
|
||||
return false;
|
||||
}
|
||||
} else if (type.equals(ServerChanTypeEnum.SERVER_CHAN_3.getType())) {
|
||||
}
|
||||
if (type.equals(ServerChanTypeEnum.SERVER_CHAN_3)) {
|
||||
if (StrUtil.isBlank(apiUrl)) {
|
||||
log.warn("apiUrl 不能为空");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log.warn("无效的server酱类型");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
46
src/main/java/ani/rss/notification/SystemNotification.java
Normal file
46
src/main/java/ani/rss/notification/SystemNotification.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.util.MenuUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* SystemMsg
|
||||
*/
|
||||
@Slf4j
|
||||
public class SystemNotification implements BaseNotification {
|
||||
@Override
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Config config = ConfigUtil.CONFIG;
|
||||
String template = config.getNotificationTemplate();
|
||||
template = replaceNotificationTemplate(ani, template, text, notificationStatusEnum);
|
||||
|
||||
String notificationTemplate = notificationConfig.getNotificationTemplate();
|
||||
notificationTemplate = notificationTemplate.replace("${notification}", template);
|
||||
notificationTemplate = replaceNotificationTemplate(ani, notificationTemplate, text, notificationStatusEnum);
|
||||
if (!SystemTray.isSupported()) {
|
||||
log.error("SystemTray is not supported");
|
||||
return false;
|
||||
}
|
||||
TrayIcon trayIcon = MenuUtil.trayIcon;
|
||||
if (Objects.isNull(trayIcon)) {
|
||||
log.error("未开启系统托盘 添加--gui参数启动");
|
||||
return false;
|
||||
}
|
||||
TrayIcon.MessageType type = TrayIcon.MessageType.INFO;
|
||||
if (Objects.nonNull(notificationStatusEnum)) {
|
||||
if (notificationStatusEnum.name().equals(NotificationStatusEnum.ERROR.name())) {
|
||||
type = TrayIcon.MessageType.ERROR;
|
||||
}
|
||||
}
|
||||
trayIcon.displayMessage("ani-rss", notificationTemplate, type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package ani.rss.msg;
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.util.ConfigUtil;
|
||||
import ani.rss.util.GsonStatic;
|
||||
import ani.rss.util.HttpReq;
|
||||
@@ -25,13 +26,13 @@ import java.util.Optional;
|
||||
* Telegram
|
||||
*/
|
||||
@Slf4j
|
||||
public class Telegram implements Message {
|
||||
public static synchronized Map<String, String> getUpdates(Config config) {
|
||||
String telegramBotToken = config.getTelegramBotToken();
|
||||
public class TelegramNotification implements BaseNotification {
|
||||
public static synchronized Map<String, String> getUpdates(NotificationConfig notificationConfig) {
|
||||
String telegramBotToken = notificationConfig.getTelegramBotToken();
|
||||
if (StrUtil.isBlank(telegramBotToken)) {
|
||||
return Map.of();
|
||||
}
|
||||
String telegramApiHost = config.getTelegramApiHost();
|
||||
String telegramApiHost = notificationConfig.getTelegramApiHost();
|
||||
telegramApiHost = StrUtil.blankToDefault(telegramApiHost, "https://api.telegram.org");
|
||||
String url = StrFormatter.format("{}/bot{}/getUpdates", telegramApiHost, telegramBotToken);
|
||||
Map<String, String> map = new HashMap<>();
|
||||
@@ -73,14 +74,21 @@ public class Telegram implements Message {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
public Boolean send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
text = replaceMessageTemplate(ani, config.getMessageTemplate(), text, messageEnum);
|
||||
String telegramBotToken = config.getTelegramBotToken();
|
||||
String telegramChatId = config.getTelegramChatId();
|
||||
Integer telegramTopicId = config.getTelegramTopicId();
|
||||
String telegramApiHost = config.getTelegramApiHost();
|
||||
Boolean telegramImage = config.getTelegramImage();
|
||||
String telegramFormat = config.getTelegramFormat();
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Config config = ConfigUtil.CONFIG;
|
||||
String template = config.getNotificationTemplate();
|
||||
template = replaceNotificationTemplate(ani, template, text, notificationStatusEnum);
|
||||
|
||||
String notificationTemplate = notificationConfig.getNotificationTemplate();
|
||||
notificationTemplate = notificationTemplate.replace("${notification}", template);
|
||||
notificationTemplate = replaceNotificationTemplate(ani, notificationTemplate, text, notificationStatusEnum);
|
||||
|
||||
String telegramBotToken = notificationConfig.getTelegramBotToken();
|
||||
String telegramChatId = notificationConfig.getTelegramChatId();
|
||||
Integer telegramTopicId = notificationConfig.getTelegramTopicId();
|
||||
String telegramApiHost = notificationConfig.getTelegramApiHost();
|
||||
Boolean telegramImage = notificationConfig.getTelegramImage();
|
||||
String telegramFormat = notificationConfig.getTelegramFormat();
|
||||
if (StrUtil.isBlank(telegramChatId) || StrUtil.isBlank(telegramBotToken)) {
|
||||
log.warn("telegram 通知的参数不完整");
|
||||
return false;
|
||||
@@ -95,7 +103,7 @@ public class Telegram implements Message {
|
||||
if (telegramTopicId > -1) {
|
||||
body.put("message_thread_id", telegramTopicId);
|
||||
}
|
||||
body.put("text", text);
|
||||
body.put("text", notificationTemplate);
|
||||
if (StrUtil.isNotBlank(telegramFormat)) {
|
||||
body.put("parse_mode", telegramFormat);
|
||||
}
|
||||
@@ -107,7 +115,7 @@ public class Telegram implements Message {
|
||||
File configDir = ConfigUtil.getConfigDir();
|
||||
File photo = new File(configDir + "/files/" + cover);
|
||||
if (StrUtil.isBlank(cover) || !photo.exists()) {
|
||||
return send(config, null, text, messageEnum);
|
||||
return send(notificationConfig, null, notificationTemplate, notificationStatusEnum);
|
||||
}
|
||||
|
||||
url = StrFormatter.format("{}/bot{}/sendPhoto", telegramApiHost, telegramBotToken);
|
||||
@@ -115,7 +123,7 @@ public class Telegram implements Message {
|
||||
HttpRequest request = HttpReq.post(url, true)
|
||||
.contentType(ContentType.MULTIPART.getValue())
|
||||
.form("chat_id", telegramChatId)
|
||||
.form("caption", text)
|
||||
.form("caption", notificationTemplate)
|
||||
.form("photo", photo)
|
||||
.form("parse_mode", telegramFormat);
|
||||
|
||||
58
src/main/java/ani/rss/notification/WebHookNotification.java
Normal file
58
src/main/java/ani/rss/notification/WebHookNotification.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package ani.rss.notification;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.util.HttpReq;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.Method;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* WebHook
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebHookNotification implements BaseNotification {
|
||||
@Override
|
||||
public Boolean send(NotificationConfig notificationConfig, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
String notificationTemplate = notificationConfig.getNotificationTemplate();
|
||||
notificationTemplate = notificationTemplate.replace("\n", "\\n");
|
||||
notificationTemplate = replaceNotificationTemplate(ani, notificationTemplate, text, notificationStatusEnum);
|
||||
|
||||
String webHookMethod = notificationConfig.getWebHookMethod();
|
||||
String webHookUrl = notificationConfig.getWebHookUrl();
|
||||
String webHookBody = notificationConfig.getWebHookBody();
|
||||
|
||||
webHookUrl = replaceNotificationTemplate(ani, webHookUrl, text, notificationStatusEnum);
|
||||
webHookBody = replaceNotificationTemplate(ani, webHookBody, text, notificationStatusEnum);
|
||||
|
||||
if (StrUtil.isBlank(webHookUrl)) {
|
||||
log.warn("webhook url is blank");
|
||||
return false;
|
||||
}
|
||||
|
||||
webHookUrl = webHookUrl.replace("${notification}", notificationTemplate);
|
||||
webHookBody = webHookBody.replace("${notification}", notificationTemplate);
|
||||
|
||||
String image = "https://docs.wushuo.top/null.png";
|
||||
|
||||
if (Objects.nonNull(ani) && StrUtil.isNotBlank(ani.getImage())) {
|
||||
image = ani.getImage();
|
||||
}
|
||||
|
||||
webHookUrl = webHookUrl.replace("${image}", image);
|
||||
webHookBody = webHookBody.replace("${image}", image);
|
||||
|
||||
HttpRequest httpRequest = HttpReq.get(webHookUrl, true)
|
||||
.method(Method.valueOf(webHookMethod));
|
||||
|
||||
if (StrUtil.isNotBlank(webHookBody)) {
|
||||
httpRequest.body(webHookBody);
|
||||
}
|
||||
return httpRequest.thenFunction(HttpResponse::isOk);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package ani.rss.util;
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.TorrentsInfo;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.TorrentsTags;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
@@ -119,7 +119,7 @@ public class AlistUtil {
|
||||
text = StrFormatter.format("已向alist添加上传任务 {}", fileName);
|
||||
}
|
||||
log.info(text);
|
||||
MessageUtil.send(config, ani, text, MessageEnum.ALIST_UPLOAD);
|
||||
NotificationUtil.send(config, ani, text, NotificationStatusEnum.ALIST_UPLOAD);
|
||||
});
|
||||
TorrentUtil.addTags(torrentsInfo, TorrentsTags.UPLOAD_COMPLETED.getValue());
|
||||
return;
|
||||
@@ -128,7 +128,7 @@ public class AlistUtil {
|
||||
}
|
||||
}
|
||||
if (AfdianUtil.verifyExpirationTime()) {
|
||||
MessageUtil.send(config, ani, "alist上传失败 " + fileName, MessageEnum.ERROR);
|
||||
NotificationUtil.send(config, ani, "alist上传失败 " + fileName, NotificationStatusEnum.ERROR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AniUtil {
|
||||
String s = FileUtil.readUtf8String(configFile);
|
||||
List<Ani> anis = GsonStatic.fromJsonList(s, Ani.class);
|
||||
for (Ani ani : anis) {
|
||||
Ani newAni = Ani.bulidAni();
|
||||
Ani newAni = Ani.createAni();
|
||||
BeanUtil.copyProperties(ani, newAni, CopyOptions
|
||||
.create()
|
||||
.setIgnoreNullValue(true));
|
||||
@@ -87,7 +87,7 @@ public class AniUtil {
|
||||
type = StrUtil.blankToDefault(type, "mikan");
|
||||
String subgroupId = MikanUtil.getSubgroupId(url);
|
||||
|
||||
Ani ani = Ani.bulidAni();
|
||||
Ani ani = Ani.createAni();
|
||||
ani.setUrl(url.trim());
|
||||
|
||||
if ("mikan".equals(type)) {
|
||||
|
||||
@@ -2,9 +2,6 @@ package ani.rss.util;
|
||||
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.Login;
|
||||
import ani.rss.entity.MyMailAccount;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.ServerChanTypeEnum;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.DynaBean;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
@@ -56,7 +53,7 @@ public class ConfigUtil {
|
||||
|
||||
String password = Md5Util.digestHex("admin");
|
||||
|
||||
String messageTemplate = """
|
||||
String notificationTemplate = """
|
||||
${emoji}${emoji}${emoji}
|
||||
事件类型: ${action}
|
||||
标题: ${title}
|
||||
@@ -117,18 +114,6 @@ public class ConfigUtil {
|
||||
.setProxyUsername("")
|
||||
.setProxyPassword("")
|
||||
.setDownloadCount(0)
|
||||
.setMail(false)
|
||||
.setMailAddressee("")
|
||||
.setMailImage(true)
|
||||
.setMailAccount(
|
||||
new MyMailAccount()
|
||||
.setHost("")
|
||||
.setPort(25)
|
||||
.setFrom("")
|
||||
.setPass("")
|
||||
.setSslEnable(false)
|
||||
.setStarttlsEnable(false)
|
||||
)
|
||||
.setLogin(new Login()
|
||||
.setUsername("admin")
|
||||
.setPassword(password)
|
||||
@@ -138,14 +123,6 @@ public class ConfigUtil {
|
||||
.setExclude(List.of("720[Pp]", "\\d-\\d", "合集", "特别篇"))
|
||||
.setImportExclude(false)
|
||||
.setEnabledExclude(false)
|
||||
.setTelegram(false)
|
||||
.setTelegramChatId("")
|
||||
.setTelegramBotToken("")
|
||||
.setTelegramApiHost("https://api.telegram.org")
|
||||
.setTelegramImage(true)
|
||||
.setTelegramTopicId(-1)
|
||||
.setTelegramFormat("")
|
||||
.setWebHook(false)
|
||||
.setTmdb(false)
|
||||
.setBgmJpName(false)
|
||||
.setTmdbId(false)
|
||||
@@ -153,9 +130,6 @@ public class ConfigUtil {
|
||||
.setTmdbRomaji(false)
|
||||
.setIpWhitelist(false)
|
||||
.setIpWhitelistStr("")
|
||||
.setWebHookBody("")
|
||||
.setWebHookUrl("")
|
||||
.setWebHookMethod("POST")
|
||||
.setShowPlaylist(true)
|
||||
.setOmit(true)
|
||||
.setBgmToken("")
|
||||
@@ -167,18 +141,7 @@ public class ConfigUtil {
|
||||
.setRenameTemplate("[${subgroup}] ${title} S${seasonFormat}E${episodeFormat}")
|
||||
.setRenameDelYear(false)
|
||||
.setRenameDelTmdbId(false)
|
||||
.setMessageList(List.of(
|
||||
MessageEnum.DOWNLOAD_START,
|
||||
MessageEnum.OMIT,
|
||||
MessageEnum.ERROR
|
||||
))
|
||||
.setVerifyLoginIp(false)
|
||||
.setServerChan(false)
|
||||
.setServerChanType(ServerChanTypeEnum.SERVER_CHAN.getType())
|
||||
.setServerChanSendKey("")
|
||||
.setServerChan3ApiUrl("")
|
||||
.setServerChanTitleAction(true)
|
||||
.setSystemMsg(false)
|
||||
.setAutoTrackersUpdate(false)
|
||||
.setTrackersUpdateUrls("https://cf.trackerslist.com/best.txt")
|
||||
.setAutoUpdate(false)
|
||||
@@ -204,10 +167,6 @@ public class ConfigUtil {
|
||||
.setOutTradeNo("")
|
||||
.setTryOut(false)
|
||||
.setVerifyExpirationTime(false)
|
||||
.setEmbyRefresh(false)
|
||||
.setEmbyApiKey("")
|
||||
.setEmbyRefreshViewIds(new ArrayList<>())
|
||||
.setEmbyDelayed(0L)
|
||||
.setProcrastinating(false)
|
||||
.setProcrastinatingDay(14)
|
||||
.setGithub("None")
|
||||
@@ -225,7 +184,8 @@ public class ConfigUtil {
|
||||
.setShowLastDownloadTime(false)
|
||||
.setCompleted(false)
|
||||
.setCompletedPathTemplate(completedPathTemplate)
|
||||
.setMessageTemplate(messageTemplate);
|
||||
.setNotificationTemplate(notificationTemplate)
|
||||
.setNotificationConfigList(new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,6 +357,9 @@ public class ConfigUtil {
|
||||
public static void format(Config config) {
|
||||
formatPath(config);
|
||||
formatUrl(config);
|
||||
|
||||
String messageTemplate = config.getNotificationTemplate();
|
||||
config.setNotificationTemplate(messageTemplate.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,11 +371,9 @@ public class ConfigUtil {
|
||||
List<Func1<Config, String>> func1List = List.of(
|
||||
Config::getDownloadToolHost,
|
||||
Config::getAlistHost,
|
||||
Config::getTelegramApiHost,
|
||||
Config::getMikanHost,
|
||||
Config::getTmdbApi,
|
||||
Config::getCustomGithubUrl,
|
||||
Config::getEmbyHost
|
||||
Config::getCustomGithubUrl
|
||||
);
|
||||
|
||||
DynaBean dynaBean = DynaBean.create(config);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ani.rss.util;
|
||||
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.EmbyViews;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -17,18 +17,18 @@ public class EmbyUtil {
|
||||
/**
|
||||
* 扫描媒体库
|
||||
*/
|
||||
public static synchronized void refresh(Config config) {
|
||||
List<String> viewIds = config.getEmbyRefreshViewIds();
|
||||
List<EmbyViews> views = getViews(config);
|
||||
public static synchronized void refresh(NotificationConfig notificationConfig) {
|
||||
List<String> viewIds = notificationConfig.getEmbyRefreshViewIds();
|
||||
List<EmbyViews> views = getViews(notificationConfig);
|
||||
|
||||
List<String> newViewIds = views
|
||||
.stream()
|
||||
.filter(view -> viewIds.contains(view.getId()))
|
||||
.peek(view -> refresh(view, config))
|
||||
.peek(view -> refresh(view, notificationConfig))
|
||||
.map(EmbyViews::getId)
|
||||
.toList();
|
||||
|
||||
config.setEmbyRefreshViewIds(newViewIds);
|
||||
notificationConfig.setEmbyRefreshViewIds(newViewIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,9 +36,9 @@ public class EmbyUtil {
|
||||
*
|
||||
* @param embyViews 媒体库
|
||||
*/
|
||||
public static synchronized void refresh(EmbyViews embyViews, Config config) {
|
||||
String embyHost = config.getEmbyHost();
|
||||
String embyApiKey = config.getEmbyApiKey();
|
||||
public static synchronized void refresh(EmbyViews embyViews, NotificationConfig notificationConfig) {
|
||||
String embyHost = notificationConfig.getEmbyHost();
|
||||
String embyApiKey = notificationConfig.getEmbyApiKey();
|
||||
|
||||
Assert.notBlank(embyHost, "embyHost 为空");
|
||||
Assert.notBlank(embyApiKey, "embyApiKey 为空");
|
||||
@@ -63,9 +63,9 @@ public class EmbyUtil {
|
||||
*
|
||||
* @return 媒体库列表
|
||||
*/
|
||||
public static synchronized List<EmbyViews> getViews(Config config) {
|
||||
String embyHost = config.getEmbyHost();
|
||||
String embyApiKey = config.getEmbyApiKey();
|
||||
public static synchronized List<EmbyViews> getViews(NotificationConfig notificationConfig) {
|
||||
String embyHost = notificationConfig.getEmbyHost();
|
||||
String embyApiKey = notificationConfig.getEmbyApiKey();
|
||||
|
||||
Assert.notBlank(embyHost, "embyHost 为空");
|
||||
Assert.notBlank(embyApiKey, "embyApiKey 为空");
|
||||
|
||||
@@ -2,7 +2,6 @@ package ani.rss.util;
|
||||
|
||||
import ani.rss.entity.Config;
|
||||
import cn.hutool.core.net.url.UrlBuilder;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
|
||||
@@ -3,7 +3,7 @@ package ani.rss.util;
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.Item;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.StringEnum;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
@@ -330,7 +330,7 @@ public class ItemsUtil {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageUtil.send(config, ani, CollUtil.join(sList, "\n"), MessageEnum.OMIT);
|
||||
NotificationUtil.send(config, ani, CollUtil.join(sList, "\n"), NotificationStatusEnum.OMIT);
|
||||
}
|
||||
|
||||
public static int currentEpisodeNumber(Ani ani, List<Item> items) {
|
||||
@@ -419,7 +419,7 @@ public class ItemsUtil {
|
||||
}
|
||||
|
||||
MyCacheUtil.put(key, text, TimeUnit.DAYS.toMillis(1));
|
||||
MessageUtil.send(config, ani, text, MessageEnum.PROCRASTINATING);
|
||||
NotificationUtil.send(config, ani, text, NotificationStatusEnum.PROCRASTINATING);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package ani.rss.util;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.msg.Message;
|
||||
import cn.hutool.core.bean.DynaBean;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.core.thread.ExecutorBuilder;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@Slf4j
|
||||
public class MessageUtil {
|
||||
private static final ExecutorService EXECUTOR_SERVICE = ExecutorBuilder.create()
|
||||
.setCorePoolSize(1)
|
||||
.setMaxPoolSize(1)
|
||||
.setWorkQueue(new LinkedBlockingQueue<>(256))
|
||||
.build();
|
||||
|
||||
public static synchronized void send(Config config, Ani ani, String text, MessageEnum messageEnum) {
|
||||
List<MessageEnum> messageList = config.getMessageList();
|
||||
|
||||
if (!messageList.contains(messageEnum)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AfdianUtil.verifyExpirationTime()) {
|
||||
if (MessageEnum.COMPLETED == messageEnum) {
|
||||
log.warn("未解锁捐赠, 无法使用订阅完结通知");
|
||||
return;
|
||||
}
|
||||
if (MessageEnum.ALIST_UPLOAD == messageEnum) {
|
||||
log.warn("未解锁捐赠, 无法使用Alist上传通知");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Boolean isMessage = Opt.ofNullable(ani)
|
||||
.map(Ani::getMessage)
|
||||
.orElse(true);
|
||||
|
||||
if (!isMessage) {
|
||||
// 未开启此订阅通知
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Class<?>> classes = ClassUtil.scanPackage("ani.rss.msg");
|
||||
DynaBean dynaBean = DynaBean.create(config);
|
||||
for (Class<?> aClass : classes) {
|
||||
if (aClass.isInterface()) {
|
||||
continue;
|
||||
}
|
||||
String name = aClass.getSimpleName();
|
||||
name = name.substring(0, 1).toLowerCase() + name.substring(1);
|
||||
Object b = dynaBean.get(name);
|
||||
if (Objects.isNull(b)) {
|
||||
continue;
|
||||
}
|
||||
if (!(b instanceof Boolean)) {
|
||||
continue;
|
||||
}
|
||||
if (!(Boolean) b) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Message message = (Message) ReflectUtil.newInstance(aClass);
|
||||
EXECUTOR_SERVICE.execute(() -> {
|
||||
try {
|
||||
message.send(config, ani, text, messageEnum);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/main/java/ani/rss/util/NotificationUtil.java
Normal file
68
src/main/java/ani/rss/util/NotificationUtil.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package ani.rss.util;
|
||||
|
||||
import ani.rss.entity.Ani;
|
||||
import ani.rss.entity.Config;
|
||||
import ani.rss.entity.NotificationConfig;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.NotificationTypeEnum;
|
||||
import ani.rss.notification.BaseNotification;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.core.thread.ExecutorBuilder;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@Slf4j
|
||||
public class NotificationUtil {
|
||||
private static final ExecutorService EXECUTOR_SERVICE = ExecutorBuilder.create()
|
||||
.setCorePoolSize(1)
|
||||
.setMaxPoolSize(1)
|
||||
.setWorkQueue(new LinkedBlockingQueue<>(256))
|
||||
.build();
|
||||
|
||||
public static synchronized void send(Config config, Ani ani, String text, NotificationStatusEnum notificationStatusEnum) {
|
||||
Boolean isMessage = Opt.ofNullable(ani)
|
||||
.map(Ani::getMessage)
|
||||
.orElse(true);
|
||||
|
||||
if (!isMessage) {
|
||||
// 未开启此订阅通知
|
||||
return;
|
||||
}
|
||||
|
||||
List<NotificationConfig> notificationConfigList = config.getNotificationConfigList();
|
||||
|
||||
for (NotificationConfig notificationConfig : notificationConfigList) {
|
||||
Boolean enable = notificationConfig.getEnable();
|
||||
NotificationTypeEnum notificationType = notificationConfig.getNotificationType();
|
||||
|
||||
if (!enable) {
|
||||
// 未开启
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!AfdianUtil.verifyExpirationTime()) {
|
||||
if (NotificationStatusEnum.COMPLETED == notificationStatusEnum) {
|
||||
log.warn("未解锁捐赠, 无法使用订阅完结通知");
|
||||
continue;
|
||||
}
|
||||
if (NotificationStatusEnum.ALIST_UPLOAD == notificationStatusEnum) {
|
||||
log.warn("未解锁捐赠, 无法使用Alist上传通知");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BaseNotification baseNotification = ReflectUtil.newInstance(notificationType.getAClass());
|
||||
EXECUTOR_SERVICE.execute(() -> {
|
||||
try {
|
||||
baseNotification.send(notificationConfig, ani, text, notificationStatusEnum);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package ani.rss.util;
|
||||
import ani.rss.action.ClearCacheAction;
|
||||
import ani.rss.download.BaseDownload;
|
||||
import ani.rss.entity.*;
|
||||
import ani.rss.enums.MessageEnum;
|
||||
import ani.rss.enums.NotificationStatusEnum;
|
||||
import ani.rss.enums.StringEnum;
|
||||
import ani.rss.enums.TorrentsTags;
|
||||
import cn.hutool.core.date.DateField;
|
||||
@@ -260,7 +260,7 @@ public class TorrentUtil {
|
||||
}
|
||||
if (currentDownloadCount >= totalEpisodeNumber) {
|
||||
log.info("{} 第 {} 季 共 {} 集 已全部下载完成, 自动停止订阅", title, season, totalEpisodeNumber);
|
||||
MessageUtil.send(config, ani, StrFormatter.format("{} 订阅已完结", title), MessageEnum.COMPLETED);
|
||||
NotificationUtil.send(config, ani, StrFormatter.format("{} 订阅已完结", title), NotificationStatusEnum.COMPLETED);
|
||||
ani.setEnable(false);
|
||||
AniUtil.sync();
|
||||
}
|
||||
@@ -693,7 +693,7 @@ public class TorrentUtil {
|
||||
if (!master) {
|
||||
text = StrFormatter.format("(备用RSS) {}", text);
|
||||
}
|
||||
MessageUtil.send(ConfigUtil.CONFIG, ani, text, MessageEnum.DOWNLOAD_START);
|
||||
NotificationUtil.send(ConfigUtil.CONFIG, ani, text, NotificationStatusEnum.DOWNLOAD_START);
|
||||
|
||||
try {
|
||||
createTvShowNfo(savePath, ani);
|
||||
@@ -716,9 +716,9 @@ public class TorrentUtil {
|
||||
log.error("{} 下载失败将进行重试, 当前重试次数为{}次", name, i);
|
||||
}
|
||||
log.error("{} 添加失败,疑似为坏种", name);
|
||||
MessageUtil.send(ConfigUtil.CONFIG, ani,
|
||||
NotificationUtil.send(ConfigUtil.CONFIG, ani,
|
||||
StrFormatter.format("{} 添加失败,疑似为坏种", name),
|
||||
MessageEnum.ERROR);
|
||||
NotificationStatusEnum.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -864,7 +864,7 @@ public class TorrentUtil {
|
||||
if (tags.contains(TorrentsTags.BACK_RSS.getValue())) {
|
||||
text = StrFormatter.format("(备用RSS) {}", text);
|
||||
}
|
||||
MessageUtil.send(ConfigUtil.CONFIG, ani, text, MessageEnum.DOWNLOAD_END);
|
||||
NotificationUtil.send(ConfigUtil.CONFIG, ani, text, NotificationStatusEnum.DOWNLOAD_END);
|
||||
|
||||
if (Objects.isNull(ani)) {
|
||||
return;
|
||||
|
||||
@@ -1,360 +0,0 @@
|
||||
<template>
|
||||
<el-collapse v-model="messageActiveName" accordion>
|
||||
<el-collapse-item title="通知设置" name="0">
|
||||
<div style="margin-bottom: 12px;">
|
||||
<div style="margin-bottom: 12px;margin-top: 4px;">
|
||||
<el-input v-model:model-value="props.config.messageTemplate" type="textarea"
|
||||
placeholder="${text}" :autosize="{ minRows: 2}"/>
|
||||
<div class="flex" style="width: 100%;justify-content: end;">
|
||||
<a target="_blank" href="https://docs.wushuo.top/config/message">通知模版示例</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-checkbox-group v-model:model-value="config.messageList">
|
||||
<el-checkbox label="开始下载" value="DOWNLOAD_START"/>
|
||||
<el-checkbox label="下载完成" value="DOWNLOAD_END"/>
|
||||
<el-checkbox label="缺集" value="OMIT"/>
|
||||
<el-checkbox label="错误" value="ERROR"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="Alist上传通知" value="ALIST_UPLOAD"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="订阅完结" value="COMPLETED"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="摸鱼检测" value="PROCRASTINATING"/>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div>
|
||||
<el-text class="mx-1" size="small">
|
||||
下载完成通知暂不支持 Aria2、Alist
|
||||
</el-text>
|
||||
<br>
|
||||
<AfdianPrompt :config="props.config" name="Alist上传通知、订阅完结、摸鱼检测"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="TG通知" name="1">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="Api Host">
|
||||
<el-input v-model:model-value="props.config.telegramApiHost"
|
||||
:disabled="config.telegram"
|
||||
placeholder="https://api.telegram.org"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Token">
|
||||
<el-input v-model:model-value="props.config.telegramBotToken" :disabled="config.telegram"
|
||||
placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="ChatId">
|
||||
<div>
|
||||
<div style="justify-content: space-between;width: 100%;" class="auto">
|
||||
<div style="margin-top: 4px;margin-right: 4px;">
|
||||
<el-input v-model:model-value="props.config.telegramChatId" :disabled="config.telegram"
|
||||
placeholder="123456789"/>
|
||||
</div>
|
||||
<div class="flex" style="margin-top: 4px;align-items: center;">
|
||||
<div>
|
||||
<el-select v-model:model-value="chatId" @change="chatIdChange" style="width: 160px"
|
||||
:disabled="config.telegram">
|
||||
<el-option v-for="item in Object.keys(chatIdMap)"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="margin-left: 4px;">
|
||||
<el-button icon="Refresh" bg text @click="getUpdates" :loading="getUpdatesLoading"
|
||||
:disabled="config.telegram"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="话题ID">
|
||||
<el-input-number v-model="props.config.telegramTopicId" :disabled="config.telegram"
|
||||
:min="-1" style="width: 160px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片">
|
||||
<el-switch v-model:model-value="props.config.telegramImage" :disabled="config.telegram"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="格式">
|
||||
<div style="width: 160px;">
|
||||
<el-select v-model:model-value="props.config.telegramFormat" :disabled="config.telegram" placeholder="None">
|
||||
<el-option label="None" value=""/>
|
||||
<el-option label="Markdown" value="Markdown"/>
|
||||
<el-option label="HTML" value="HTML"/>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="开关">
|
||||
<div style="width: 100%;display: flex;justify-content: space-between;">
|
||||
<el-switch v-model:model-value="props.config.telegram"/>
|
||||
<el-button bg text @click="messageTest('Telegram')"
|
||||
:loading="messageTestLoading && messageTestType === 'Telegram'"
|
||||
:disabled="!config.telegram" icon="Odometer">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="邮箱通知" name="2">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="SMTP地址">
|
||||
<el-input v-model:model-value="props.config.mailAccount.host" :disabled="config.mail"
|
||||
placeholder="smtp.xx.com"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="SMTP端口">
|
||||
<el-input-number v-model:model-value="props.config.mailAccount.port" :min="1" :max="65535"
|
||||
:disabled="config.mail"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发件人邮箱">
|
||||
<el-input v-model:model-value="props.config.mailAccount.from" :disabled="config.mail"
|
||||
placeholder="xx@xx.com"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码">
|
||||
<el-input v-model:model-value="props.config.mailAccount.pass" show-password :disabled="config.mail"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="SSL">
|
||||
<el-switch v-model:model-value="props.config.mailAccount.sslEnable" :disabled="config.mail"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="STARTTLS">
|
||||
<el-switch v-model:model-value="props.config.mailAccount['starttlsEnable']" :disabled="config.mail"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="收件人邮箱">
|
||||
<el-input v-model:model-value="props.config.mailAddressee" :disabled="config.mail"
|
||||
placeholder="xx@xx.com"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片">
|
||||
<el-switch v-model:model-value="props.config.mailImage" :disabled="config.mail"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开关">
|
||||
<div style="width: 100%;display: flex;justify-content: space-between;">
|
||||
<el-switch v-model:model-value="props.config.mail"></el-switch>
|
||||
<el-button bg text @click="messageTest('Mail')" :loading="messageTestLoading && messageTestType === 'Mail'"
|
||||
:disabled="!config.mail" icon="Odometer">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Server酱" name="3">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="Type">
|
||||
<el-select v-model="props.config.serverChanType" :disabled="config.serverChan">
|
||||
<el-option
|
||||
v-for="(value, label) in { 'server酱': 'serverChan', 'server酱³': 'serverChan3' }"
|
||||
:key="label"
|
||||
:label="label"
|
||||
:value="value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="sendKey" v-if="props.config.serverChanType === 'serverChan'">
|
||||
<el-input v-model="props.config.serverChanSendKey" placeholder="1234567890"
|
||||
:disabled="config.serverChan"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="apiUrl" v-else-if="props.config.serverChanType === 'serverChan3'">
|
||||
<el-input v-model="props.config.serverChan3ApiUrl"
|
||||
:disabled="config.serverChan"
|
||||
placeholder="https://<uid>.push.ft07.com/send/<sendKey>.send"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="事件标题">
|
||||
<el-switch v-model="props.config['serverChanTitleAction']"
|
||||
:disabled="!config.serverChan"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开关">
|
||||
<div style="display: flex;width: 100%;justify-content: space-between;">
|
||||
<el-switch v-model:model-value="props.config.serverChan"/>
|
||||
<el-button bg text @click="messageTest('ServerChan')"
|
||||
:loading="messageTestLoading && messageTestType === 'ServerChan'"
|
||||
:disabled="!config.serverChan" icon="Odometer">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="4" title="系统通知">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="开关">
|
||||
<div style="display: flex;width: 100%;justify-content: space-between;">
|
||||
<el-switch v-model:model-value="props.config.systemMsg"/>
|
||||
<el-button :disabled="!config.systemMsg" :loading="messageTestLoading" bg
|
||||
icon="Odometer"
|
||||
text @click="messageTest('SystemMsg')">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="WebHook" name="5">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="Method">
|
||||
<el-select v-model:model-value="props.config.webHookMethod">
|
||||
<el-option v-for="item in ['POST','GET','PUT','DELETE']"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="URL">
|
||||
<el-input v-model:model-value="props.config.webHookUrl" type="textarea"
|
||||
autosize
|
||||
placeholder="http://www.xxx.com?text=test_${message}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Body">
|
||||
<el-input v-model:model-value="props.config.webHookBody" type="textarea"
|
||||
:autosize="{ minRows: 2}"
|
||||
placeholder='{"text":"test_${message}"}'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="开关">
|
||||
<div style="display: flex;width: 100%;justify-content: space-between;">
|
||||
<el-switch v-model:model-value="props.config.webHook"/>
|
||||
<el-button bg text @click="messageTest('WebHook')"
|
||||
:loading="messageTestLoading && messageTestType === 'WebHook'"
|
||||
:disabled="!config.webHook" icon="Odometer">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div style="display: flex;justify-content: end;">
|
||||
<a target="_blank" href="https://docs.wushuo.top/config/message">通知模版示例</a>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="6" title="Emby媒体库刷新">
|
||||
<el-form label-width="auto" @submit="(event)=>{
|
||||
event.preventDefault()
|
||||
}">
|
||||
<el-form-item label="EmbyHost">
|
||||
<el-input v-model="props.config['embyHost']" placeholder="http://x.x.x.x:8096"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Emby密钥">
|
||||
<el-input v-model="props.config['embyApiKey']"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="媒体库">
|
||||
<div>
|
||||
<el-checkbox-group v-model="props.config['embyRefreshViewIds']">
|
||||
<el-checkbox
|
||||
v-for="view in views"
|
||||
:key="view.id"
|
||||
:label="view.name"
|
||||
:value="view.id"/>
|
||||
</el-checkbox-group>
|
||||
<div>
|
||||
<el-button :loading="getEmbyViewsLoading" bg icon="Refresh" text @click="getEmbyViews"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="延迟">
|
||||
<el-input-number v-model="props.config['embyDelayed']" :min="0">
|
||||
<template #suffix>
|
||||
<span>秒</span>
|
||||
</template>
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启">
|
||||
<el-switch v-model="props.config['embyRefresh']" :disabled="!props.config['verifyExpirationTime']"/>
|
||||
</el-form-item>
|
||||
<div class="flex" style="justify-content: space-between;width: 100%;">
|
||||
<AfdianPrompt :config="props.config" name="Emby媒体库刷新"/>
|
||||
<el-button :loading="messageTestLoading" bg
|
||||
icon="Odometer"
|
||||
text @click="messageTest('EmbyRefresh')">测试
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import {ElMessage} from "element-plus";
|
||||
import api from "../js/api.js";
|
||||
import AfdianPrompt from "../other/AfdianPrompt.vue";
|
||||
|
||||
const chatIdMap = ref({})
|
||||
const chatId = ref('')
|
||||
const getUpdatesLoading = ref(false)
|
||||
|
||||
const views = ref([])
|
||||
|
||||
const getEmbyViewsLoading = ref(false)
|
||||
|
||||
const getEmbyViews = () => {
|
||||
getEmbyViewsLoading.value = true
|
||||
api.post('api/emby?type=getViews', props.config)
|
||||
.then(res => {
|
||||
views.value = res.data
|
||||
})
|
||||
.finally(() => {
|
||||
getEmbyViewsLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.config['embyHost'] && props.config['embyApiKey']) {
|
||||
getEmbyViews()
|
||||
}
|
||||
})
|
||||
|
||||
const getUpdates = () => {
|
||||
if (!props.config.telegramBotToken.length) {
|
||||
ElMessage.error('Token 不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
getUpdatesLoading.value = true
|
||||
api.post("api/telegram?method=getUpdates", props.config)
|
||||
.then(res => {
|
||||
chatIdMap.value = res.data
|
||||
if (Object.keys(chatIdMap.value).length) {
|
||||
chatId.value = Object.keys(chatIdMap.value)[0]
|
||||
chatIdChange(chatId.value)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
getUpdatesLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const chatIdChange = (k) => {
|
||||
props.config.telegramChatId = chatIdMap.value[k]
|
||||
}
|
||||
|
||||
const messageTestLoading = ref(false)
|
||||
const messageTestType = ref('')
|
||||
|
||||
const messageTest = (type) => {
|
||||
messageTestType.value = type
|
||||
messageTestLoading.value = true
|
||||
|
||||
let config = JSON.parse(JSON.stringify(props.config))
|
||||
config.embyDelayed = 0
|
||||
|
||||
api.post("api/message?type=" + type, config)
|
||||
.then(res => {
|
||||
ElMessage.success(res.message)
|
||||
})
|
||||
.finally(() => {
|
||||
messageTestLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const messageActiveName = ref('0')
|
||||
|
||||
let props = defineProps(['config'])
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1000px) {
|
||||
.auto {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
74
ui/src/config/Notification.vue
Normal file
74
ui/src/config/Notification.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div style="margin-bottom: 12px;margin-top: 4px;">
|
||||
<el-input v-model:model-value="props.config['notificationTemplate']" type="textarea"
|
||||
placeholder="${text}" :autosize="{ minRows: 2}"/>
|
||||
<div class="flex" style="width: 100%;justify-content: end;">
|
||||
<a target="_blank" href="https://docs.wushuo.top/config/message">通知模版示例</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<el-space wrap class="flex flex-wrap gap-4" size="small">
|
||||
<el-card v-for="it in props.config['notificationConfigList']" shadow="never" style="min-width: 240px">
|
||||
<div style="align-items: center;justify-content: space-between;" class="flex">
|
||||
<div>
|
||||
<p>
|
||||
{{ getLabel(it['notificationType']) }}
|
||||
</p>
|
||||
<el-text size="small">
|
||||
{{ it['comment'] ? it['comment'] : '无备注' }}
|
||||
</el-text>
|
||||
</div>
|
||||
<div>
|
||||
<el-button icon="Edit" bg text type="primary" @click="notificationConfigRef?.show(it)"/>
|
||||
<el-button icon="Delete" bg text type="danger" @click="del(it)"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
<el-button
|
||||
icon="FolderAdd"
|
||||
bg text
|
||||
type="primary"
|
||||
@click="add"
|
||||
style="margin-top: 12px;"
|
||||
>
|
||||
添加通知类型
|
||||
</el-button>
|
||||
</div>
|
||||
<NotificationConfig ref="notificationConfigRef" v-model:config="props.config"/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NotificationConfig from "./NotificationConfig.vue";
|
||||
import {ref} from "vue";
|
||||
|
||||
import {getLabel} from "../js/notification-type.js";
|
||||
import api from "../js/api.js";
|
||||
|
||||
let add = () => {
|
||||
api.post('api/notification?type=add')
|
||||
.then((res) => {
|
||||
props.config['notificationConfigList'].push(res.data)
|
||||
notificationConfigRef.value?.show(res.data)
|
||||
})
|
||||
}
|
||||
|
||||
let del = (it) => {
|
||||
props.config['notificationConfigList'] = props.config['notificationConfigList'].filter(item => item !== it)
|
||||
}
|
||||
|
||||
let notificationConfigRef = ref()
|
||||
|
||||
|
||||
let props = defineProps(['config'])
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1000px) {
|
||||
.auto {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
124
ui/src/config/NotificationConfig.vue
Normal file
124
ui/src/config/NotificationConfig.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" center title="修改通知">
|
||||
<el-scrollbar style="height: 400px;padding: 15px;">
|
||||
<el-form label-width="auto">
|
||||
<el-form-item label="通知类型">
|
||||
<el-select v-model="notificationConfig['notificationType']">
|
||||
<el-option :label="it.label" :value="it.name" :key="it.name" v-for="it in notificationTypeList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="notificationConfig['comment']" placeholder="无备注"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知状态">
|
||||
<el-checkbox-group v-model:model-value="notificationConfig['statusList']">
|
||||
<el-checkbox label="开始下载" value="DOWNLOAD_START"/>
|
||||
<el-checkbox label="下载完成" value="DOWNLOAD_END"/>
|
||||
<el-checkbox label="缺集" value="OMIT"/>
|
||||
<el-checkbox label="错误" value="ERROR"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="Alist上传通知" value="ALIST_UPLOAD"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="订阅完结" value="COMPLETED"/>
|
||||
<el-checkbox :disabled="!props.config['verifyExpirationTime']" label="摸鱼检测" value="PROCRASTINATING"/>
|
||||
</el-checkbox-group>
|
||||
<AfdianPrompt :config="props.config" name="Alist上传通知、订阅完结、摸鱼检测"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知模版">
|
||||
<el-input v-model:model-value="notificationConfig['notificationTemplate']" type="textarea"
|
||||
placeholder="${text}" :autosize="{ minRows: 2}"/>
|
||||
</el-form-item>
|
||||
<EmbyRefreshNotification v-model:notification-config="notificationConfig" v-model:config="props.config"/>
|
||||
<MailNotification v-model:notification-config="notificationConfig" v-model:config="props.config"/>
|
||||
<ServerChanNotification v-model:notification-config="notificationConfig" v-model:config="props.config"/>
|
||||
<TelegramNotification v-model:notification-config="notificationConfig" v-model:config="props.config"/>
|
||||
<WebhookNotification v-model:notification-config="notificationConfig" v-model:config="props.config"/>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<div class="flex" style="justify-content: space-between;width: 100%;margin-top: 8px;">
|
||||
<el-button bg text @click="messageTest" icon="Odometer" :loading="messageTestLoading">测试
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false" text bg icon="Check" type="primary">确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import AfdianPrompt from "../other/AfdianPrompt.vue";
|
||||
import EmbyRefreshNotification from "./notification/EmbyRefreshNotification.vue";
|
||||
import MailNotification from "./notification/MailNotification.vue";
|
||||
import ServerChanNotification from "./notification/ServerChanNotification.vue";
|
||||
import TelegramNotification from "./notification/TelegramNotification.vue";
|
||||
import WebhookNotification from "./notification/WebhookNotification.vue";
|
||||
|
||||
import {notificationTypeList} from "../js/notification-type.js";
|
||||
import {ElMessage} from "element-plus";
|
||||
import api from "../js/api.js";
|
||||
|
||||
let notificationConfig = ref({
|
||||
"comment": "无备注",
|
||||
"notificationTemplate": "${notification}",
|
||||
"notificationType": "TELEGRAM",
|
||||
"mailSMTPHost": "smtp.qq.com",
|
||||
"mailSMTPPort": 465,
|
||||
"mailFrom": "",
|
||||
"mailPassword": "",
|
||||
"mailSSLEnable": true,
|
||||
"mailTLSEnable": false,
|
||||
"mailAddressee": "",
|
||||
"mailImage": true,
|
||||
"serverChanType": "SERVER_CHAN",
|
||||
"serverChanSendKey": "",
|
||||
"serverChan3ApiUrl": "",
|
||||
"serverChanTitleAction": true,
|
||||
"telegramBotToken": "",
|
||||
"telegramChatId": "",
|
||||
"telegramTopicId": -1,
|
||||
"telegramApiHost": "https://api.telegram.org",
|
||||
"telegramImage": true,
|
||||
"telegramFormat": "",
|
||||
"webHookMethod": "POST",
|
||||
"webHookUrl": "",
|
||||
"webHookBody": "",
|
||||
"embyRefresh": false,
|
||||
"embyApiKey": "",
|
||||
"embyRefreshViewIds": [],
|
||||
"embyDelayed": 0,
|
||||
"statusList": [
|
||||
"DOWNLOAD_START",
|
||||
"OMIT",
|
||||
"ERROR"
|
||||
]
|
||||
})
|
||||
|
||||
const messageTestLoading = ref(false)
|
||||
|
||||
const messageTest = () => {
|
||||
messageTestLoading.value = true
|
||||
|
||||
let config = JSON.parse(JSON.stringify(notificationConfig.value))
|
||||
config.embyDelayed = 0
|
||||
|
||||
api.post("api/notification?type=test", config)
|
||||
.then(res => {
|
||||
ElMessage.success(res.message)
|
||||
})
|
||||
.finally(() => {
|
||||
messageTestLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
let dialogVisible = ref(false)
|
||||
|
||||
let props = defineProps(['config'])
|
||||
|
||||
let show = (newNotificationConfig) => {
|
||||
notificationConfig.value = newNotificationConfig
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
|
||||
</script>
|
||||
66
ui/src/config/notification/EmbyRefreshNotification.vue
Normal file
66
ui/src/config/notification/EmbyRefreshNotification.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<template v-if="props.notificationConfig['notificationType'] === 'EMBY_REFRESH'">
|
||||
<el-form-item label="EmbyHost">
|
||||
<el-input v-model="props.notificationConfig['embyHost']" placeholder="http://x.x.x.x:8096"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Emby密钥">
|
||||
<el-input v-model="props.notificationConfig['embyApiKey']"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="媒体库">
|
||||
<div>
|
||||
<el-checkbox-group v-model="props.notificationConfig['embyRefreshViewIds']">
|
||||
<el-checkbox
|
||||
v-for="view in views"
|
||||
:key="view.id"
|
||||
:label="view.name"
|
||||
:value="view.id"/>
|
||||
</el-checkbox-group>
|
||||
<div>
|
||||
<el-button :loading="getEmbyViewsLoading" bg icon="Refresh" text @click="getEmbyViews"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="延迟">
|
||||
<el-input-number v-model="props.notificationConfig['embyDelayed']" :min="0">
|
||||
<template #suffix>
|
||||
<span>秒</span>
|
||||
</template>
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启">
|
||||
<el-switch v-model="props.notificationConfig['enable']" :disabled="!props.config['verifyExpirationTime']"/>
|
||||
</el-form-item>
|
||||
<div class="flex" style="justify-content: space-between;width: 100%;">
|
||||
<AfdianPrompt :config="props.config" name="Emby媒体库刷新"/>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AfdianPrompt from "../../other/AfdianPrompt.vue";
|
||||
import {onMounted, ref} from "vue";
|
||||
import api from "../../js/api.js";
|
||||
|
||||
const views = ref([])
|
||||
|
||||
const getEmbyViewsLoading = ref(false)
|
||||
|
||||
const getEmbyViews = () => {
|
||||
getEmbyViewsLoading.value = true
|
||||
api.post('api/emby?type=getViews', props.config)
|
||||
.then(res => {
|
||||
views.value = res.data
|
||||
})
|
||||
.finally(() => {
|
||||
getEmbyViewsLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.notificationConfig['embyHost'] && props.notificationConfig['embyApiKey']) {
|
||||
getEmbyViews()
|
||||
}
|
||||
})
|
||||
|
||||
let props = defineProps(['notificationConfig', 'config'])
|
||||
</script>
|
||||
34
ui/src/config/notification/MailNotification.vue
Normal file
34
ui/src/config/notification/MailNotification.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<template v-if="props.notificationConfig['notificationType'] === 'MAIL'">
|
||||
<el-form-item label="SMTP地址">
|
||||
<el-input v-model:model-value="props.notificationConfig['mailSMTPHost']" placeholder="smtp.qq.com"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="SMTP端口">
|
||||
<el-input-number v-model:model-value="props.notificationConfig['mailSMTPPort']" :min="1" :max="65535"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发件人邮箱">
|
||||
<el-input v-model:model-value="props.notificationConfig['mailFrom']"
|
||||
placeholder="xx@qq.com"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码">
|
||||
<el-input v-model:model-value="props.notificationConfig['mailPassword']" show-password/>
|
||||
</el-form-item>
|
||||
<el-form-item label="SSL">
|
||||
<el-switch v-model:model-value="props.notificationConfig['mailSSLEnable']"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="STARTTLS">
|
||||
<el-switch v-model:model-value="props.notificationConfig['mailTLSEnable']"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="收件人邮箱">
|
||||
<el-input v-model:model-value="props.notificationConfig['mailAddressee']"
|
||||
placeholder="xx@xx.com"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片">
|
||||
<el-switch v-model:model-value="props.notificationConfig['mailImage']"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let props = defineProps(['notificationConfig', 'config'])
|
||||
</script>
|
||||
28
ui/src/config/notification/ServerChanNotification.vue
Normal file
28
ui/src/config/notification/ServerChanNotification.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<template v-if="props.notificationConfig['notificationType'] === 'SERVER_CHAN'">
|
||||
<el-form-item label="Type">
|
||||
<el-select v-model="props.notificationConfig.serverChanType">
|
||||
<el-option
|
||||
v-for="it in ['serverChan', 'serverChan3']"
|
||||
:key="it"
|
||||
:label="it"
|
||||
:value="it"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="sendKey" v-if="props.notificationConfig.serverChanType === 'serverChan'">
|
||||
<el-input v-model="props.notificationConfig.serverChanSendKey" placeholder="1234567890"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="apiUrl" v-if="props.notificationConfig.serverChanType === 'serverChan3'">
|
||||
<el-input v-model="props.notificationConfig.serverChan3ApiUrl"
|
||||
placeholder="https://<uid>.push.ft07.com/send/<sendKey>.send"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="事件标题">
|
||||
<el-switch v-model="props.notificationConfig['serverChanTitleAction']"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let props = defineProps(['notificationConfig', 'config'])
|
||||
</script>
|
||||
89
ui/src/config/notification/TelegramNotification.vue
Normal file
89
ui/src/config/notification/TelegramNotification.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<template v-if="notificationConfig['notificationType'] === 'TELEGRAM'">
|
||||
<el-form-item label="Api Host">
|
||||
<el-input v-model:model-value="props.notificationConfig['telegramApiHost']"
|
||||
placeholder="https://api.telegram.org"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Token">
|
||||
<el-input v-model:model-value="props.notificationConfig['telegramBotToken']"
|
||||
placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="ChatId">
|
||||
<div>
|
||||
<div style="justify-content: space-between;width: 100%;" class="auto">
|
||||
<div style="margin-top: 4px;margin-right: 4px;">
|
||||
<el-input v-model:model-value="props.notificationConfig['telegramChatId']"
|
||||
placeholder="123456789"/>
|
||||
</div>
|
||||
<div class="flex" style="margin-top: 4px;align-items: center;">
|
||||
<div>
|
||||
<el-select v-model:model-value="chatId" @change="chatIdChange" style="width: 160px">
|
||||
<el-option v-for="item in Object.keys(chatIdMap)"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="margin-left: 4px;">
|
||||
<el-button icon="Refresh" bg text @click="getUpdates" :loading="getUpdatesLoading"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="话题ID">
|
||||
<el-input-number v-model="props.notificationConfig['telegramTopicId']"
|
||||
:min="-1" style="width: 160px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片">
|
||||
<el-switch v-model:model-value="props.notificationConfig['telegramImage']"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="格式">
|
||||
<div style="width: 160px;">
|
||||
<el-select v-model:model-value="props.notificationConfig['telegramFormat']" placeholder="None">
|
||||
<el-option label="None" value=""/>
|
||||
<el-option label="Markdown" value="Markdown"/>
|
||||
<el-option label="HTML" value="HTML"/>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {ElMessage} from "element-plus";
|
||||
import api from "../../js/api.js";
|
||||
import {ref} from "vue";
|
||||
|
||||
let chatIdMap = ref({})
|
||||
let chatId = ref('')
|
||||
let getUpdatesLoading = ref(false)
|
||||
|
||||
let getUpdates = () => {
|
||||
if (!props.notificationConfig.telegramBotToken.length) {
|
||||
ElMessage.error('Token 不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
getUpdatesLoading.value = true
|
||||
api.post("api/telegram?method=getUpdates", props.notificationConfig)
|
||||
.then(res => {
|
||||
chatIdMap.value = res.data
|
||||
if (Object.keys(chatIdMap.value).length) {
|
||||
chatId.value = Object.keys(chatIdMap.value)[0]
|
||||
chatIdChange(chatId.value)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
getUpdatesLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
let chatIdChange = (k) => {
|
||||
props.notificationConfig.telegramChatId = chatIdMap.value[k]
|
||||
}
|
||||
|
||||
let props = defineProps(['notificationConfig', 'config'])
|
||||
|
||||
</script>
|
||||
31
ui/src/config/notification/WebhookNotification.vue
Normal file
31
ui/src/config/notification/WebhookNotification.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<template label-width="auto" v-if="notificationConfig['notificationType'] === 'WEB_HOOK'">
|
||||
<el-form-item label="Method">
|
||||
<el-select v-model:model-value="props.notificationConfig['webHookMethod']">
|
||||
<el-option v-for="item in ['POST','GET','PUT','DELETE']"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="URL">
|
||||
<el-input v-model:model-value="props.notificationConfig['webHookUrl']" type="textarea"
|
||||
autosize
|
||||
placeholder="http://www.xxx.com?text=test_${message}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Body">
|
||||
<el-input v-model:model-value="props.notificationConfig['webHookBody']" type="textarea"
|
||||
:autosize="{ minRows: 2}"
|
||||
placeholder='{"text":"test_${message}"}'></el-input>
|
||||
</el-form-item>
|
||||
<div style="display: flex;justify-content: end;">
|
||||
<a target="_blank" href="https://docs.wushuo.top/config/message">通知模版示例</a>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
|
||||
let props = defineProps(['notificationConfig', 'config'])
|
||||
</script>
|
||||
@@ -26,8 +26,8 @@ import {Ban, Save} from "@vicons/fa";
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
let texts = ref([
|
||||
'不忍直视 1 (请谨慎评价)', '很差 2', '差 3', '较差 4', '不过不失 5',
|
||||
'还行 6','推荐 7','力荐 8','神作 9','超神作 10 (请谨慎评价)'
|
||||
'不忍直视 1 (请谨慎评价)', '很差 2', '差 3', '较差 4', '不过不失 5',
|
||||
'还行 6', '推荐 7', '力荐 8', '神作 9', '超神作 10 (请谨慎评价)'
|
||||
])
|
||||
|
||||
let dialogVisible = ref(false)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</el-icon>
|
||||
<span>全局排除</span>
|
||||
</template>
|
||||
<Exclude ref="exclude" v-model:exclude="config.exclude" :show-text="true"/>
|
||||
<Exclude v-model:exclude="config.exclude" :show-text="true"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="代理设置" :lazy="true">
|
||||
<template #label>
|
||||
@@ -64,7 +64,7 @@
|
||||
</template>
|
||||
<div style="height: 500px;">
|
||||
<el-scrollbar style="padding: 0 12px">
|
||||
<Message ref="messageRef" v-model:config="config" v-model:message-active-name="messageActiveName"/>
|
||||
<Notification ref="notificationRef" v-model:config="config"/>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div style="height: 4px;"></div>
|
||||
@@ -103,7 +103,7 @@ import {ElMessage} from "element-plus";
|
||||
import CryptoJS from "crypto-js";
|
||||
import api from "../js/api.js";
|
||||
import Exclude from "../config/Exclude.vue";
|
||||
import Message from "../config/Message.vue";
|
||||
import Notification from "../config/Notification.vue";
|
||||
import Proxy from "../config/Proxy.vue";
|
||||
import Download from "../config/Download.vue";
|
||||
import Basic from "../config/Basic.vue";
|
||||
@@ -159,32 +159,11 @@ const config = ref({
|
||||
'proxyPort': 8080,
|
||||
'renameSleep': 1,
|
||||
'downloadCount': 0,
|
||||
'mail': false,
|
||||
'mailAddressee': '',
|
||||
'mailAccount': {
|
||||
'downloadToolHost': '',
|
||||
'port': 25,
|
||||
'from': '',
|
||||
'pass': '',
|
||||
'sslEnable': false
|
||||
},
|
||||
'mailImage': true,
|
||||
'login': {
|
||||
'downloadToolUsername': '',
|
||||
'downloadToolPassword': ''
|
||||
},
|
||||
'telegram': false,
|
||||
'telegramBotToken': '',
|
||||
'telegramChatId': '',
|
||||
'telegramTopicId': -1,
|
||||
'telegramApiHost': 'https://api.telegram.org',
|
||||
'webHookUrl': '',
|
||||
'webHookMethod': '',
|
||||
'webHookBody': '',
|
||||
'webHook': false,
|
||||
'qbRenameTitle': true,
|
||||
'qbUseDownloadPath': false,
|
||||
'seasonName': 'Season 1',
|
||||
'showPlaylist': false,
|
||||
'enabledExclude': false,
|
||||
'importExclude': false,
|
||||
@@ -194,17 +173,9 @@ const config = ref({
|
||||
'scoreShow': false,
|
||||
'standbyRss': false,
|
||||
'downloadNew': false,
|
||||
'telegramImage': true,
|
||||
'telegramFormat': '',
|
||||
'innerIP': false,
|
||||
'renameTemplate': '',
|
||||
'messageList': [],
|
||||
'verifyLoginIp': true,
|
||||
'serverChanSendKey': '',
|
||||
'serverChan3ApiUrl': '',
|
||||
'serverChan': false,
|
||||
'serverChanType': '',
|
||||
'systemMsg': false,
|
||||
'loginEffectiveHours': 3,
|
||||
'trackersUpdateUrls': '',
|
||||
'autoTrackersUpdate': false,
|
||||
@@ -212,7 +183,6 @@ const config = ref({
|
||||
'tmdbId': false,
|
||||
'renameDelYear': false,
|
||||
'renameDelTmdbId': false,
|
||||
'messageTemplate': '',
|
||||
'ratioLimit': -2,
|
||||
'seedingTimeLimit': -2,
|
||||
'inactiveSeedingTimeLimit': -2,
|
||||
@@ -222,10 +192,7 @@ const config = ref({
|
||||
|
||||
const activeName = ref('download')
|
||||
|
||||
const exclude = ref()
|
||||
|
||||
const messageActiveName = ref('')
|
||||
const messageRef = ref()
|
||||
const notificationRef = ref()
|
||||
|
||||
const show = (update) => {
|
||||
activeName.value = update ? 'about' : 'download'
|
||||
@@ -261,7 +228,6 @@ defineExpose({
|
||||
show
|
||||
})
|
||||
const emit = defineEmits(['load'])
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -125,10 +125,9 @@
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import {Back, Delete, Edit as EditIcon, Files} from "@element-plus/icons-vue"
|
||||
import {Delete, Edit as EditIcon, Files} from "@element-plus/icons-vue"
|
||||
import Edit from "./Edit.vue";
|
||||
import api from "../js/api.js";
|
||||
import Popconfirm from "../other/Popconfirm.vue";
|
||||
import PlayList from "../play/PlayList.vue";
|
||||
import Cover from "./Cover.vue";
|
||||
import Del from "./Del.vue";
|
||||
|
||||
@@ -68,7 +68,8 @@
|
||||
<div class="flex" style="align-items: center;">
|
||||
<img :src="img(it)" height="40" width="40" @click.stop="open(it.url)">
|
||||
<div class="flex" style="align-items: center;">
|
||||
<el-text :truncated="false" line-clamp="1" size="small" style="margin-left: 4px;line-height: 1.6;">
|
||||
<el-text :truncated="false" line-clamp="1" size="small"
|
||||
style="margin-left: 4px;line-height: 1.6;">
|
||||
{{ it.title }}
|
||||
</el-text>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
target="_blank">
|
||||
{{ group.name }}
|
||||
</el-link>
|
||||
<el-badge v-if="props.ani.tmdb['tmdbGroupId'] === group.id" class="item" style="margin-left: 4px;" type="primary" value="已选择"/>
|
||||
<el-badge v-if="props.ani.tmdb['tmdbGroupId'] === group.id" class="item" style="margin-left: 4px;"
|
||||
type="primary" value="已选择"/>
|
||||
</div>
|
||||
<el-button icon="Select" text @click="select(group)"/>
|
||||
</div>
|
||||
|
||||
30
ui/src/js/notification-type.js
Normal file
30
ui/src/js/notification-type.js
Normal file
@@ -0,0 +1,30 @@
|
||||
export let notificationTypeList = [
|
||||
{
|
||||
name: 'TELEGRAM',
|
||||
label: 'TG通知'
|
||||
},
|
||||
{
|
||||
name: 'MAIL',
|
||||
label: '邮箱通知'
|
||||
},
|
||||
{
|
||||
name: 'SERVER_CHAN',
|
||||
label: 'Server酱'
|
||||
},
|
||||
{
|
||||
name: 'SYSTEM',
|
||||
label: '系统通知'
|
||||
},
|
||||
{
|
||||
name: 'WEB_HOOK',
|
||||
label: 'WebHook'
|
||||
},
|
||||
{
|
||||
name: 'EMBY_REFRESH',
|
||||
label: 'Emby媒体库刷新'
|
||||
}
|
||||
]
|
||||
|
||||
export let getLabel = (name) => {
|
||||
return notificationTypeList.filter(item => item.name === name)[0].label;
|
||||
}
|
||||
Reference in New Issue
Block a user