新增机器人指令控制

This commit is contained in:
yutou 2021-04-08 18:33:34 +08:00
parent ef0d7e5850
commit ab6bfbfd42
11 changed files with 746 additions and 49 deletions

33
pom.xml
View File

@ -15,6 +15,7 @@
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<kotlin.version>1.4.10</kotlin.version>
</properties>
<dependencies>
<dependency>
@ -102,10 +103,42 @@
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>net.mamoe</groupId>
<artifactId>mirai-core-jvm</artifactId>
<version>2.5.0</version> <!-- 替换版本为你需要的版本 -->
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>

View File

@ -30,7 +30,8 @@ public class RealTimeDataController {
@RequestMapping("get/query.do")
public JSONObject queryToDayLiveData(int roomid,Date startTime,Date endTime) throws ParseException {
JSONObject json = new JSONObject();
BilibiliUpInfo info = service.queryUpToRoomId(roomid);
BilibiliUpInfo info = new BilibiliUpInfo();
info.setRoomid(roomid);
Live live = LiveUtils.liveContains(info);
if(startTime==null){
startTime=AppTools.getToDayStartTime();

View File

@ -10,7 +10,6 @@ import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
import com.yutou.bilibili.BiliBili.Tools.BiliTools;
import com.yutou.bilibili.Services.IUserService;
import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.Log;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
import com.yutou.bilibili.mybatis.model.UUser;
import org.springframework.stereotype.Controller;
@ -19,7 +18,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Controller

View File

@ -7,8 +7,11 @@ import com.yutou.bilibili.BiliBili.Datas.LiveData;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
import com.yutou.bilibili.QQBot.QQBotManager;
import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.Log;
import com.yutou.bilibili.Tools.Tools;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
@ -81,13 +84,13 @@ public class Live implements ApplicationContextAware {
Live.lives.add(this);
updateUpInfo();
com.yutou.bilibili.Tools.Log.i("roomId = " + roomId + ", isLogin = " + isLogin);
checkLiveTimer=new Timer();
checkLiveTimer = new Timer();
checkLiveTimer.schedule(new TimerTask() {
@Override
public void run() {
checkLive();
}
},0,1000);
}, 0, 1000);
}
private void updateUpInfo() {
@ -104,7 +107,7 @@ public class Live implements ApplicationContextAware {
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
}
}
@ -147,7 +150,7 @@ public class Live implements ApplicationContextAware {
try {
likeLive();
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
}
}
@ -179,7 +182,7 @@ public class Live implements ApplicationContextAware {
client.close();
start();
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
}
return;
}
@ -197,7 +200,7 @@ public class Live implements ApplicationContextAware {
@Override
public void onError(Exception e) {
e.printStackTrace();
Log.e(e);
run = false;
client.close();
}
@ -216,7 +219,7 @@ public class Live implements ApplicationContextAware {
}
Live.lives.remove(this);
com.yutou.bilibili.Tools.Log.i("退出" + roomId + "直播间");
if(checkLiveTimer!=null){
if (checkLiveTimer != null) {
checkLiveTimer.cancel();
}
}
@ -281,13 +284,13 @@ public class Live implements ApplicationContextAware {
JSONObject json = JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8));
com.yutou.bilibili.Tools.Log.i(json.toJSONString());
} catch (Exception e) {
checkLive();
int popular = LiveUtils.bytesToInt2(bytes, 0);
info.setPopular(popular);
checkLive();
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
com.yutou.bilibili.Tools.Log.i("----------ERROR----------");
com.yutou.bilibili.Tools.Log.i(new String(data, StandardCharsets.UTF_8));
LiveUtils.printHex(LiveUtils.dec(data));
@ -467,6 +470,18 @@ public class Live implements ApplicationContextAware {
case "WIDGET_BANNER"://鬼知道是啥
case "HOT_RANK_SETTLEMENT":
case "LIVE"://开始直播,不过有在心跳包上做检测了所以也无所谓
JSONObject liveInfo = LiveUtils.getLiveInfo(roomId);
StringBuilder builder = new StringBuilder();
builder.append(upData.getName()).append("开播了!").append("\n");
builder.append(liveInfo.getJSONObject("data").getJSONObject("room_info").getString("title"));
Tools.download(liveInfo.getJSONObject("data").getJSONObject("room_info").getString("keyframe"), new DownloadInterface() {
@Override
public void onDownload(File file) {
super.onDownload(file);
QQBotManager.getInstance().sendMessage(file, builder.toString());
}
});
break;
case "PK_BATTLE_SETTLE_V2":
case "PK_BATTLE_END":
case "PK_BATTLE_SETTLE":
@ -487,12 +502,12 @@ public class Live implements ApplicationContextAware {
service.addLiveData(liveData);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
try {
JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8));
processData(new String(bytes, StandardCharsets.UTF_8), null);
} catch (Exception e2) {
e2.printStackTrace();
Log.e(e2);
com.yutou.bilibili.Tools.Log.i(msg);
com.yutou.bilibili.Tools.Log.i("---------ERROR -----");
LiveUtils.printHex(bytes);
@ -558,7 +573,7 @@ public class Live implements ApplicationContextAware {
outputStream.flush();
client.send(outputStream.toByteArray());
} catch (Exception e) {
e.printStackTrace();
Log.e(e);
com.yutou.bilibili.Tools.Log.i(client.isClosed());
com.yutou.bilibili.Tools.Log.i(client.isOpen());

View File

@ -43,11 +43,10 @@ public class LiveUtils {
com.yutou.bilibili.Tools.Log.i("\n");
}
if (str.length() - i > 4) {
System.out.print(str.substring(i, i + 4));
com.yutou.bilibili.Tools.Log.i(str.substring(i, i + 4));
} else {
com.yutou.bilibili.Tools.Log.i(str.substring(i));
}
System.out.print(" ");
}
}
@ -211,7 +210,8 @@ public class LiveUtils {
}
} catch (IOException e) {
e.printStackTrace();
//e.printStackTrace();
Log.i("412 in "+url);
}
return null;
}
@ -340,9 +340,19 @@ public class LiveUtils {
}
return null;
}
public static JSONObject getLiveInfo(int roomId){
return http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=" + roomId);
}
public static String getLiveTitle(int roomId){
JSONObject json=getLiveInfo(roomId);
if(json!=null){
return json.getJSONObject("data").getJSONObject("room_info").getString("title");
}
return null;
}
public static boolean isLivePlayer(int roomId) {
JSONObject json = http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=" + roomId);
JSONObject json =getLiveInfo(roomId);
if (json == null)
return false;
BilibiliUpInfo upData = new BilibiliUpInfo();

View File

@ -3,6 +3,7 @@ package com.yutou.bilibili.BiliBili.Tools;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.Live;
import com.yutou.bilibili.BiliBili.LiveUtils;
import com.yutou.bilibili.QQBot.QQBotManager;
import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.HttpTools;
@ -14,9 +15,9 @@ import java.util.*;
public class SaveLive {
private static SaveLive live;
private List<String> saveList = new ArrayList<>();
private Map<Integer,DownloadThread> downloads = new HashMap<>();
private Map<Integer,Timer> heartbeats=new HashMap<>();
private final List<String> saveList = new ArrayList<>();
private final Map<Integer, DownloadThread> downloads = new HashMap<>();
private final Map<Integer, Timer> heartbeats = new HashMap<>();
public static void main(String[] args) {
SaveLive.getInstance().addLive(3715397);
@ -35,7 +36,11 @@ public class SaveLive {
public void addLive(Live live) {
addLive(live.geData().getRoomid());
}
public void startLive(int roomId){
saveList.add(roomId + "");
start(roomId);
QQBotManager.getInstance().sendMessage(roomId+" 已启动录制");
}
public void addLive(int roomId) {
if (saveList.contains(roomId + "")) {
return;
@ -45,11 +50,15 @@ public class SaveLive {
}
saveList.add(roomId + "");
start(roomId);
QQBotManager.getInstance().sendMessage(roomId+" 已启动录制");
}
public boolean checkLive(int roomId) {
return saveList.contains(roomId + "");
}
public File getLiveFile(int roomId){
return downloads.get(roomId).liveFile;
}
private long timer = 0;
@ -57,12 +66,12 @@ public class SaveLive {
com.yutou.bilibili.Tools.Log.i("t停止录播:" + roomId + " time=" + (System.currentTimeMillis() - timer));
saveList.remove(roomId + "");
if(downloads.containsKey(roomId)){
downloads.get(roomId).isSave=false;
if (downloads.containsKey(roomId)) {
downloads.get(roomId).isSave = false;
downloads.remove(roomId);
}
if(heartbeats.containsKey(roomId)){
if (heartbeats.containsKey(roomId)) {
heartbeats.get(roomId).cancel();
heartbeats.remove(roomId);
}
@ -72,7 +81,7 @@ public class SaveLive {
private void start(int roomId) {
timer = System.currentTimeMillis();
DownloadThread thread = new DownloadThread(roomId);
downloads.put(roomId,thread);
downloads.put(roomId, thread);
}
@ -84,6 +93,7 @@ public class SaveLive {
int roomId = 0;
boolean isSave = true;
Timer heartbeat;
File liveFile;
public DownloadThread(int roomId) {
this.roomId = roomId;
@ -112,20 +122,20 @@ public class SaveLive {
heartbeat = new Timer();
//Heartbeat beat = new Heartbeat();
heartbeat.schedule(new Heartbeat(), 0, 30000);
heartbeats.put(roomId,heartbeat);
heartbeats.put(roomId, heartbeat);
//heartbeats.add(beat);
InputStream inputStream = connection.getInputStream();
File file = new File(String.format("live%s%s%s[%s]%d.mp4",
liveFile = new File(String.format("live%s%s%s[%s]%d.mp4",
File.separator,
AppTools.getToDayTime(),
File.separator,
AppTools.getToDayNowTimeToString().replace(":", ""),
roomId));
if (!file.exists()) {
file.mkdirs();
file.delete();
if (!liveFile.exists()) {
liveFile.mkdirs();
liveFile.delete();
}
FileOutputStream outputStream = new FileOutputStream(file);
FileOutputStream outputStream = new FileOutputStream(liveFile);
int len;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) != -1 && isSave) {
@ -134,16 +144,17 @@ public class SaveLive {
}
outputStream.close();
inputStream.close();
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId + " save = " + isSave + " len = " + len);
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId + " save = " + isSave + " len = " + len);
} catch (Exception e) {
e.printStackTrace();
} finally {
SaveLive.this.stop(roomId);
}
SaveLive.this.stop(roomId);
}
private class Heartbeat extends TimerTask {
int nextInterval=1;
int nextInterval = 1;
@Override
public void run() {
try {
@ -151,16 +162,16 @@ public class SaveLive {
JSONObject userHear = new JSONObject();
JSONObject cookie = JSONObject.parseObject(LiveUtils.getFile("cookies.json"));
hearBeat = LiveUtils.http_get("https://api.live.bilibili.com/relation/v1/Feed/heartBeat");
com.yutou.bilibili.Tools.Log.i(hearBeat+" \t");
hearBeat = LiveUtils.http_get(String.format("https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat?hb=%s&pf=web", URLEncoder.encode(new String(Base64.getEncoder().encode(String.format("%d|%d|1|0",nextInterval, roomId).getBytes(StandardCharsets.UTF_8))), "UTF-8")));
com.yutou.bilibili.Tools.Log.i(hearBeat+"\t");
nextInterval=hearBeat.getJSONObject("data").getInteger("next_interval");
com.yutou.bilibili.Tools.Log.i("next = "+nextInterval);
userHear.put("csrf_token",cookie.getString("bili_jct"));
userHear.put("csrf",cookie.getString("bili_jct"));
userHear.put("visit_id","");
hearBeat=LiveUtils.http_post("https://api.live.bilibili.com/User/userOnlineHeart", HttpTools.toUrlParams(userHear));
com.yutou.bilibili.Tools.Log.i("["+AppTools.getToDayNowTimeToString()+"]"+hearBeat);
com.yutou.bilibili.Tools.Log.i(hearBeat + " \t");
hearBeat = LiveUtils.http_get(String.format("https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat?hb=%s&pf=web", URLEncoder.encode(new String(Base64.getEncoder().encode(String.format("%d|%d|1|0", nextInterval, roomId).getBytes(StandardCharsets.UTF_8))), "UTF-8")));
com.yutou.bilibili.Tools.Log.i(hearBeat + "\t");
nextInterval = hearBeat.getJSONObject("data").getInteger("next_interval");
com.yutou.bilibili.Tools.Log.i("next = " + nextInterval);
userHear.put("csrf_token", cookie.getString("bili_jct"));
userHear.put("csrf", cookie.getString("bili_jct"));
userHear.put("visit_id", "");
hearBeat = LiveUtils.http_post("https://api.live.bilibili.com/User/userOnlineHeart", HttpTools.toUrlParams(userHear));
com.yutou.bilibili.Tools.Log.i("[" + AppTools.getToDayNowTimeToString() + "]" + hearBeat);
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -2,18 +2,22 @@ package com.yutou.bilibili;
import com.yutou.bilibili.BiliBili.Live;
import com.yutou.bilibili.BiliBili.Tools.LiveT;
import com.yutou.bilibili.QQBot.QQBotManager;
import com.yutou.bilibili.Tools.ExcelUtils;
import com.yutou.bilibili.Tools.ServiceTools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
@Import({Live.class,ServiceTools.class, ExcelUtils.class})
@Import({Live.class,ServiceTools.class, ExcelUtils.class, QQBotManager.class})
@SpringBootApplication
public class BilibiliApplication {
public static String version="0.6";
public static void main(String[] args) {
SpringApplication.run(BilibiliApplication.class, args);
QQBotManager.getInstance().init();
}
}

View File

@ -0,0 +1,404 @@
package com.yutou.bilibili.QQBot;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.Controllers.RealTimeDataController;
import com.yutou.bilibili.BiliBili.Live;
import com.yutou.bilibili.BiliBili.LiveUtils;
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
import com.yutou.bilibili.BilibiliApplication;
import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.HttpTools;
import com.yutou.bilibili.Tools.Log;
import com.yutou.bilibili.Tools.Tools;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
import net.mamoe.mirai.Bot;
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.MessageChainBuilder;
import net.mamoe.mirai.utils.BotConfiguration;
import net.mamoe.mirai.utils.ExternalResource;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
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;
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 implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (QQBotManager.applicationContext == null)
QQBotManager.applicationContext = applicationContext;
}
private <T> T getBean(Class<T> tClass) {
return applicationContext.getBean(tClass);
}
private static class QQCommands {
private final static String QQ_HELP = "!help";
private final static String QQ_GET_IP = "!ip";
private final static String QQ_GET_VERSION = "!version";
private final static String QQ_LIVE_LIST = "!直播列表";
private final static String QQ_LIVE_SAVE = "!录播列表";
private final static String QQ_LIVE_TO_DAY_DATE = "!今日数据";
private final static String QQ_LIVE_DATE = "!数据";
private final static String QQ_LIVE_USE_SAVE = "!启动录播";
}
private static QQBotManager botManager = null;
private Bot bot;
private static final long qqGroup = 891655174L;
private boolean isLogin = false;
private static boolean isInit = false;
private static final boolean debug = true;
@Resource
RealTimeDataController realTimeDataController;
private QQBotManager() {
}
public void init() {
new Thread(new Runnable() {
@Override
public void run() {
long qq = 3620756944L;
String password = "UAs6YBYMyxJU";
System.out.println("调用机器人");
bot = BotFactory.INSTANCE.newBot(qq, password, new BotConfiguration() {
{
setProtocol(MiraiProtocol.ANDROID_PAD);
fileBasedDeviceInfo("qq_bot_devices_info.json");
if (debug) {
noBotLog();
noNetworkLog();
}
}
});
//Events.registerEvents(bot, new MessageListener());
GlobalEventChannel.INSTANCE.subscribeAlways(GroupMessageEvent.class, new MessageListener());
System.out.println("准备登陆");
bot.login();
System.out.println("登陆成功");
isLogin = true;
isInit = true;
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String str = sendMessage("姬妻酱上线拉~");
Log.i(str);
}
}).start();
bot.join();
}
}).start();
}
public static QQBotManager getInstance() {
if (botManager == null && !isInit) {
botManager = new QQBotManager();
}
return botManager;
}
public boolean isLogin() {
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 String sendMessage(String text) {
if (bot != null) {
try {
return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(text).toString();
} catch (Exception e) {
e.printStackTrace();
}
}
return getNotLoginQQ();
}
public String sendMessage(Long group, String text) {
if (bot != null) {
try {
return Objects.requireNonNull(bot.getGroup(group)).sendMessage(text).toString();
} catch (Exception e) {
e.printStackTrace();
}
}
return getNotLoginQQ();
}
public void sendMessage(Long group, MessageChainBuilder builder) {
if (bot != null) {
Objects.requireNonNull(bot.getGroup(group)).sendMessage(builder.asMessageChain());
}
}
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<File> imgs, String text) {
if (bot != null) {
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();
}
private static List<String> getImages(String str) {
List<String> list = new ArrayList<>();
String regex = "<img(.*?)/img>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
list.add(matcher.group().replace("<img", "")
.replace("/img>", "")
.trim());
}
return list;
}
public static void main(String[] args) {
getInstance();
}
private static class MessageListener implements Consumer<GroupMessageEvent> {
@Override
public void accept(GroupMessageEvent event) {
String msg = event.getMessage().contentToString();
switch (event.getGroup().getId() + "") {
case qqGroup + "":
myGroup(msg);
}
}
private void myGroup(String msg) {
msg = msg.replace("", "!").toLowerCase();
StringBuilder builder = new StringBuilder();
JSONObject json;
String[] cmd = new String[0];
int _roomId = 0;
switch (msg) {
case QQCommands.QQ_GET_IP:
json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/"));
String ip = json.getString("ip");
getInstance().sendMessage("服务器IP:" + ip);
break;
case QQCommands.QQ_GET_VERSION:
sendVersion();
break;
case QQCommands.QQ_LIVE_LIST:
builder.append("当前正在记录数据的直播间:");
builder.append("\n");
for (Live live : Live.lives) {
JSONObject liveJson = LiveUtils.getLiveInfo(live.getInfo().getRoomid());
builder
.append("名字:").append(live.geData().getName()).append(" ")
.append(" roomId:").append(live.geData().getRoomid()).append(" ");
if (liveJson != null) {
builder.append("标题:").append(liveJson.getJSONObject("data").getJSONObject("room_info").getString("title")).append("\n");
} else {
builder.append("\n");
}
}
getInstance().sendMessage(builder.toString());
break;
case QQCommands.QQ_LIVE_SAVE:
builder.append("当前正在录制的直播间:");
builder.append("\n");
for (String roomId : SaveLive.getInstance().getLiveList()) {
BilibiliUpInfo data = new BilibiliUpInfo();
data.setRoomid(Integer.parseInt(roomId));
Live live = LiveUtils.liveContains(data);
if (live != null) {
File file = SaveLive.getInstance().getLiveFile(_roomId);
builder
.append("名字:").append(live.geData().getName()).append(" ")
.append("文件大小(字节):").append(file.length()).append(" ")
.append("roomId:").append(live.geData().getRoomid()).append("\n");
}
}
getInstance().sendMessage(builder.toString());
break;
case QQCommands.QQ_HELP:
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(QQCommands.QQ_LIVE_TO_DAY_DATE)){
try {
cmd = msg.split(" ");
_roomId = Integer.parseInt(cmd[1]);
QQBotManager.getInstance().sendMessage("请稍等,正在查询...");
sendGiftData(_roomId, null, null);
} catch (Exception e) {
getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_TO_DAY_DATE + "+空格+roomId");
}
}else if(msg.startsWith(QQCommands.QQ_LIVE_DATE)){
try {
cmd = msg.split(" ");
_roomId = Integer.parseInt(cmd[1]);
Date startTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[2]);
Date endTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[3]);
QQBotManager.getInstance().sendMessage("请稍等,正在查询...");
sendGiftData(_roomId, startTime, endTime);
} catch (Exception e) {
getInstance().sendMessage("参数错误。" +
"\n使用方式: " + QQCommands.QQ_LIVE_DATE + "+空格+roomId+起始时间+空格+结束时间" +
"\n时间格式年-月-日_时:分:秒 例:2021-4-1_12:00:00" +
"\n时分秒不可省略");
}
}else if(msg.startsWith(QQCommands.QQ_LIVE_USE_SAVE)){
try {
cmd = msg.split(" ");
_roomId = Integer.parseInt(cmd[1]);
if (SaveLive.getInstance().checkLive(_roomId)) {
SaveLive.getInstance().stop(_roomId);
}
SaveLive.getInstance().startLive(_roomId);
getInstance().sendMessage("已启动" + _roomId + "的录播");
} catch (Exception e) {
getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_USE_SAVE + "+空格+roomId");
}
}
}
}
public void sendGiftData(int roomId, Date startTime, Date endTime) throws ParseException {
StringBuilder builder = new StringBuilder();
if (startTime == null) {
startTime = AppTools.getToDayStartTime();
}
if (endTime == null) {
endTime = AppTools.getToDayNowTime();
}
if (getInstance().realTimeDataController == null)
getInstance().realTimeDataController = getInstance().getBean(RealTimeDataController.class);
JSONObject json = getInstance().realTimeDataController.queryToDayLiveData(roomId, startTime, endTime);
System.out.println(json);
builder.append("当前人气:").append(json.getJSONObject("data").getInteger("popular")).append("\n");
builder.append("普通观众入场:").append(json.getJSONObject("data").getInteger("userLength")).append("\n");
builder.append("舰长入场:").append(json.getJSONObject("data").getInteger("vipLength")).append("\n");
int price = 0;
for (Object o : json.getJSONObject("data").getJSONArray("price")) {
price += ((JSONObject) o).getInteger("price");
}
builder.append("金瓜子:").append(price).append(" 抽成后:").append((price / 2) / 1000).append("").append("\n");
builder.append("礼物收益情况:").append("\n");
for (Object o : json.getJSONObject("data").getJSONArray("gift")) {
builder.append(((JSONObject) o).getString("giftName")).append(":").append(((JSONObject) o).getInteger("size")).append("\n");
}
getInstance().sendMessage(builder.toString());
}
private List<File> files;
private int index = 0;
private void sendImagesMsg(List<String> 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(File file) {
super.onDownload(file);
files.add(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);
Log.i("str = " + str);
}
}
private void sendVersion() {
String msg = "软件版本:" + BilibiliApplication.version;
QQBotManager.getInstance().sendMessage(msg);
}
}
}

View File

@ -2,10 +2,17 @@ package com.yutou.bilibili.Tools;
public class Log {
public static void i(Object log){
if(true)
return;
System.out.printf("[%s]%s%n",
AppTools.getToDayNowTimeToString(),
log
);
}
public static void e(Exception e){
if(true)
return;
e.printStackTrace();
}
}

View File

@ -0,0 +1,211 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONArray;
import com.yutou.bilibili.interfaces.DownloadInterface;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Random;
public class Tools {
/**
* 获取项目路径
*
* @param request
* @return
*/
public static String getPath(HttpServletRequest request) {
return request.getServletContext().getRealPath("/") + "/";
}
/**
* 获取客户端IP
*
* @param request
* @return
*/
public static String getRemoteAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getRemoteAddr();
}
return ip;
}
/**
* N以内的不重复随机数
*
* @param min 最小值
* @param max 最大值
* @param n
* @return
*/
public static int[] randomCommon(int min, int max, int n) {
int len = max - min + 1;
if (max < min || n > len) {
return new int[0];
}
// 初始化给定范围的待选数组
int[] source = new int[len];
for (int i = min; i < min + len; i++) {
source[i - min] = i;
}
int[] result = new int[n];
Random rd = new Random();
int index = 0;
for (int i = 0; i < result.length; i++) {
// 待选数组0到(len-2)随机一个下标
index = Math.abs(rd.nextInt() % len--);
// 将随机到的数放入结果集
result[i] = source[index];
// 将待选数组中被随机到的数用待选数组(len-1)下标对应的数替换
source[index] = source[len];
}
return result;
}
public static void download(String url, DownloadInterface downloadInterface) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36");
connection.disconnect();
new File("tmp").mkdirs();
File file = new File("tmp" + File.separator + url.trim().split("/")[url.trim().split("/").length - 1]);
if (file.exists()) {
file.delete();
}
FileOutputStream outputStream = new FileOutputStream(file);
InputStream inputStream = connection.getInputStream();
byte[] bytes = new byte[4096];
int len;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
downloadInterface.onDownload(file);
} catch (IOException e) {
e.printStackTrace();
downloadInterface.onError(e);
}
}
/**
* 构造给前端的文件
*
* @param file 文件路径
* @return 前端获取的文件
*/
public static ResponseEntity<FileSystemResource> getFile(File file) {
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
try {
headers.add("Content-Disposition", "attachment; filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
headers.add("Content-Disposition", "attachment; filename=" + file.getName());
}
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.add("Last-Modified", new Date().toString());
headers.add("ETag", String.valueOf(System.currentTimeMillis()));
return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));
}
public static String getFileMD5(File file) {
if (!file.isFile()) {
return null;
}
MessageDigest digest = null;
FileInputStream in = null;
byte buffer[] = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance("MD5");
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bytesToHexString(digest.digest());
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (byte aSrc : src) {
int v = aSrc & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
public static String base64ToString(String base) {
base = base.replace(" ", "+");
try {
base = new String(Base64.getDecoder().decode(base.replace("\r\n", "").getBytes()));
} catch (Exception e) {
try {
base = URLDecoder.decode(base, "UTF-8");
base = base.replace(" ", "+");
base = new String(Base64.getDecoder().decode(base.replace("\r\n", "").getBytes()));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return base;
}
/**
* 异常输出
*
* @param e 异常
* @return
*/
public static String getExceptionString(Exception e) {
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
printWriter.close();
return writer.toString();
}
public static String getToDayTime() {
return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
}
}

View File

@ -1,6 +1,9 @@
package com.yutou.bilibili.interfaces;
import java.io.File;
public abstract class DownloadInterface {
public void onDownload(String file){};
public void onDownloading(double soFarBytes, double totalBytes){};
public void onDownload(File file){};
public void onError(Exception e){};
}