Compare commits

...

12 Commits

Author SHA1 Message Date
David Kohler
d2ea00bcae Merge pull request #72 from jwdeveloper/develop-1.6.1
Develop 1.6.1
2024-05-12 20:52:28 -04:00
kohlerpop1
4297af1349 Simplify LiveDataMapper#map 2024-05-12 20:47:13 -04:00
kohlerpop1
d09c90ef54 Added append live username option to FileStorage and now support connection to 18+ age restricted! 2024-05-10 16:44:42 -04:00
kohlerpop1
9c96c8899a Added option to use File Locking as through testing, some events occur simultaneously causing the file to become overlapped or corrupted. 2024-05-04 15:21:34 -04:00
kohlerpop1
301df6392d More updated to TikTokLinkMicBattleEvent, updated Gift since its no longer enum we do not need to use Unsafe, and added default mappings for WebcastLinkMicBattle and WebcastLinkMicArmies 2024-04-19 13:41:07 -04:00
kohlerpop1
fb9fc04ee5 Revert "More updated to TikTokLinkMicBattleEvent, updated Gift since its no longer enum we do not need to use Unsafe, and added default mappings for WebcastLinkMicBattle and WebcastLinkMicArmies"
This reverts commit 43a8ba4225.
2024-04-19 13:33:49 -04:00
kohlerpop1
43a8ba4225 More updated to TikTokLinkMicBattleEvent, updated Gift since its no longer enum we do not need to use Unsafe, and added default mappings for WebcastLinkMicBattle and WebcastLinkMicArmies 2024-04-19 13:28:10 -04:00
David Kohler
dffccf1f0b Update README.md 2024-04-10 12:08:46 -04:00
GitHub Action
6dcccccb78 Update version in pom.xml 2024-04-10 16:07:17 +00:00
David Kohler
0d467d79c3 Update TikTokGiftEventHandlerTest.java
Fixed minor issue with Client compilation
2024-04-10 12:05:20 -04:00
David Kohler
33c98508c0 MINOR
Merge pull request #70 from jwdeveloper/develop-1.6.0
2024-04-10 12:01:00 -04:00
GitHub Action
4545503441 Update version in pom.xml 2024-04-02 02:28:56 +00:00
20 changed files with 78 additions and 88 deletions

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>API</artifactId>

View File

@@ -27,7 +27,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
import io.github.jwdeveloper.tiktok.data.models.battles.*;
import io.github.jwdeveloper.tiktok.messages.enums.LinkMicBattleStatus;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLinkMicBattle;
import lombok.Getter;
import lombok.*;
import java.util.*;
@@ -43,6 +43,8 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent
true if battle is finished otherwise false
*/
private final boolean finished;
@Getter(AccessLevel.NONE)
private final boolean oneVsOne;
private final List<Team> teams;
public TikTokLinkMicBattleEvent(WebcastLinkMicBattle msg) {
@@ -53,6 +55,7 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent
if (msg.getHostTeamCount() == 2) { // 1v1 battle
teams.add(new Team1v1(msg.getHostTeam(0), msg));
teams.add(new Team1v1(msg.getHostTeam(1), msg));
oneVsOne = true;
} else { // 2v2 battle
if (isFinished()) {
teams.add(new Team2v2(msg.getHostData2V2List().stream().filter(data -> data.getTeamNumber() == 1).findFirst().orElse(null), msg));
@@ -61,6 +64,7 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent
teams.add(new Team2v2(msg.getHostTeam(0), msg.getHostTeam(1), msg));
teams.add(new Team2v2(msg.getHostTeam(2), msg.getHostTeam(3), msg));
}
oneVsOne = false;
}
// Info:
@@ -68,4 +72,12 @@ public class TikTokLinkMicBattleEvent extends TikTokHeaderEvent
// - msg.getDetailsCount() & msg.getViewerTeamCount() always is 2 only when battle is finished
// - msg.getHostTeamCount() always is 2 for 1v1 or 4 for 2v2
}
public boolean is1v1() {
return oneVsOne;
}
public boolean is2v2() {
return !oneVsOne;
}
}

View File

