Breaking changes:

'Gift': changed from class to enum, so now you can handle
incoming gifts in switch

`Events`
- new:
     onGiftComboFinished
- Removed:
      onGiftBrodcast
- Rename:
     onGiftMessage -> onGift
     onRoomPinMessage -> onRoomPin
     onRoomMessage -> onRoom
     onLinkMessage -> onLink
     onBarrageMessage -> onBarrage
     onPollMessage -> onPoll
     onShopMessage -> onShop
     onDetectMessage -> onDetect

`GiftManager`
   added:
      registerGift
      findById
      findByName
      getGifts
   removed:
      getActiveGifts
This commit is contained in:
JW
2023-10-06 02:31:40 +02:00
parent 6cc74413ec
commit 65a2d5cfff
132 changed files with 1196 additions and 589 deletions

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>0.0.25-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Tools-EventsWebViewer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>Tools-EventsCollector</artifactId>
<version>0.0.25-Release</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,28 @@
package io.github.jwdeveloper.tiktok.webviewer;
import io.github.jwdeveloper.tiktok.webviewer.handlers.TikTokHandler;
import io.javalin.Javalin;
public class Main {
public static void main(String[] args) {
var manager = new TikTokManager();
var app = Javalin.create(config ->
{
config.plugins.enableCors(corsContainer ->
{
corsContainer.add(corsPluginConfig ->
{
corsPluginConfig.allowHost("http://localhost:5500");
});
});
config.staticFiles.add("/public");
}).start(8001);
var handler = new TikTokHandler(manager);
app.get("/tiktok/connect", handler::connect);
app.get("/tiktok/disconnect", handler::disconnect);
app.get("/tiktok/events", handler::events);
app.get("/tiktok/events/message", handler::eventMessage);
}
}

View File

@@ -0,0 +1,66 @@
package io.github.jwdeveloper.tiktok.webviewer;
import com.google.protobuf.InvalidProtocolBufferException;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.tools.collector.client.MessageCollector;
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient;
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessagessCollectorBuilder;
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
import lombok.Value;
import java.sql.SQLException;
import java.util.Base64;
import java.util.List;
import java.util.Random;
public class TikTokManager {
TikTokMessagessCollectorBuilder client;
MessageCollector msgCollector;
public TikTokManager() {
msgCollector = new MessageCollector("web");
}
public void connect(String name) throws SQLException {
disconnect();
client = TikTokMessageCollectorClient.create(msgCollector, "web").addUser(name);
client.buildAndRun();
}
public List<String> getEventsNames() {
return msgCollector.getMessages().keySet().stream().toList();
}
public List<String> getEventMessages(String eventName) {
return msgCollector.getMessages().get(eventName).stream().map(MessageCollector.MessageData::getEventData).toList();
}
public MessageDto getMessage(String event) throws InvalidProtocolBufferException {
var eventData = msgCollector.getMessages().get(event);
var messages = eventData.stream().toList();
var random = new Random();
var index = random.nextInt(messages.size()-1);
var msg = messages.get(index);
var bytes = Base64.getDecoder().decode(msg.getEventData());
var content = MessageUtil.getContent(event,bytes);
return new MessageDto(content, msg.getEventData(), event);
}
@Value
public class MessageDto {
String content;
String base64;
String eventName;
}
public void disconnect() {
if (client == null) {
return;
}
client.stop();
}
}

View File

@@ -0,0 +1,48 @@
package io.github.jwdeveloper.tiktok.webviewer.handlers;
import com.google.gson.Gson;
import com.google.protobuf.InvalidProtocolBufferException;
import io.github.jwdeveloper.tiktok.webviewer.TikTokManager;
import io.javalin.http.Context;
import java.sql.SQLException;
public class TikTokHandler {
private final TikTokManager tikTokManager;
public TikTokHandler(TikTokManager tikTokManager) {
this.tikTokManager = tikTokManager;
}
public void connect(Context context) throws SQLException {
String name = context.queryParam("name");
if (name.equals(" ")) {
context.result("Name can not be empty");
context.status(400);
return;
}
tikTokManager.connect(name);
context.status(200);
}
public void disconnect(Context context) throws SQLException {
tikTokManager.disconnect();
context.status(200);
}
public void events(Context context) throws SQLException {
var events = tikTokManager.getEventsNames();
var gson = new Gson();
var result = gson.toJson(events);
context.result(result);
context.status(200);
}
public void eventMessage(Context context) throws InvalidProtocolBufferException {
String name = context.queryParam("eventName");
var result = tikTokManager.getMessage(name);
var gson = new Gson();
context.result(gson.toJson(result));
}
}

