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-05 09:04:39 +02:00
parent f55cbcae7e
commit f0d7cb0cbc
93 changed files with 5492 additions and 771 deletions

View File

@@ -45,6 +45,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>Tools</artifactId>
<version>0.0.25-Release</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -23,14 +23,12 @@
package io.github.jwdeveloper.tiktok.tools.collector;
import io.github.jwdeveloper.tiktok.TikTokLive;
import io.github.jwdeveloper.tiktok.events.messages.*;
import io.github.jwdeveloper.tiktok.events.messages.TikTokJoinEvent;
import io.github.jwdeveloper.tiktok.events.messages.TikTokLikeEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
import io.github.jwdeveloper.tiktok.tools.collector.tables.ExceptionInfoModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -52,33 +50,26 @@ public class RunCollector {
//ignoredEvents = List.of("TikTokJoinEvent","TikTokLikeEvent");
filter = new ArrayList<>();
filter.add(TikTokUnhandledSocialEvent.class);
filter.add(TikTokFollowEvent.class);
filter.add(TikTokLikeEvent.class);
filter.add(TikTokShareEvent.class);
filter.add(TikTokJoinEvent.class);
// filter.add(TikTokUnhandledSocialEvent.class);
// filter.add(TikTokFollowEvent.class);
// filter.add(TikTokLikeEvent.class);
// filter.add(TikTokShareEvent.class);
// filter.add(TikTokJoinEvent.class);
var db = new TikTokDatabase("social_db");
var db = new TikTokDatabase("test");
db.init();
var errors = db.selectErrors();
var users = new ArrayList<String>();
users.add("mia_tattoo");
users.add("mr_wavecheck");
// users.add("mia_tattoo");
// users.add("mr_wavecheck");
users.add("bangbetmenygy");
users.add("larasworld0202");
for (var user : users)
{
users.add("szwagierkaqueen");
for (var user : users) {
try {
runTikTokLiveInstance(user, db);
}
catch (Exception e)
{
} catch (Exception e) {
}
}
}
@@ -87,29 +78,40 @@ public class RunCollector {
TikTokLive.newClient(tiktokUser)
.onConnected((liveClient, event) ->
{
System.out.println("CONNECTED TO "+liveClient.getRoomInfo().getUserName());
System.out.println("CONNECTED TO " + liveClient.getRoomInfo().getHostName());
})
.onWebsocketResponse((liveClient, event) ->
{
var response = Base64.getEncoder().encodeToString(event.getResponse().toByteArray());
var responseModel = new TikTokResponseModel();
responseModel.setResponse(response);
responseModel.setHostName(liveClient.getRoomInfo().getHostName());
tikTokDatabase.insertResponse(responseModel);
System.out.println("Included response");
})
.onWebsocketMessage((liveClient, event) ->
{
var eventName = event.getEvent().getClass().getSimpleName();
if(filter.size() != 0 && !filter.contains(event.getEvent().getClass()))
{
if (filter.size() != 0 && !filter.contains(event.getEvent().getClass())) {
return;
}
var binary = Base64.getEncoder().encodeToString(event.getMessage().toByteArray());
var messageBinary = Base64.getEncoder().encodeToString(event.getMessage().toByteArray());
var model = new TikTokMessageModel();
model.setType("messsage");
model.setHostName(tiktokUser);
model.setEventName(eventName);
model.setEventContent(binary);
model.setMessage(messageBinary);
tikTokDatabase.insertMessage(model);
// tikTokDatabase.insertMessage(model);
System.out.println("EVENT: [" + tiktokUser + "] " + eventName);
})
.onError((liveClient, event) ->
{
event.getException().printStackTrace();
var exception = event.getException();
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
var errorModel = new TikTokErrorModel();

View File

@@ -48,4 +48,13 @@ public class SqlConsts
);
""";
public static String CREATE_RESPONSE_MODEL = """
CREATE TABLE IF NOT EXISTS TikTokResponseModel (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostName TEXT,
response TEXT,
createdAt TEXT
);
""";
}

View File

@@ -24,6 +24,7 @@ package io.github.jwdeveloper.tiktok.tools.collector.db;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
@@ -37,6 +38,7 @@ public class TikTokDatabase {
private final String database;
private TikTokMessageModelDAO messagesTable;
private TikTokErrorModelDAO errorTable;
private TikTokResponseModelDAO responseTable;
public TikTokDatabase(String database) {
this.database = database;
@@ -44,29 +46,34 @@ public class TikTokDatabase {
public void init() throws SQLException {
var jdbcUrl = "jdbc:sqlite:" + database + ".db";
var connection = DriverManager.getConnection(jdbcUrl);
DriverManager.getConnection(jdbcUrl);
var jdbi = Jdbi.create(jdbcUrl)
.installPlugin(new SqlObjectPlugin());
jdbi.useHandle(handle -> {
handle.execute(SqlConsts.CREATE_MESSAGES_TABLE);
handle.execute(SqlConsts.CREATE_ERROR_TABLE);
handle.execute(SqlConsts.CREATE_RESPONSE_MODEL);
});
messagesTable = jdbi.onDemand(TikTokMessageModelDAO.class);
errorTable = jdbi.onDemand(TikTokErrorModelDAO.class);
responseTable = jdbi.onDemand(TikTokResponseModelDAO.class);
}
public void insertMessage(TikTokMessageModel message) {
var dateFormat = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS");
message.setCreatedAt(dateFormat.format(new Date()));
message.setCreatedAt(getTime());
messagesTable.insertTikTokMessage(message);
}
public void insertError(TikTokErrorModel message) {
var dateFormat = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS");
message.setCreatedAt(dateFormat.format(new Date()));
message.setCreatedAt(getTime());
errorTable.insertTikTokMessage(message);
}
public void insertResponse(TikTokResponseModel message) {
message.setCreatedAt(getTime());
responseTable.insert(message);
}
public List<TikTokErrorModel> selectErrors() {
return errorTable.selectErrors();
}
@@ -74,4 +81,12 @@ public class TikTokDatabase {
public List<TikTokMessageModel> selectMessages() {
return messagesTable.select();
}
public List<TikTokResponseModel> selectResponces() {
return responseTable.select();
}
private String getTime() {
return new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS").format(new Date());
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.tools.collector.db;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.customizer.BindBean;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import java.util.List;
@RegisterBeanMapper(TikTokResponseModel.class)
public interface TikTokResponseModelDAO
{
@SqlUpdate("INSERT INTO TikTokResponseModel (hostName, response, createdAt) " +
"VALUES (:hostName, :response, :createdAt)")
void insert(@BindBean TikTokResponseModel message);
@SqlQuery("SELECT * FROM TikTokResponseModel")
List<TikTokResponseModel> select();
}

View File

@@ -22,8 +22,6 @@
*/
package io.github.jwdeveloper.tiktok.tools.collector.tables;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -38,7 +36,7 @@ public class TikTokMessageModel
private String type;
private String eventContent;
private String message;
private String createdAt;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.tools.collector.tables;
import lombok.Data;
@Data
public class TikTokResponseModel
{
private Integer id;
private String hostName;
private String response;
private String createdAt;
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.tools.tester;
import com.google.protobuf.ByteString;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.mockClient.TikTokClientMock;
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class RunDbTester {
public static void main(String[] args) throws Exception {
var db = new TikTokDatabase("test");
db.init();
var responses = db.selectResponces().stream().map(TikTokResponseModel::getResponse).toList();
var client = TikTokClientMock
.create()
.addResponses(responses)
.onWebsocketUnhandledMessage((liveClient, event) ->
{
liveClient.getLogger().info("Unhandled Message! " + event.getData().getMethod());
})
.onWebsocketMessage((liveClient, event) ->
{
var sb = new StringBuilder();
sb.append(event.getEvent().getClass().getSimpleName());
sb.append(event.getEvent().toJson());
// sb.append(ConsoleColors.YELLOW + messageContent(event.getMessage()));
liveClient.getLogger().info(sb.toString());
})
.build();
updateLogger(client.getLogger());
client.connect();
}
protected static String messageContent(WebcastResponse.Message message) {
try {
var methodName = message.getMethod();
if (!methodName.contains("Webcast")) {
methodName = "Webcast" + methodName;
}
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + methodName);
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", ByteString.class);
var deserialized = parseMethod.invoke(null, message.getPayload());
return JsonUtil.messageToJson(deserialized);
} catch (Exception ex) {
return "";
}
}
public static void updateLogger(Logger logger) {
for (var handler : logger.getHandlers()) {
logger.removeHandler(handler);
}
var handler = new ConsoleHandler();
handler.setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
return ConsoleColors.WHITE_BRIGHT + record.getLevel() + ": " + ConsoleColors.GREEN + record.getMessage() + "\n" + ConsoleColors.RESET;
}
});
logger.setUseParentHandlers(false);
logger.addHandler(handler);
}
}

View File

@@ -22,17 +22,16 @@
*/
package io.github.jwdeveloper.tiktok.tools.tester;
import io.github.jwdeveloper.tiktok.events.objects.Gift;
import io.github.jwdeveloper.tiktok.mockClient.TikTokClientMock;
public class RunLogTester
{
public static void main(String[] args)
{
var mockClient = TikTokClientMock.create("123").buildAndRun();
public class RefelcionTest {
public static void main(String[] run) throws NoSuchFieldException, IllegalAccessException {
var gift = Gift.PANDA;
var url = gift.getPicture();
var field = gift.getClass().getDeclaredField("picture");
field.setAccessible(true);
field.set(gift, null);
var url2 = gift.getPicture();
}
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.jwdeveloper.tiktok.tools.tester;
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.events.messages.TikTokGiftComboFinishedEvent;
import io.github.jwdeveloper.tiktok.events.messages.TikTokGiftEvent;
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
import java.util.Base64;
public class RunTester {
public static void main(String[] args) throws Exception {
var db = new TikTokDatabase("test");
db.init();
var errors = db.selectErrors();
var handler = getMessageHandler();
for (var error : errors) {
var bytes = Base64.getDecoder().decode(error.getResponse());
var response = WebcastResponse.parseFrom(bytes);
handler.handle(null, response);
}
var messags = db.selectMessages();
for (var msg : messags) {
if (!msg.getEventName().contains("Gift")) {
continue;
}
var bytes = Base64.getDecoder().decode(msg.getEventContent());
var response = WebcastResponse.Message.parseFrom(bytes);
handler.handleSingleMessage(null, response);
}
}
public static TikTokMessageHandlerRegistration getMessageHandler() {
var observer = new TikTokEventObserver();
observer.<TikTokGiftEvent>subscribe(TikTokGiftEvent.class, (liveClient, event) ->
{
var sb = new StringBuilder();
sb.append("Event: " + event.getGift());
sb.append(" combo: " + event.getComboCount());
sb.append(" index " + event.getComboIndex());
sb.append(" sender " + event.getSender().getNickName());
System.out.println(sb.toString());
});
observer.<TikTokGiftComboFinishedEvent>subscribe(TikTokGiftComboFinishedEvent.class, (liveClient, event) ->
{
System.out.println("Combo finished event! " + event.getComboCount() + " " + event.getGift());
});
observer.<TikTokErrorEvent>subscribe(TikTokErrorEvent.class, (liveClient, event) ->
{
event.getException().printStackTrace();
});
var roomInfo = new TikTokRoomInfo();
var manager = new TikTokGiftManager();
return new TikTokMessageHandlerRegistration(observer, manager, roomInfo);
}
}

File diff suppressed because one or more lines are too long