diff --git a/pom.xml b/pom.xml index 014e310..84fcef7 100644 --- a/pom.xml +++ b/pom.xml @@ -108,8 +108,8 @@ net.mamoe - mirai-core-qqandroid - 1.3.3 + mirai-core-jvm + 2.0.0-dev-2 org.jetbrains.kotlin diff --git a/src/main/java/com/yutou/tools/ToolsApplication.java b/src/main/java/com/yutou/tools/ToolsApplication.java index da34655..b168a74 100644 --- a/src/main/java/com/yutou/tools/ToolsApplication.java +++ b/src/main/java/com/yutou/tools/ToolsApplication.java @@ -9,7 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ToolsApplication { - public static final String version="1.0.14.2"; + public static final String version="1.0.15"; public static void main(String[] args) { System.out.println("当前版本号:"+version); diff --git a/src/main/java/com/yutou/tools/bangumi/BangumiTools.java b/src/main/java/com/yutou/tools/bangumi/BangumiTools.java index b044325..3c5ffd5 100644 --- a/src/main/java/com/yutou/tools/bangumi/BangumiTools.java +++ b/src/main/java/com/yutou/tools/bangumi/BangumiTools.java @@ -5,31 +5,41 @@ import com.alibaba.fastjson.JSONObject; import com.yutou.tools.utils.HttpTools; import com.yutou.tools.utils.RedisTools; -import java.util.Calendar; -import java.util.Date; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class BangumiTools { private static final String url = "http://api.bgm.tv/"; private static final String toDayBangumi = url + "calendar"; private static final String BangumiInfo = url + "/subject/%s?responseGroup=large"; + private static final String SearchBangumi = url + "/search/subject/%s?responseGroup=large"; /** * 获取番剧列表 + * * @param day 周几,-1为全部,非1~7范围则为当天 * @return 当日数据 */ public static JSONObject getBangumi(int day) { String str = HttpTools.get(toDayBangumi); JSONArray main = JSONArray.parseArray(str); - if(day==-1){ - JSONObject json=new JSONObject(); - json.put("bangumi",main); + if (day == -1) { + JSONObject json = new JSONObject(); + json.put("bangumi", main); return json; } - if(day<1||day>7) { + if (day < 1 || day > 7) { Calendar calendar = Calendar.getInstance(); + calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); + calendar.setFirstDayOfWeek(Calendar.MONDAY); calendar.setTime(new Date()); - day=calendar.get(Calendar.DAY_OF_WEEK); + day = calendar.get(Calendar.DAY_OF_WEEK) - 1; + if (day == 0) { + day = 7; + } } if (main != null) for (Object o : main) { @@ -43,23 +53,238 @@ public class BangumiTools { /** * 获取番剧详细信息 + * * @param id 剧集id * @return 详细信息 */ - public static JSONObject getBangumiInfo(int id){ - String str = HttpTools.get(String.format(BangumiInfo,id+"")); - JSONObject main = JSONObject.parseObject(str); - return main; + public static JSONObject getBangumiInfo(int id) { + String str = HttpTools.get(String.format(BangumiInfo, id + "")); + return JSONObject.parseObject(str); } - public static void reportToDayBangumi(){ - if(!RedisTools.get("reportToDayBangumi").equals("true")){ - JSONObject toDay=getBangumi(0); + /** + * 搜索番剧 + * + * @param key 关键词 + * @return 详细信息 + */ + public static JSONObject search(String key) { + String str = HttpTools.get(String.format(SearchBangumi, key)); + return JSONObject.parseObject(str); + } + /** + * 获取下一集播放日期 + * + * @param id 番剧id + * @return 日期 + */ + public static String getPlayNextTime(int id) { + JSONObject info = getBangumiInfo(id); + JSONArray eps = info.getJSONArray("eps"); + String toDayTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + for (Object o : eps) { + JSONObject ep = (JSONObject) o; + String time = ep.getString("airdate"); + try { + if (new SimpleDateFormat("yyyy-MM-dd").parse(time).getTime() >= + new SimpleDateFormat("yyyy-MM-dd").parse(toDayTime).getTime()) { + return time; + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + return null; + } + + /** + * 格式化字符串输出番剧详细信息 + * + * @param id 番剧id + * @return 详细内容 + */ + public static String reportBangumiInfo(int id) { + JSONObject json = getBangumiInfo(id); + if(json.containsKey("code")){ + return json.getString("error"); + } + JSONArray eps = json.getJSONArray("eps"); + JSONArray crts = json.getJSONArray("crt"); + JSONArray staffs = json.getJSONArray("staff"); + StringBuilder builder = new StringBuilder(); + builder.append("").append("\n"); + builder.append("标题:").append(json.getString("name_cn")).append("\n"); + builder.append("日文标题:").append(json.getString("name")).append("\n"); + builder.append("首播时间:").append(json.getString("air_date")).append("\n"); + builder.append("每周").append(json.getInteger("air_weekday")).append("放送").append("\n"); + builder.append("Bangumi地址:").append(json.getString("url")).append("\n"); + builder.append("Bangumi评分:").append(json.getJSONObject("rating").getFloat("score")).append("\n"); + builder.append("预计放送集数:").append(json.getInteger("eps_count")).append("\n"); + if (eps != null) { + builder.append("已放送集:").append("\n"); + for (Object o : eps) { + JSONObject ep = (JSONObject) o; + if (ep.getString("status").equals("Air")) { + builder.append("· 第").append(ep.getInteger("sort")).append("话:"); + builder.append(ep.getString("name")); + builder.append("[").append(ep.getString("name_cn")).append("]").append("\n"); + builder.append("播放日期:").append(ep.getString("airdate")).append(";\n"); + builder.append("播放时长:").append(ep.getString("duration")).append(";\n"); + builder.append("单集介绍:").append(ep.getString("desc")); + builder.append("\n\n"); + } else { + builder.append("下一话:"); + builder.append(" 第").append(ep.getInteger("sort")).append("话:"); + builder.append("播放日期:").append(ep.getString("airdate")).append("\n\n"); + break; + } + } + } + if (crts != null) { + builder.append("角色介绍:").append("\n"); + for (Object o : crts) { + JSONObject crt = (JSONObject) o; + JSONObject info = crt.getJSONObject("info"); + builder.append(crt.getString("role_name")).append(":"); + builder.append(crt.getString("name")); + builder.append("(").append(crt.getString("name_cn")).append(")").append(" "); + builder.append("CV:").append(crt.getJSONArray("actors").getJSONObject(0).getString("name")); + builder.append("(").append(info.getString("gender")).append(")"); + builder.append("\n"); + } + } + Map> map = new HashMap<>(); + for (Object o : staffs) { + JSONObject staff = (JSONObject) o; + for (Object jobs : staff.getJSONArray("jobs")) { + String job = (String) jobs; + List list; + if (!map.containsKey(job)) { + list = new ArrayList<>(); + } else { + list = map.get(job); + } + list.add(staff); + map.put(job, list); + } + } + if (!map.isEmpty()) { + builder.append("staff:").append("\n"); + for (String key : map.keySet()) { + builder.append(key).append(":"); + for (JSONObject staff : map.get(key)) { + builder.append(staff.getString("name_cn")); + builder.append("(").append(staff.getString("name")).append(")"); + builder.append("、"); + } + builder.append("\n"); + } + } + return builder.toString(); + } + + /** + * 格式化字符串输出今日播放番剧列表 + * + * @return 番剧列表 + */ + public static String reportToDayBangumi() { + if (!RedisTools.get("reportToDayBangumi").equals("true")) { + RedisTools.set("reportToDayBangumi", "true"); + StringBuilder builder = new StringBuilder(); + JSONObject toDay = getBangumi(0); + if (toDay == null) { + builder.append("今天没有任何番剧放送~"); + } else { + JSONObject weekday = toDay.getJSONObject("weekday"); + JSONArray items = toDay.getJSONArray("items"); + builder.append("今日 ").append(weekday.get("cn")).append("(").append(weekday.get("ja")).append(")"); + builder.append(" 放送列表:").append("\n"); + int epIndex = 0; + String epName = "N/A"; + for (Object o : items) { + JSONObject item = (JSONObject) o; + builder.append("[").append(item.getInteger("id")).append("]"); + builder.append(item.getString("name_cn")); + JSONArray eps = getBangumiInfo(item.getInteger("id")).getJSONArray("eps"); + for (Object oe : eps) { + JSONObject ep = (JSONObject) oe; + if (ep.getString("status").equals("Air")) { + epIndex = ep.getInteger("sort"); + epName = ep.getString("name"); + } else { + break; + } + } + builder.append(" 第").append(epIndex).append("话:"); + builder.append(epName); + builder.append("\n"); + } + } + RedisTools.set("toDayBangumi", builder.toString()); + return builder.toString(); + } else { + return RedisTools.get("toDayBangumi"); } } - public static void main(String[] args) { - System.out.println(getBangumiInfo(293193)); + /** + * 格式化字符串输出搜索动画 + * + * @param key 关键词 + * @return 详细内容 + */ + public static String reportSearchBangumi(String key) { + JSONObject main = search(key); + if (main.getInteger("results") > 0) { + StringBuilder builder = new StringBuilder(); + List list = main.getJSONArray("list").toJavaList(JSONObject.class); + Collections.reverse(list); + for (Object items : list) { + JSONObject item = (JSONObject) items; + builder.append("标题:").append(item.getString("name_cn")).append("\n"); + builder.append("日文标题:").append(item.getString("name")).append("\n"); + String type; + switch (item.getInteger("type")) { + case 1: + type = "书籍"; + break; + case 2: + type = "动画"; + break; + case 3: + type = "音乐"; + break; + case 4: + type = "游戏"; + break; + case 6: + type = "真人剧(Real)"; + break; + default: + type = item.getInteger("type") + ""; + } + builder.append("类型:").append(type).append("\n"); + builder.append("id:").append(item.getInteger("id")).append("\n"); + if (item.containsKey("rating")) + builder.append("Bangumi评分:").append(item.getJSONObject("rating").getFloat("score")).append("\n"); + builder.append("首播时间:").append(item.getString("air_date")).append("\n"); + builder.append("每周 ").append(item.getInteger("air_weekday")).append(" 放送").append("\n"); + builder.append("放送集数:").append(item.getInteger("eps")).append("\n"); + builder.append("Bangumi地址:").append(item.getString("url")).append("\n"); + builder.append("介绍:").append(item.getString("summary")).append("\n"); + builder.append("\n").append("\n"); + } + return builder.toString(); + } else { + return "搜索不到任何内容:" + key; + } + } + + public static void main(String[] args) { + String str = reportBangumiInfo(262897); + System.out.println(str); + } } diff --git a/src/main/java/com/yutou/tools/utils/ApplicationInit.java b/src/main/java/com/yutou/tools/utils/ApplicationInit.java index 4c26626..7b7aaef 100644 --- a/src/main/java/com/yutou/tools/utils/ApplicationInit.java +++ b/src/main/java/com/yutou/tools/utils/ApplicationInit.java @@ -5,6 +5,10 @@ import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; /** * 服务启动后执行 @@ -16,5 +20,20 @@ public class ApplicationInit implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { musicTools.init();//初始化音乐库 + new Timer().schedule(new TimerTask() { + @Override + public void run() { + String time = new SimpleDateFormat("HH:mm").format(new Date()); + switch (time){ + case "00:00": + musicTools.scanMusic(); + break; + case "08:00": + QQBotManager.getInstance().reportToDayBangumi(); + break; + + } + } + },0,10 * 1000); } } diff --git a/src/main/java/com/yutou/tools/utils/MusicTools.java b/src/main/java/com/yutou/tools/utils/MusicTools.java index 1361d05..b162c1a 100644 --- a/src/main/java/com/yutou/tools/utils/MusicTools.java +++ b/src/main/java/com/yutou/tools/utils/MusicTools.java @@ -51,16 +51,6 @@ public class MusicTools implements MusicToolsService { public void init() { musicPath = (String) ConfigTools.load(ConfigTools.CONFIG, "musicDir"); scanMusic(); - new Timer().schedule(new TimerTask() { - @Override - public void run() { - String time = new SimpleDateFormat("HH:mm").format(new Date()); - if (time.equals("00:00")) { - System.out.println("零点刷新列表"); - scanMusic(); - } - } - }, 0, 10 * 1000); } @Override diff --git a/src/main/java/com/yutou/tools/utils/QQBotManager.java b/src/main/java/com/yutou/tools/utils/QQBotManager.java index 7b8f3ba..bb26d3e 100644 --- a/src/main/java/com/yutou/tools/utils/QQBotManager.java +++ b/src/main/java/com/yutou/tools/utils/QQBotManager.java @@ -1,26 +1,40 @@ package com.yutou.tools.utils; import com.yutou.tools.ToolsApplication; -import kotlin.coroutines.CoroutineContext; +import com.yutou.tools.bangumi.BangumiTools; +import com.yutou.tools.interfaces.DownloadInterface; import net.mamoe.mirai.Bot; -import net.mamoe.mirai.BotFactoryJvm; -import net.mamoe.mirai.contact.Contact; -import net.mamoe.mirai.event.EventHandler; -import net.mamoe.mirai.event.Events; -import net.mamoe.mirai.event.ListeningStatus; -import net.mamoe.mirai.event.SimpleListenerHost; -import net.mamoe.mirai.message.GroupMessageEvent; -import net.mamoe.mirai.message.MessageEvent; -import net.mamoe.mirai.message.MessageReceipt; +import net.mamoe.mirai.BotFactory; +import net.mamoe.mirai.event.GlobalEventChannel; +import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.message.data.Image; -import net.mamoe.mirai.message.data.MessageChain; -import net.mamoe.mirai.message.data.MessageUtils; +import net.mamoe.mirai.message.data.MessageChainBuilder; import net.mamoe.mirai.utils.BotConfiguration; -import org.jetbrains.annotations.NotNull; +import net.mamoe.mirai.utils.ExternalResource; import java.io.File; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class QQBotManager { + + + private static class QQCommands { + private final static String QQ_HELP = "!help"; + private final static String QQ_UPDATE_IP = "!更新ip"; + private final static String QQ_GET_IP = "!ip"; + private final static String QQ_OPEN_PC = "!开机"; + private final static String QQ_GET_VERSION = "!version"; + private final static String QQ_CMD = "!cmd"; + private final static String QQ_BANGUMI_TODAY = "!今日动画"; + private final static String QQ_BANGUMI_SUB = "!查动画"; + } + private static QQBotManager botManager = null; private Bot bot; private static final long qqGroup = 891655174L; @@ -29,8 +43,8 @@ public class QQBotManager { private QQBotManager() { Object isRun = ConfigTools.load(ConfigTools.CONFIG, "qq_bot"); if (isRun != null && (boolean) isRun) { - init(); isLogin = true; + init(); } } @@ -45,8 +59,9 @@ public class QQBotManager { password = "UAs6YBYMyxJU"; } - bot = BotFactoryJvm.newBot(qq, password, new BotConfiguration() { + bot = BotFactory.INSTANCE.newBot(qq, password, new BotConfiguration() { { + setProtocol(MiraiProtocol.ANDROID_PAD); fileBasedDeviceInfo("qq_bot_devices_info.json"); if (ConfigTools.load(ConfigTools.CONFIG, "model").equals("nas")) { noBotLog(); @@ -54,10 +69,22 @@ public class QQBotManager { } } }); - Events.registerEvents(bot, new MessageListener()); - + //Events.registerEvents(bot, new MessageListener()); + GlobalEventChannel.INSTANCE.subscribeAlways(GroupMessageEvent.class, new MessageListener()); bot.login(); - sendMessage("姬妻酱上线拉~"); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + String str=sendMessage("姬妻酱上线拉~"); + System.out.println(str); + + } + }).start(); bot.join(); } @@ -76,15 +103,25 @@ public class QQBotManager { return isLogin; } + private Image getImage(File file) { + if (bot != null) { + return Objects.requireNonNull(bot.getGroup(qqGroup)).uploadImage(ExternalResource.create(file)); + } + return null; + } + private String getNotLoginQQ() { return "没有登录QQ"; } + public void reportToDayBangumi() { + getInstance().sendMessage(BangumiTools.reportToDayBangumi()); + } public String sendMessage(String text) { if (bot != null) { try { - MessageReceipt receipt = bot.getGroup(qqGroup).sendMessage(text); - return receipt.toString(); + System.out.println("发送QQ"); + return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(text).toString(); } catch (Exception e) { e.printStackTrace(); } @@ -93,66 +130,153 @@ public class QQBotManager { } public String sendMessage(File imageFile, String text) { + try { + if (bot != null) { + Image image = getImage(imageFile); + MessageChainBuilder builder = new MessageChainBuilder(); + if (image != null) { + builder.append(image); + } + builder.append(text); + return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return getNotLoginQQ(); + } + + public String sendMessage(List imgs, String text) { if (bot != null) { - Image image = bot.getGroup(qqGroup).uploadImage(imageFile); - MessageChain chain = MessageUtils.newImage(image.getImageId()).plus(text); - MessageReceipt receipt = bot.getGroup(qqGroup).sendMessage(chain); - return receipt.toString(); + MessageChainBuilder builder = new MessageChainBuilder(); + for (File img : imgs) { + builder.append(Objects.requireNonNull(getImage(img))); + } + builder.append(text); + return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString(); } return getNotLoginQQ(); } + public static List getImages(String str) { + List list = new ArrayList<>(); + String regex = ""; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(str); + while (matcher.find()) { + list.add(matcher.group().replace("", "") + .trim()); + } + return list; + } + public static void main(String[] args) { getInstance(); } - private static class MessageListener extends SimpleListenerHost { - @Override - public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { - super.handleException(context, exception); - System.out.println("error: " + exception.getLocalizedMessage()); - } + private static class MessageListener implements Consumer { - @EventHandler - public ListeningStatus onGroupMessage(GroupMessageEvent event) { + @Override + public void accept(GroupMessageEvent event) { if (event.getGroup().getId() == qqGroup) { String msg = event.getMessage().contentToString(); msg = msg.replace("!", "!").toLowerCase(); switch (msg) { - case "!开机": + case QQCommands.QQ_OPEN_PC: RedisTools.Consumer.system("openPC", null); break; - case "!更新ip": + case QQCommands.QQ_UPDATE_IP: RedisTools.Consumer.system("updateIP", null); break; - case "!ip": + case QQCommands.QQ_GET_IP: RedisTools.Consumer.bot("getip"); break; - case "!version": + case QQCommands.QQ_GET_VERSION: sendVersion(); break; + case QQCommands.QQ_BANGUMI_TODAY: + QQBotManager.getInstance().sendMessage(BangumiTools.reportToDayBangumi()); + break; + case QQCommands.QQ_HELP: + StringBuilder builder=new StringBuilder(); + for (Field field : QQCommands.class.getDeclaredFields()) { + try { + field.setAccessible(true); + builder.append(field.get(null)).append("\n"); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + getInstance().sendMessage(builder.toString()); + break; default: - if (msg.startsWith("!cmd")) { - RedisTools.Consumer.system("cmd", msg.replace("!cmd", "")); + if (msg.startsWith(QQCommands.QQ_CMD)) { + RedisTools.Consumer.system("cmd", msg.replace(QQCommands.QQ_CMD, "")); + } else if (msg.startsWith(QQCommands.QQ_BANGUMI_SUB)) { + String info = null; + try { + int id = Integer.parseInt(msg.replace(QQCommands.QQ_BANGUMI_SUB, "").trim()); + info = BangumiTools.reportBangumiInfo(id); + } catch (Exception e) { + String key=msg.replace(QQCommands.QQ_BANGUMI_SUB, "").trim(); + info = BangumiTools.reportSearchBangumi(key); + } + List imgs=new ArrayList<>(); + if (info.contains("")) { + imgs = getImages(info); + for (String img : imgs) { + info=info.replace("",""); + } + } + sendImagesMsg(imgs,info); } } }/*else{ sendMessage("群:"+event.getGroup().getId()+" 发来消息:\n"+event.getMessage().contentToString()); }*/ - return ListeningStatus.LISTENING; } + private List files; + private int index=0; + private void sendImagesMsg(List imgs,String text){ + files=new ArrayList<>(); + index=0; + if(imgs.size()==0){ + getInstance().sendMessage(text); + return; + } + for (String img : imgs) { + Tools.download(img, new DownloadInterface() { + @Override + public void onDownload(String file) { + super.onDownload(file); + files.add(new File(file)); + send(imgs.size(), text); + } + @Override + public void onError(Exception e) { + super.onError(e); + index++; + send(imgs.size(),text); + } + }); + } + } + private void send(int size,String text){ + if((files.size()+index)==size){ + String str= getInstance().sendMessage(files,text); + System.out.println("str = "+str); + } + } private void sendVersion() { - String localVersion= ToolsApplication.version; - String serverVersion=HttpTools.get("http://tools.yutou233.cn:8000/public/version.do?token=zIrsh9TUZP2lfRW753PannG49E7VJvor"); - String msg="本地版本:"+localVersion+"\n"+"服务器版本:"+serverVersion; + String localVersion = ToolsApplication.version; + String serverVersion = HttpTools.get("http://tools.yutou233.cn:8000/public/version.do?token=zIrsh9TUZP2lfRW753PannG49E7VJvor"); + String msg = "本地版本:" + localVersion + "\n" + "服务器版本:" + serverVersion; QQBotManager.getInstance().sendMessage(msg); - Tools.sendServer("服务版本查询",msg); + Tools.sendServer("服务版本查询", msg); } - @EventHandler - public void onMessage(@NotNull MessageEvent event) throws Exception { - // sendMessage("个人:"+event.getSender().getNick()+" 发来消息:"+event.getMessage().contentToString()); - } } } diff --git a/src/main/java/com/yutou/tools/utils/RedisTools.java b/src/main/java/com/yutou/tools/utils/RedisTools.java index 1ecfec4..8e7bd86 100644 --- a/src/main/java/com/yutou/tools/utils/RedisTools.java +++ b/src/main/java/com/yutou/tools/utils/RedisTools.java @@ -93,6 +93,9 @@ public class RedisTools { if (jedis != null) jedis.close(); } + if(value==null){ + value="-999"; + } return value; }