新增redis

新增直播数据日志存储
修复直播中断不会重连的bug
QQ机器人可支持直接挂断服务
This commit is contained in:
yutou 2021-04-14 11:42:47 +08:00
parent c0a8478d10
commit bd80d17441
8 changed files with 323 additions and 15 deletions

View File

@ -114,6 +114,12 @@
<artifactId>kotlin-stdlib</artifactId> <artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version> <version>${kotlin.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0-RC1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -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(); stop();
return; return;
} }
startTime=new Date();
HashMap<String, String> header = new HashMap<String, String>(); HashMap<String, String> header = new HashMap<String, String>();
header.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits"); header.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits");
header.put("Sec-WebSocket-Key", "tORCZd8AI6xIyvqvgvI1Vw=="); header.put("Sec-WebSocket-Key", "tORCZd8AI6xIyvqvgvI1Vw==");
@ -180,11 +181,12 @@ public class Live implements ApplicationContextAware {
public void onClose(int i, String s, boolean b) { public void onClose(int i, String s, boolean b) {
com.yutou.bilibili.Tools.Log.i("连接时间:" + (System.currentTimeMillis() - time)); com.yutou.bilibili.Tools.Log.i("连接时间:" + (System.currentTimeMillis() - time));
if (upData.getOfflinelistening() == 1) { if (upData.getOfflinelistening() == 1) {
System.err.println(roomId + " 断开连接,重连..."); Log.i(roomId + " 断开连接,重连...");
try { try {
init = true; init = true;
heartBeattimer.cancel(); heartBeattimer.cancel();
client.close(); client.close();
liveOfRoomId.remove(roomId + "");
start(); start();
} catch (Exception e) { } catch (Exception e) {
Log.e(e); Log.e(e);
@ -221,9 +223,7 @@ public class Live implements ApplicationContextAware {
if (danmuManager != null) { if (danmuManager != null) {
danmuManager.close(); danmuManager.close();
} }
if(liveOfRoomId.contains(roomId+"")){ liveOfRoomId.remove(roomId+"");
liveOfRoomId.remove(roomId+"");
}
if (SaveLive.getInstance().checkLive(roomId)) { if (SaveLive.getInstance().checkLive(roomId)) {
SaveLive.getInstance().stop(roomId); SaveLive.getInstance().stop(roomId);
} }
@ -339,7 +339,7 @@ public class Live implements ApplicationContextAware {
switch (json.getString("cmd")) { switch (json.getString("cmd")) {
case "INTERACT_WORD"://普通用户进直播间 case "INTERACT_WORD"://普通用户进直播间
danmu = json.getJSONObject("data").getString("uname") + " 进入到直播间"; 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.setUid(json.getJSONObject("data").getInteger("uid"));
liveData.setType(LiveData.INTERACT_WORD); liveData.setType(LiveData.INTERACT_WORD);
liveData.setMsg(danmu); liveData.setMsg(danmu);
@ -361,11 +361,10 @@ public class Live implements ApplicationContextAware {
danmuData.setUname(infoData.getJSONArray(2).getString(1)); danmuData.setUname(infoData.getJSONArray(2).getString(1));
if (upData != null && upData.getSavedanmu() == 1) { if (upData != null && upData.getSavedanmu() == 1) {
Log.i(danmuData.toString());
if (danmuManager != null) if (danmuManager != null)
danmuManager.addDanmu(danmuData); danmuManager.addDanmu(danmuData);
} }
// com.yutou.bilibili.Tools.Log.i(json.toJSONString()); Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu);
break; break;
case "SEND_GIFT"://送礼 case "SEND_GIFT"://送礼
data = json.getJSONObject("data"); data = json.getJSONObject("data");
@ -392,6 +391,7 @@ public class Live implements ApplicationContextAware {
liveData.setRoomid(roomId); liveData.setRoomid(roomId);
info.setGiftuser(info.getGiftuser() + 1); info.setGiftuser(info.getGiftuser() + 1);
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu);
break; break;
case "COMBO_SEND"://礼物连击 case "COMBO_SEND"://礼物连击
data = json.getJSONObject("data"); data = json.getJSONObject("data");
@ -422,9 +422,9 @@ public class Live implements ApplicationContextAware {
liveData.setRoomid(roomId); liveData.setRoomid(roomId);
info.setGiftuser(info.getGiftuser() + 1); info.setGiftuser(info.getGiftuser() + 1);
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu);
break; break;
case "ENTRY_EFFECT"://舰长进直播间 case "ENTRY_EFFECT"://舰长进直播间
// com.yutou.bilibili.Tools.Log.i("[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间");
info.setVipuserindex(info.getVipuserindex() + 1); info.setVipuserindex(info.getVipuserindex() + 1);
danmu = "[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间"; danmu = "[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间";
liveData.setUid(json.getJSONObject("data").getInteger("uid")); liveData.setUid(json.getJSONObject("data").getInteger("uid"));
@ -433,6 +433,7 @@ public class Live implements ApplicationContextAware {
liveData.setRoomid(roomId); liveData.setRoomid(roomId);
liveData.setSubtime(new Date()); liveData.setSubtime(new Date());
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu);
break; break;
case "LIVE_INTERACTIVE_GAME"://彩色弹幕通过游戏弹幕 case "LIVE_INTERACTIVE_GAME"://彩色弹幕通过游戏弹幕
break; break;
@ -452,6 +453,7 @@ public class Live implements ApplicationContextAware {
liveData.setSubtime(new Date()); liveData.setSubtime(new Date());
info.setGiftuser(info.getGiftuser() + 1); info.setGiftuser(info.getGiftuser() + 1);
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,danmu);
break; break;
case "USER_TOAST_MSG": case "USER_TOAST_MSG":
break; break;
@ -469,6 +471,7 @@ public class Live implements ApplicationContextAware {
liveData.setRoomid(roomId); liveData.setRoomid(roomId);
info.setGiftuser(info.getGiftuser() + 1); info.setGiftuser(info.getGiftuser() + 1);
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,liveData.toString());
break; break;
case "LIVE"://开始直播,不过有在心跳包上做检测了所以也无所谓 case "LIVE"://开始直播,不过有在心跳包上做检测了所以也无所谓
if (upData.getLive() == 1) { if (upData.getLive() == 1) {
@ -490,6 +493,7 @@ public class Live implements ApplicationContextAware {
QQBotManager.getInstance().sendMessage(file, builder.toString()); QQBotManager.getInstance().sendMessage(file, builder.toString());
} }
}); });
Log.i(AppTools.getToDayTimeToString(startTime),roomId,upData.getName()+"开播了!");
break; break;
case "PREPARING":// case "PREPARING"://
case "SUPER_CHAT_MESSAGE_JPN": case "SUPER_CHAT_MESSAGE_JPN":
@ -519,9 +523,11 @@ public class Live implements ApplicationContextAware {
liveData.setRoomid(roomId); liveData.setRoomid(roomId);
liveData.setSubtime(new Date()); liveData.setSubtime(new Date());
service.addLiveData(liveData); service.addLiveData(liveData);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,liveData.toString());
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(e); Log.e(e);
Log.i(AppTools.getToDayTimeToString(startTime),roomId,e.getLocalizedMessage());
try { try {
JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8)); JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8));
processData(new String(bytes, StandardCharsets.UTF_8), null); processData(new String(bytes, StandardCharsets.UTF_8), null);

View File

@ -157,7 +157,8 @@ public class SaveLive {
} catch (Exception e) { } catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e); com.yutou.bilibili.Tools.Log.e(e);
Log.i("录制发生意外:" + e.getMessage()); Log.i("录制发生意外:" + e.getMessage());
QQBotManager.getInstance().sendMessage("录制发生意外:" + e.getMessage()); QQBotManager.getInstance().sendMessage("录制发生意外:" + e.getLocalizedMessage());
LiveUtils.LiveInfoManager.getInstance().check(roomId);
} }
SaveLive.this.stop(roomId); SaveLive.this.stop(roomId);

View File

@ -24,7 +24,6 @@ import org.springframework.context.ApplicationContextAware;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -49,6 +48,8 @@ public class QQBotManager implements ApplicationContextAware {
private static class QQCommands { private static class QQCommands {
private final static String QQ_HELP = "!help"; 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_IP = "!ip";
private final static String QQ_GET_VERSION = "!version"; private final static String QQ_GET_VERSION = "!version";
private final static String QQ_LIVE_LIST = "!列表"; private final static String QQ_LIVE_LIST = "!列表";
@ -60,7 +61,7 @@ public class QQBotManager implements ApplicationContextAware {
private static QQBotManager botManager = null; private static QQBotManager botManager = null;
private Bot bot; private Bot bot;
private static long qqGroup ; private static long qqGroup;
private boolean isLogin = false; private boolean isLogin = false;
private static boolean isInit = false; private static boolean isInit = false;
@ -73,7 +74,7 @@ public class QQBotManager implements ApplicationContextAware {
} }
public void init() { public void init() {
if(!((boolean) ConfigTools.load(ConfigTools.CONFIG,"qq_bot"))){ if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "qq_bot"))) {
return; return;
} }
new Thread(new Runnable() { new Thread(new Runnable() {
@ -230,6 +231,7 @@ public class QQBotManager implements ApplicationContextAware {
private void myGroup(String msg) { private void myGroup(String msg) {
msg = msg.replace("", "!").toLowerCase(); msg = msg.replace("", "!").toLowerCase();
msg=msg.trim();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
JSONObject json; JSONObject json;
String[] cmd = new String[0]; String[] cmd = new String[0];
@ -243,12 +245,17 @@ public class QQBotManager implements ApplicationContextAware {
case QQCommands.QQ_GET_VERSION: case QQCommands.QQ_GET_VERSION:
sendVersion(); sendVersion();
break; break;
case QQCommands.QQ_SYSTEM_STOP:
getInstance().sendMessage("正在停止服务");
System.out.println("结束进程");
System.exit(0);
break;
case QQCommands.QQ_LIVE_LIST: case QQCommands.QQ_LIVE_LIST:
builder.append("当前正在记录数据的直播间:"); builder.append("当前正在记录数据的直播间:");
builder.append("\n"); builder.append("\n");
for (Live live : Live.lives) { for (Live live : Live.lives) {
JSONObject liveJson = LiveUtils.LiveInfoManager.getInstance().getInfo(live.getInfo().getRoomid()); JSONObject liveJson = LiveUtils.LiveInfoManager.getInstance().getInfo(live.getInfo().getRoomid());
if(LiveUtils.isLivePlayer(live.getInfo().getRoomid())){ if (LiveUtils.isLivePlayer(live.getInfo().getRoomid())) {
builder.append("【直播中】"); builder.append("【直播中】");
} }
builder builder
@ -327,6 +334,26 @@ public class QQBotManager implements ApplicationContextAware {
} catch (Exception e) { } catch (Exception e) {
getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_USE_SAVE + "+空格+roomId"); 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);
} }
} }
} }

View File

@ -55,6 +55,8 @@ public class AppTools {
} }
public static String getToDayTime() { public static String getToDayTime() {
return new SimpleDateFormat("yyyy-MM-dd").format(new Date()); 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(){ public static Date getToDayStartTime(){
return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(AppTools.getToDayTime() + " " + "00:00",new ParsePosition(0)); return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(AppTools.getToDayTime() + " " + "00:00",new ParsePosition(0));

View File

@ -1,6 +1,14 @@
package com.yutou.bilibili.Tools; 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 { public class Log {
private static Logger logger;
public static void i(Object log) { public static void i(Object log) {
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout")))
return; return;
@ -17,4 +25,26 @@ public class Log {
i(e.getMessage()); i(e.getMessage());
e.printStackTrace(); 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;
}
} }

View File

@ -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<String> 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");
}
}

View File

@ -47,7 +47,6 @@ public class BiliBiliLiveDatabasesManager extends SQLiteManager {
,data.getUid() ,data.getUid()
,data.getUname() ,data.getUname()
); );
Log.i(sql);
statement.execute(sql); statement.execute(sql);
statement.closeOnCompletion(); statement.closeOnCompletion();
}catch (Exception e){ }catch (Exception e){