View File

@@ -0,0 +1,226 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Bootstrap Styled Javalin App</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
<style>
body, html {
height: 100%;
margin: 0;
display: flex;
flex-direction: column;
background-color: #121212; /* Dark background */
}
#app {
height: 100vh; /* 100% of the viewport height */
display: flex;
flex-direction: column;
}
.header {
margin-bottom: 20px;
}
.btn-primary
{
background-color: #2c2c2c;
border-color: #2c2c2c;
}
.btn-primary:hover
{
background-color: #474747;
border-color: #474747;
}
#editor {
overflow-y: auto;
white-space: pre-wrap;
height: 100%;
overflow-y: auto;
}
.editor-container
{
padding: 10em;
}
.list-group-item:hover
{
background-color: #474747;
color: azure;
cursor: pointer;
}
.list-group-item
{
background-color: #2c2c2c;
color: azure;
border-color: #252424;
}
.content {
flex-grow: 1; /* Takes up the remaining space */
display: flex;
}
.col-md-10, .col-md-2 {
padding: 0; /* Remove default padding */
height: 100%;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/editor/editor.main.css">
<!-- Load Monaco Editor's main loader script -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.min.js"></script>
<!-- Configure the loader -->
<script>
require.config({
paths: {'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs'}
});
</script>
<!-- Load the editor -->
<script>
var editor;
require(['vs/editor/editor.main'], function() {
editor = monaco.editor.create(document.getElementById('editor'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'json',
theme: 'vs-dark'
});
});
</script>
</head>
<body class="bg-dark">
<div id="app" class="container-fluid mt-5">
<div >
<div class="mb-3">
<label for="name" class="form-label">Name:</label>
<input type="text" id="name" name="name" class="form-control">
</div>
<button type="button" onclick="connect()" class="btn btn-primary">Connect</button>
<button type="button" onclick="disconnect()" class="btn btn-primary">Disconnect</button>
<button onclick="showEvents()" class="btn btn-primary">Show Events</button>
</div>
<div class="content row mt-5">
<div class="col-md-2 ">
<ul id="eventList" class="list-group" style="max-height: 100%; overflow-y: auto;">
<!-- List items will be added dynamically -->
</ul>
</div>
<div class="col-md-10 editor-container ">
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item btn-primary"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</nav>
<div id="editor"></div>
</div>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
</div>
</div>
</div>
<script>
async function connect() {
let name = document.getElementById('name').value;
name = "bangbetmenygy"
let response = await fetch(`http://localhost:8001/tiktok/connect?name=${name}`);
let greeting = await response.text();
console.log("connect",greeting);
connected = true;
}
async function disconnect() {
let response = await fetch(`http://localhost:8001/tiktok/disconnect`);
let greeting = await response.text();
console.log("disconnect",greeting);
connected = false;
}
async function loadMessage(event)
{
let response = await fetch(`http://localhost:8001/tiktok/events/message?eventName=${event}`);
let json = await response.text();
// json = json.replace(/\/n/g, "\n");
let root= JSON.parse(json);
console.log(root)
editor.setValue(root.content);
}
async function showEvents() {
let response = await fetch(`http://localhost:8001/tiktok/events`);
let json = await response.text();
console.log("events:",json);
let events= JSON.parse(json);
$("#eventList").empty();
$.each(events, function(index, event) {
let listItem = $('<li>', {
class: 'list-group-item',
text: event
}).click(async function()
{
await loadMessage(event);
});
$("#eventList").append(listItem);
});
}
async function loop()
{
if(!connected)
{
return;
}
console.log("updating");
await showEvents();
}
var connected = false;
setInterval(loop, 1000)
showEvents()
</script>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>