diff --git a/pom.xml b/pom.xml index 35fc14e..b688616 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,12 @@ kotlin-stdlib ${kotlin.version} + + + redis.clients + jedis + 3.6.0-RC1 + diff --git a/src/main/java/com/yutou/bilibili/BiliBili/Live.java b/src/main/java/com/yutou/bilibili/BiliBili/Live.java index baa41c9..a8f8c50 100644 --- a/src/main/java/com/yutou/bilibili/BiliBili/Live.java +++ b/src/main/java/com/yutou/bilibili/BiliBili/Live.java @@ -112,7 +112,7 @@ public class Live implements ApplicationContextAware { } } - private int reloadLike = 0; + private Date startTime; /** * 开始监听 @@ -133,6 +133,7 @@ public class Live implements ApplicationContextAware { stop(); return; } + startTime=new Date(); HashMap header = new HashMap(); header.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits"); header.put("Sec-WebSocket-Key", "tORCZd8AI6xIyvqvgvI1Vw=="); @@ -180,11 +181,12 @@ public class Live implements ApplicationContextAware { public void onClose(int i, String s, boolean b) { com.yutou.bilibili.Tools.Log.i("连接时间:" + (System.currentTimeMillis() - time)); if (upData.getOfflinelistening() == 1) { - System.err.println(roomId + " 断开连接,重连..."); + Log.i(roomId + " 断开连接,重连..."); try { init = true; heartBeattimer.cancel(); client.close(); + liveOfRoomId.remove(roomId + ""); start(); } catch (Exception e) { Log.e(e); @@ -221,9 +223,7 @@ public class Live implements ApplicationContextAware { if (danmuManager != null) { danmuManager.close(); } - if(liveOfRoomId.contains(roomId+"")){ - liveOfRoomId.remove(roomId+""); - } + liveOfRoomId.remove(roomId+""); if (SaveLive.getInstance().checkLive(roomId)) { SaveLive.getInstance().stop(roomId); } @@ -339,7 +339,7 @@ public class Live implements ApplicationContextAware { switch (json.getString("cmd")) { case "INTERACT_WORD"://普通用户进直播间 danmu = json.getJSONObject("data").getString("uname") + " 进入到直播间"; - //com.yutou.bilibili.Tools.Log.i(danmu); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); liveData.setUid(json.getJSONObject("data").getInteger("uid")); liveData.setType(LiveData.INTERACT_WORD); liveData.setMsg(danmu); @@ -361,11 +361,10 @@ public class Live implements ApplicationContextAware { danmuData.setUname(infoData.getJSONArray(2).getString(1)); if (upData != null && upData.getSavedanmu() == 1) { - Log.i(danmuData.toString()); if (danmuManager != null) danmuManager.addDanmu(danmuData); } - // com.yutou.bilibili.Tools.Log.i(json.toJSONString()); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); break; case "SEND_GIFT"://送礼 data = json.getJSONObject("data"); @@ -392,6 +391,7 @@ public class Live implements ApplicationContextAware { liveData.setRoomid(roomId); info.setGiftuser(info.getGiftuser() + 1); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); break; case "COMBO_SEND"://礼物连击 data = json.getJSONObject("data"); @@ -422,9 +422,9 @@ public class Live implements ApplicationContextAware { liveData.setRoomid(roomId); info.setGiftuser(info.getGiftuser() + 1); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); break; case "ENTRY_EFFECT"://舰长进直播间 - // com.yutou.bilibili.Tools.Log.i("[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间"); info.setVipuserindex(info.getVipuserindex() + 1); danmu = "[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间"; liveData.setUid(json.getJSONObject("data").getInteger("uid")); @@ -433,6 +433,7 @@ public class Live implements ApplicationContextAware { liveData.setRoomid(roomId); liveData.setSubtime(new Date()); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); break; case "LIVE_INTERACTIVE_GAME"://彩色弹幕?通过游戏弹幕 break; @@ -452,6 +453,7 @@ public class Live implements ApplicationContextAware { liveData.setSubtime(new Date()); info.setGiftuser(info.getGiftuser() + 1); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu); break; case "USER_TOAST_MSG": break; @@ -469,6 +471,7 @@ public class Live implements ApplicationContextAware { liveData.setRoomid(roomId); info.setGiftuser(info.getGiftuser() + 1); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,liveData.toString()); break; case "LIVE"://开始直播,不过有在心跳包上做检测了,所以也无所谓? if (upData.getLive() == 1) { @@ -490,6 +493,7 @@ public class Live implements ApplicationContextAware { QQBotManager.getInstance().sendMessage(file, builder.toString()); } }); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,upData.getName()+"开播了!"); break; case "PREPARING":// case "SUPER_CHAT_MESSAGE_JPN": @@ -519,9 +523,11 @@ public class Live implements ApplicationContextAware { liveData.setRoomid(roomId); liveData.setSubtime(new Date()); service.addLiveData(liveData); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,liveData.toString()); } } catch (Exception e) { Log.e(e); + Log.i(AppTools.getToDayTimeToString(startTime),roomId,e.getLocalizedMessage()); try { JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8)); processData(new String(bytes, StandardCharsets.UTF_8), null); diff --git a/src/main/java/com/yutou/bilibili/BiliBili/Tools/SaveLive.java b/src/main/java/com/yutou/bilibili/BiliBili/Tools/SaveLive.java index cc4a3d5..c85b2ad 100644 --- a/src/main/java/com/yutou/bilibili/BiliBili/Tools/SaveLive.java +++ b/src/main/java/com/yutou/bilibili/BiliBili/Tools/SaveLive.java @@ -157,7 +157,8 @@ public class SaveLive { } catch (Exception e) { com.yutou.bilibili.Tools.Log.e(e); Log.i("录制发生意外:" + e.getMessage()); - QQBotManager.getInstance().sendMessage("录制发生意外:" + e.getMessage()); + QQBotManager.getInstance().sendMessage("录制发生意外:" + e.getLocalizedMessage()); + LiveUtils.LiveInfoManager.getInstance().check(roomId); } SaveLive.this.stop(roomId); diff --git a/src/main/java/com/yutou/bilibili/QQBot/QQBotManager.java b/src/main/java/com/yutou/bilibili/QQBot/QQBotManager.java index babe217..7ee5b86 100644 --- a/src/main/java/com/yutou/bilibili/QQBot/QQBotManager.java +++ b/src/main/java/com/yutou/bilibili/QQBot/QQBotManager.java @@ -24,7 +24,6 @@ import org.springframework.context.ApplicationContextAware; import javax.annotation.Resource; import java.io.File; import java.lang.reflect.Field; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -49,6 +48,8 @@ public class QQBotManager implements ApplicationContextAware { private static class QQCommands { private final static String QQ_HELP = "!help"; + private final static String QQ_SYSTEM_LOG = "!log"; + private final static String QQ_SYSTEM_STOP = "!stopliveservice"; private final static String QQ_GET_IP = "!ip"; private final static String QQ_GET_VERSION = "!version"; private final static String QQ_LIVE_LIST = "!列表"; @@ -60,7 +61,7 @@ public class QQBotManager implements ApplicationContextAware { private static QQBotManager botManager = null; private Bot bot; - private static long qqGroup ; + private static long qqGroup; private boolean isLogin = false; private static boolean isInit = false; @@ -73,7 +74,7 @@ public class QQBotManager implements ApplicationContextAware { } public void init() { - if(!((boolean) ConfigTools.load(ConfigTools.CONFIG,"qq_bot"))){ + if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "qq_bot"))) { return; } new Thread(new Runnable() { @@ -230,6 +231,7 @@ public class QQBotManager implements ApplicationContextAware { private void myGroup(String msg) { msg = msg.replace("!", "!").toLowerCase(); + msg=msg.trim(); StringBuilder builder = new StringBuilder(); JSONObject json; String[] cmd = new String[0]; @@ -243,12 +245,17 @@ public class QQBotManager implements ApplicationContextAware { case QQCommands.QQ_GET_VERSION: sendVersion(); break; + case QQCommands.QQ_SYSTEM_STOP: + getInstance().sendMessage("正在停止服务"); + System.out.println("结束进程"); + System.exit(0); + break; case QQCommands.QQ_LIVE_LIST: builder.append("当前正在记录数据的直播间:"); builder.append("\n"); for (Live live : Live.lives) { JSONObject liveJson = LiveUtils.LiveInfoManager.getInstance().getInfo(live.getInfo().getRoomid()); - if(LiveUtils.isLivePlayer(live.getInfo().getRoomid())){ + if (LiveUtils.isLivePlayer(live.getInfo().getRoomid())) { builder.append("【直播中】"); } builder @@ -327,6 +334,26 @@ public class QQBotManager implements ApplicationContextAware { } catch (Exception e) { getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_USE_SAVE + "+空格+roomId"); } + } else if (msg.startsWith(QQCommands.QQ_SYSTEM_LOG)) { + try { + cmd = msg.split(" "); + switch (cmd[1]){ + case "true": + RedisTools.set(1,"live-log","true"); + getInstance().sendMessage("日志设为 true"); + break; + case "false": + RedisTools.set(1,"live-log","false"); + getInstance().sendMessage("日志设为 false"); + break; + default: + getInstance().sendMessage("设置错误,"+QQCommands.QQ_SYSTEM_LOG +" true|false"); + } + } catch (Exception e) { + e.printStackTrace(); + } + }else { + System.out.println("未知指令:"+msg); } } } diff --git a/src/main/java/com/yutou/bilibili/Tools/AppTools.java b/src/main/java/com/yutou/bilibili/Tools/AppTools.java index 9e731c8..d967959 100644 --- a/src/main/java/com/yutou/bilibili/Tools/AppTools.java +++ b/src/main/java/com/yutou/bilibili/Tools/AppTools.java @@ -55,6 +55,8 @@ public class AppTools { } public static String getToDayTime() { return new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + } public static String getToDayTime(Date date) { + return new SimpleDateFormat("yyyy-MM-dd").format(date); } public static Date getToDayStartTime(){ return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(AppTools.getToDayTime() + " " + "00:00",new ParsePosition(0)); diff --git a/src/main/java/com/yutou/bilibili/Tools/Log.java b/src/main/java/com/yutou/bilibili/Tools/Log.java index e76ffe7..a1e4e7c 100644 --- a/src/main/java/com/yutou/bilibili/Tools/Log.java +++ b/src/main/java/com/yutou/bilibili/Tools/Log.java @@ -1,6 +1,14 @@ package com.yutou.bilibili.Tools; + +import java.io.File; +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + public class Log { + private static Logger logger; public static void i(Object log) { if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) return; @@ -17,4 +25,26 @@ public class Log { i(e.getMessage()); e.printStackTrace(); } + public static void i(String timer,int roomId,Object log){ + String logFlag=RedisTools.get("live-log",1); + if(logFlag!=null&&logFlag.equals("true")) { + getLogger("[" + timer.replace(":", "_") + "]" + roomId).log(Level.INFO, log.toString()); + } + } + + public static Logger getLogger(String fileName){ + if(logger==null){ + try { + if(!new File("logs").exists()){ + new File("logs").mkdirs(); + } + logger=Logger.getLogger("Live-Log"); + FileHandler handler=new FileHandler("logs"+ File.separator+fileName+".log"); + logger.addHandler(handler); + } catch (IOException e) { + e.printStackTrace(); + } + } + return logger; + } } diff --git a/src/main/java/com/yutou/bilibili/Tools/RedisTools.java b/src/main/java/com/yutou/bilibili/Tools/RedisTools.java new file mode 100644 index 0000000..00d21dd --- /dev/null +++ b/src/main/java/com/yutou/bilibili/Tools/RedisTools.java @@ -0,0 +1,237 @@ +package com.yutou.bilibili.Tools; + +import com.alibaba.fastjson.JSONObject; +import com.yutou.bilibili.QQBot.QQBotManager; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.JedisPubSub; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Properties; +import java.util.Set; + + +public class RedisTools { + private static boolean isNotInstallRedis = false; + private static String host; + private static int port; + public static int TOKEN_TIMEOUT_DEFAULT = 360; + + private RedisTools() { + + } + + // 写成静态代码块形式,只加载一次,节省资源 + static { + //Properties properties = PropertyUtil.loadProperties("jedis.properties"); + //host = properties.getProperty("redis.host"); + //port = Integer.valueOf(properties.getProperty("redis.port")); + host = "127.0.0.1"; + port = 6379; + } + + public static boolean set(int dbIndex, String key, String value) { + try { + if (isNotInstallRedis) { + return false; + } + Jedis jedis = getRedis(); + jedis.select(dbIndex); + String ret = jedis.set(key, value); + Log.i("Redis set =" + ret); + jedis.close(); + } catch (Exception e) { + // TODO: handle exception + e.printStackTrace(); + return false; + } + return true; + } + + public static boolean set(String key, String value) { + return set(0, key, value); + } + + public static boolean set(String key, String value, int timeout) { + try { + if (isNotInstallRedis) { + return false; + } + Jedis jedis = getRedis(); + if (timeout == -1) { + jedis.set(key, value); + } else { + jedis.setex(key, timeout, value); + } + jedis.close(); + } catch (Exception e) { + // TODO: handle exception + e.printStackTrace(); + return false; + } + return true; + } + + public static String get(String key, int dbIndex) { + String value = "-999"; + if (isNotInstallRedis) { + return value; + } + try (Jedis jedis = getRedis()) { + jedis.select(dbIndex); + value = jedis.get(key); + jedis.close(); + } catch (Exception e) { + // TODO: handle exception + // e.printStackTrace(); + } + return value; + } + + public static String get(String key) { + return get(key, 0); + } + + public static boolean remove(String key) { + return remove(key,0); + } + + public static void removeLoginState(String uid) { + Jedis jedis = getRedis(); + Set keys = jedis.keys("*"); + for (String string : keys) { + if (string.equals(uid)) { + jedis.del(string); + } + } + + } + + public static String ping() { + Jedis jedis = getRedis(); + String tmp = jedis.ping(); + jedis.close(); + return tmp; + } + + public static boolean exists(String key, String value) { + if (isNotInstallRedis) { + return false; + } + Jedis jedis = getRedis(); + boolean flag = value.equals(jedis.get(key)); + jedis.close(); + return flag; + } + + public static Jedis getRedis() { + return new Jedis(host, port); + } + + public static boolean remove(String key, int index) { + if (isNotInstallRedis) { + return false; + } + Jedis jedis = getRedis(); + jedis.select(index); + Long i = jedis.del(key); + jedis.close(); + if (i > 0) { + return true; + } else { + return false; + } + } + + private static class PropertyUtil { + + // 加载property文件到io流里面 + public static Properties loadProperties(String propertyFile) { + Properties properties = new Properties(); + try { + InputStream is = PropertyUtil.class.getClassLoader().getResourceAsStream(propertyFile); + if (is == null) { + is = PropertyUtil.class.getClassLoader().getResourceAsStream(propertyFile); + } + properties.load(is); + } catch (IOException e) { + e.printStackTrace(); + } + return properties; + } + } + + private static Jedis getPoolRedis() { + if (isNotInstallRedis) { + return null; + } + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMaxIdle(0); + poolConfig.setMaxWaitMillis(1000); + JedisPool pool = new JedisPool(poolConfig, host); + return pool.getResource(); + } + + public static void pullMsg(String channel, String msg) { + Jedis jedis = getPoolRedis(); + jedis.publish(channel, msg); + jedis.close(); + } + + private static boolean init = false; + + public static void initRedisPoolSub() { + if (init) + return; + init = true; + Log.i("初始化订阅"); + new Thread(new Runnable() { + @Override + public void run() { + Jedis jedis = getPoolRedis(); + if (jedis != null) + jedis.psubscribe(new Consumer(), "*"); + } + }).start(); + + } + + protected static class Consumer extends JedisPubSub { + @Override + public void onPMessage(String pattern, String channel, String message) { + super.onPMessage(pattern, channel, message); + Log.i("onPMessage: channel=" + channel + " msg=" + message + " pattern=" + pattern); + switch (channel) { + case "bot": + bot(message); + break; + } + } + + @Override + public void onMessage(String channel, String message) { + super.onMessage(channel, message); + Log.i("onMessage: channel=" + channel + " msg=" + message); + } + + + + + public static void bot(String value) { + switch (value) { + case "getip": + JSONObject json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/")); + String ip = json.getString("ip"); + QQBotManager.getInstance().sendMessage("服务器IP:\n" + ip); + break; + } + } + } + public static void main(String[] args) { + RedisTools.pullMsg("msg", "abc"); + } +} diff --git a/src/main/java/com/yutou/bilibili/sqlite/BiliBiliLiveDatabasesManager.java b/src/main/java/com/yutou/bilibili/sqlite/BiliBiliLiveDatabasesManager.java index 6aa0e1f..c16c08a 100644 --- a/src/main/java/com/yutou/bilibili/sqlite/BiliBiliLiveDatabasesManager.java +++ b/src/main/java/com/yutou/bilibili/sqlite/BiliBiliLiveDatabasesManager.java @@ -47,7 +47,6 @@ public class BiliBiliLiveDatabasesManager extends SQLiteManager { ,data.getUid() ,data.getUname() ); - Log.i(sql); statement.execute(sql); statement.closeOnCompletion(); }catch (Exception e){