@@ -2,9 +2,7 @@ package io.github.jwdeveloper.tiktok.data.models.gifts;
import com.google.gson.JsonObject;
import io.github.jwdeveloper.tiktok.data.models.Picture;
import lombok.*;
import java.util.*;
import lombok.Data;
@Data
public class Gift {
@@ -16,7 +14,7 @@ public class Gift {
private final int diamondCost;
private final Picture picture;
private Picture picture;
private final JsonObject properties;

View File

@@ -91,6 +91,9 @@ public class LiveClientSettings {
*/
private long pingInterval = 5000;
/** Throw an exception on 18+ Age Restriction */
private boolean throwOnAgeRestriction;
/**
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
* @see <a href="https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages">Documentation: How to obtain sessionId</a>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -91,7 +91,6 @@ public class TikTokLive {
return new TikTokLiveHttpClient();
}
//I don't like it, but it is reasonable for now
private static GiftsManager giftsManager;
@@ -108,6 +107,4 @@ public class TikTokLive {
}
return giftsManager;
}
}

View File

@@ -23,26 +23,19 @@
package io.github.jwdeveloper.tiktok;
import com.google.protobuf.ByteString;
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.control.*;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent;
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
import io.github.jwdeveloper.tiktok.data.requests.*;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.*;
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
import io.github.jwdeveloper.tiktok.listener.*;
import io.github.jwdeveloper.tiktok.live.*;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.models.ConnectionState;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.websocket.SocketClient;
import java.util.Base64;
@@ -144,7 +137,7 @@ public class TikTokLiveClient implements LiveClient {
var liveDataRequest = new LiveData.Request(userData.getRoomId());
var liveData = httpClient.fetchLiveData(liveDataRequest);
if (liveData.isAgeRestricted())
if (liveData.isAgeRestricted() && clientSettings.isThrowOnAgeRestriction())
throw new TikTokLiveException("Livestream for " + liveRoomInfo.getHostName() + " is 18+ or age restricted!");
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound)

View File

@@ -207,8 +207,14 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
//LinkMic events
// mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
// mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
mapper.forMessage(WebcastLinkMicBattle.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicBattle.class);
return MappingResult.of(message, new TikTokLinkMicBattleEvent(message));
});
mapper.forMessage(WebcastLinkMicArmies.class, (inputBytes, messageName, mapperHelper) -> {
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastLinkMicArmies.class);
return MappingResult.of(message, new TikTokLinkMicArmiesEvent(message));
});
// mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
// mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);

View File

@@ -1,13 +1,9 @@
package io.github.jwdeveloper.tiktok.gifts;
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -32,11 +28,7 @@ public class TikTokGiftsManager implements GiftsManager {
}
public Gift getById(int giftId) {
if (!giftsByIdIndex.containsKey(giftId)) {
return Gift.UNDEFINED;
}
return giftsByIdIndex.get(giftId);
return giftsByIdIndex.getOrDefault(giftId, Gift.UNDEFINED);
}
public Gift getByFilter(Predicate<Gift> filter) {
@@ -44,7 +36,7 @@ public class TikTokGiftsManager implements GiftsManager {
.stream()
.filter(filter)
.findFirst()
.orElseGet(() -> Gift.UNDEFINED);
.orElse(Gift.UNDEFINED);
}
@Override

View File

@@ -65,8 +65,7 @@ public class LiveDataMapper {
default -> LiveData.LiveStatus.HostNotFound;
};
response.setLiveStatus(statusValue);
} else if (data.has("prompts") && jsonObject.has("status_code") &&
data.get("prompts").getAsString().isEmpty() && jsonObject.get("status_code").isJsonPrimitive()) {
} else if (data.has("prompts") && data.get("prompts").getAsString().isEmpty() && jsonObject.has("status_code")) {
response.setAgeRestricted(jsonObject.get("status_code").getAsInt() == TikTokLiveHttpClient.TIKTOK_AGE_RESTRICTED_CODE);
} else {
response.setLiveStatus(LiveData.LiveStatus.HostNotFound);

View File

@@ -27,13 +27,11 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.*;
import io.github.jwdeveloper.tiktok.data.models.Picture;
import io.github.jwdeveloper.tiktok.data.models.gifts.*;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
import lombok.SneakyThrows;
import sun.misc.Unsafe;
import java.util.*;
@@ -124,36 +122,8 @@ public class TikTokGiftEventHandler {
}
if (gift.getPicture().getLink().endsWith(".webp"))
{
updatePicture(gift, giftMessage);
}
gift.setPicture(Picture.map(giftMessage.getGift().getImage()));
return gift;
}
// TODO-kohlerpop1: I do not think this method is needed for any reason?
// TODO response:
/**
* Some generated gifts in JSON file contains .webp image format,
* that's bad since java by the defult is not supporing .webp and when URL is
* converted to Java.io.Image then image is null
*
* However, TikTok in GiftWebcast event always has image in .jpg format,
* so I take advantage of it and swap .webp url with .jpg url
*
*/
private void updatePicture(Gift gift, WebcastGiftMessage webcastGiftMessage) {
try {
var picture = Picture.map(webcastGiftMessage.getGift().getImage());
var constructor = Unsafe.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
var field = Gift.class.getDeclaredField("picture");
field.setAccessible(true);
field.set(gift, picture);
} catch (Exception e) {
throw new TikTokLiveException("Unable to update picture in gift: " + gift.toString());
}
}
}

View File

@@ -117,7 +117,7 @@ class TikTokGiftEventHandlerTest {
giftBuilder.setId(giftId);
giftBuilder.setName(giftName);
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
giftBuilder.setImage(Image.newBuilder().addUrl(giftImage).build());
giftBuilder.setType(streakable ? 1 : 0);
userBuilder.setId(userId);

View File

@@ -41,7 +41,7 @@
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -75,7 +75,7 @@
<dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>extension-collector</artifactId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -70,7 +70,7 @@ Maven
<dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>Client</artifactId>
<version>1.5.0-Release</version>
<version>1.6.0-Release</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>TikTokLiveJava</artifactId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
@@ -33,7 +33,7 @@
<dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>API</artifactId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -25,9 +25,14 @@ package io.github.jwdeveloper.tiktok.extension.collector.api.settings;
import lombok.Data;
import java.io.File;
import java.util.function.*;
@Data
public class FileDataCollectorSettings {
private File parentFile;
private BiPredicate<String, String> typeFilter = (dataType, dataTypeName) -> true;
private Predicate<String> userFilter = (tiktokUser) -> true;
private boolean useFileLocks = false;
private boolean appendUserName = false;
}

View File

@@ -5,17 +5,20 @@ import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCol
import org.bson.Document;
import org.bson.json.JsonWriterSettings;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.*;
public class FileStorage implements Storage {
private final FileDataCollectorSettings settings;
private final Map<String, ReentrantLock> locks;
public FileStorage(FileDataCollectorSettings fileDataCollectorSettings) {
this.settings = fileDataCollectorSettings;
this.locks = settings.isUseFileLocks() ? new ConcurrentHashMap<>() : null;
}
@Override
@@ -30,11 +33,23 @@ public class FileStorage implements Storage {
@Override
public void insert(Document document) {
var fileName = document.get("dataType") + "_" + document.get("dataTypeName") + ".json";
if (settings.getTypeFilter().test(document.getString("dataType"), document.getString("dataTypeName")) && settings.getUserFilter().test(document.getString("tiktokUser"))) {
var fileName = document.get("dataType") + "_" + document.get("dataTypeName") + (settings.isAppendUserName() ? "_"+document.getString("tiktokUser") : "") + ".json";
if (settings.isUseFileLocks()) {
var lock = locks.computeIfAbsent(fileName, s -> new ReentrantLock());
lock.lock();
save(document, fileName);
lock.unlock();
} else
save(document, fileName);
}
}
private void save(Document document, String fileName) {
try {
var file = new File(settings.getParentFile(), fileName);
file.createNewFile();
Files.writeString(file.toPath(), document.toJson(JsonWriterSettings.builder().indent(true).build()), StandardOpenOption.APPEND);
Files.writeString(file.toPath(), document.toJson(JsonWriterSettings.builder().indent(true).build())+'\n', StandardOpenOption.APPEND);
} catch (IOException e) {
e.printStackTrace();
}

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>extension-recorder</artifactId>

View File

@@ -7,7 +7,7 @@
<groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>TikTokLiveJava</artifactId>
<packaging>pom</packaging>
<version>1.5.3-Release</version>
<version>1.6.0-Release</version>
<modules>
<module>API</module>
<module>Client</module>