mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-28 09:19:40 -05:00
Compare commits
57 Commits
develop-1-
...
1.0.15-Rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1308b86567 | ||
|
|
20ba88c0ac | ||
|
|
77533ea4be | ||
|
|
3231924f8f | ||
|
|
ea525470e2 | ||
|
|
b0bf4ac606 | ||
|
|
0b9f1570d0 | ||
|
|
7a4c7fecbd | ||
|
|
0ae9068858 | ||
|
|
8905958207 | ||
|
|
c12f3cc4dc | ||
|
|
7402899f52 | ||
|
|
1b8b150d61 | ||
|
|
b2305b7bed | ||
|
|
7b911838a2 | ||
|
|
e44cb71869 | ||
|
|
af8c689417 | ||
|
|
81ac92fb33 | ||
|
|
34a78b5435 | ||
|
|
534cb7906d | ||
|
|
0bb8edfe5c | ||
|
|
4979c1b27a | ||
|
|
f7c8ffdaa5 | ||
|
|
c1fda687d3 | ||
|
|
05c49c4545 | ||
|
|
7d36f36cee | ||
|
|
f8a716429d | ||
|
|
fee805f0ea | ||
|
|
1733102aff | ||
|
|
89f54d5976 | ||
|
|
39055b5f3a | ||
|
|
cd9e9ead85 | ||
|
|
5a2d2d23f0 | ||
|
|
3eed982d6b | ||
|
|
385560de3a | ||
|
|
2e37b6627b | ||
|
|
c4f0d63b43 | ||
|
|
15550ed703 | ||
|
|
c7d84218f2 | ||
|
|
1ecd192539 | ||
|
|
d6c0d50ac3 | ||
|
|
b4997da0a8 | ||
|
|
82990665b8 | ||
|
|
155b47977d | ||
|
|
3e262773a4 | ||
|
|
89fbeb848b | ||
|
|
aa99c5929b | ||
|
|
4dd866c6cc | ||
|
|
0d384f0fdc | ||
|
|
4f3ec1c6d9 | ||
|
|
31075e5f09 | ||
|
|
33a3f7afb8 | ||
|
|
6c888c5d5b | ||
|
|
214aa3b1ff | ||
|
|
3f2c9083d5 | ||
|
|
450014759c | ||
|
|
790f568244 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,10 +1,10 @@
|
|||||||
backend-infrastructure/.aws-sam
|
backend-infrastructure/.aws-sam
|
||||||
|
|
||||||
# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
|
# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
|
||||||
|
*.db
|
||||||
### Linux ###
|
### Linux ###
|
||||||
*~
|
*~
|
||||||
|
.db
|
||||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
.fuse_hidden*
|
.fuse_hidden*
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class ClientSettings {
|
|||||||
* Whether to print Logs to Console
|
* Whether to print Logs to Console
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private boolean printToConsole;
|
private boolean printToConsole = true;
|
||||||
/**
|
/**
|
||||||
* LoggingLevel for Logs
|
* LoggingLevel for Logs
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface TikTokEventHandler
|
public @interface TikTokEventObserver
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,8 @@ public class TikTokUserInfo
|
|||||||
|
|
||||||
String roomId;
|
String roomId;
|
||||||
|
|
||||||
|
long startTime;
|
||||||
|
|
||||||
public enum UserStatus
|
public enum UserStatus
|
||||||
{
|
{
|
||||||
NotFound,
|
NotFound,
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ public class TikTokCommentEvent extends TikTokHeaderEvent {
|
|||||||
|
|
||||||
public TikTokCommentEvent(WebcastChatMessage msg) {
|
public TikTokCommentEvent(WebcastChatMessage msg) {
|
||||||
super(msg.getCommon());
|
super(msg.getCommon());
|
||||||
user = User.map(msg.getUser());
|
user = User.map(msg.getUser(),msg.getUserIdentity());
|
||||||
text = msg.getContent();
|
text = msg.getContent();
|
||||||
visibleToSender = msg.getVisibleToSender();
|
visibleToSender = msg.getVisibleToSender();
|
||||||
getUserLanguage = msg.getContentLanguage();
|
getUserLanguage = msg.getContentLanguage();
|
||||||
mentionedUser = User.map(msg.getAtUser(),msg.getUserIdentity());
|
mentionedUser = User.map(msg.getAtUser());
|
||||||
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
|
pictures = msg.getEmotesListList().stream().map(e -> Picture.map(e.getEmote().getImage())).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
|||||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ import lombok.Getter;
|
|||||||
* <p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
* <p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
* <p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
* <p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
* <p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
* <p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||||
*
|
* <p>
|
||||||
* Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
* Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
*/
|
*/
|
||||||
@EventMeta(eventType = EventType.Message)
|
@EventMeta(eventType = EventType.Message)
|
||||||
@@ -48,8 +49,8 @@ import lombok.Getter;
|
|||||||
public class TikTokGiftComboEvent extends TikTokGiftEvent {
|
public class TikTokGiftComboEvent extends TikTokGiftEvent {
|
||||||
private final GiftSendType comboState;
|
private final GiftSendType comboState;
|
||||||
|
|
||||||
public TikTokGiftComboEvent(Gift gift, WebcastGiftMessage msg, GiftSendType comboState) {
|
public TikTokGiftComboEvent(Gift gift, User host, WebcastGiftMessage msg, GiftSendType comboState) {
|
||||||
super(gift, msg);
|
super(gift, host, msg);
|
||||||
this.comboState = comboState;
|
this.comboState = comboState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,17 @@ package io.github.jwdeveloper.tiktok.data.events.gift;
|
|||||||
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/*
|
|
||||||
|
/**
|
||||||
* Triggered when user sends gifts that has
|
* Triggered when user sends gifts that has
|
||||||
* no combo (most of expensive gifts)
|
* no combo (most of expensive gifts)
|
||||||
* or if combo has finished
|
* or if combo has finished
|
||||||
@@ -43,11 +46,18 @@ import lombok.Getter;
|
|||||||
public class TikTokGiftEvent extends TikTokHeaderEvent {
|
public class TikTokGiftEvent extends TikTokHeaderEvent {
|
||||||
private final Gift gift;
|
private final Gift gift;
|
||||||
private final User user;
|
private final User user;
|
||||||
|
private final User toUser;
|
||||||
private final int combo;
|
private final int combo;
|
||||||
public TikTokGiftEvent(Gift gift, WebcastGiftMessage msg) {
|
|
||||||
|
public TikTokGiftEvent(Gift gift, User liveHost, WebcastGiftMessage msg) {
|
||||||
super(msg.getCommon());
|
super(msg.getCommon());
|
||||||
this.gift = gift;
|
this.gift = gift;
|
||||||
user = User.map(msg.getUser(), msg.getUserIdentity());
|
user = User.map(msg.getUser(), msg.getUserIdentity());
|
||||||
|
if (msg.getToUser().getNickname().isEmpty()) {
|
||||||
|
toUser = liveHost;
|
||||||
|
} else {
|
||||||
|
toUser = User.map(msg.getToUser());
|
||||||
|
}
|
||||||
combo = msg.getComboCount();
|
combo = msg.getComboCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.data.events.http;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.http.HttpData;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EventMeta(eventType = EventType.Debug)
|
||||||
|
public class TikTokHttpResponseEvent extends TikTokEvent
|
||||||
|
{
|
||||||
|
String url;
|
||||||
|
|
||||||
|
HttpData response;
|
||||||
|
|
||||||
|
HttpData request;
|
||||||
|
}
|
||||||
@@ -28,15 +28,10 @@ import lombok.Getter;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
|
||||||
public class Picture {
|
public class Picture {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -49,7 +44,6 @@ public class Picture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Picture map(io.github.jwdeveloper.tiktok.messages.data.Image profilePicture) {
|
public static Picture map(io.github.jwdeveloper.tiktok.messages.data.Image profilePicture) {
|
||||||
|
|
||||||
var index = profilePicture.getUrlListCount() - 1;
|
var index = profilePicture.getUrlListCount() - 1;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return new Picture("");
|
return new Picture("");
|
||||||
@@ -74,12 +68,11 @@ public class Picture {
|
|||||||
return CompletableFuture.supplyAsync(this::downloadImage);
|
return CompletableFuture.supplyAsync(this::downloadImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage download(String urlString)
|
private BufferedImage download(String urlString) {
|
||||||
{
|
if (urlString.isEmpty()) {
|
||||||
if(urlString.isEmpty())
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var baos = new ByteArrayOutputStream();
|
var baos = new ByteArrayOutputStream();
|
||||||
try (var is = new URL(urlString).openStream()) {
|
try (var is = new URL(urlString).openStream()) {
|
||||||
var byteChunk = new byte[4096];
|
var byteChunk = new byte[4096];
|
||||||
@@ -103,4 +96,9 @@ public class Picture {
|
|||||||
public static Picture Empty() {
|
public static Picture Empty() {
|
||||||
return new Picture("");
|
return new Picture("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Picture{link='" + link + "', image=" + image + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,4 @@ public class Badge {
|
|||||||
public static Badge empty() {
|
public static Badge empty() {
|
||||||
return new Badge();
|
return new Badge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,19 +24,22 @@ package io.github.jwdeveloper.tiktok.data.models.badges;
|
|||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class CombineBadge extends Badge {
|
public class CombineBadge extends Badge {
|
||||||
private final Picture picture;
|
private final Picture picture;
|
||||||
private final String text;
|
private final String text;
|
||||||
private final String subText;
|
private final String subText;
|
||||||
|
|
||||||
|
|
||||||
public CombineBadge(BadgeStruct.CombineBadge combineBadge) {
|
public CombineBadge(BadgeStruct.CombineBadge combineBadge) {
|
||||||
|
|
||||||
picture = Picture.map(combineBadge.getIcon());
|
picture = Picture.map(combineBadge.getIcon());
|
||||||
text = combineBadge.getText().getDefaultPattern();
|
text = combineBadge.getText().getDefaultPattern();
|
||||||
subText = combineBadge.getStr();
|
subText = combineBadge.getStr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CombineBadge{picture=" + picture +", text='" + text + "', subText='" + subText + "'}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,12 +24,18 @@ package io.github.jwdeveloper.tiktok.data.models.badges;
|
|||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class PictureBadge extends Badge {
|
public class PictureBadge extends Badge {
|
||||||
|
|
||||||
private final Picture picture;
|
private final Picture picture;
|
||||||
public PictureBadge(BadgeStruct.ImageBadge imageBadge) {
|
|
||||||
|
|
||||||
|
public PictureBadge(BadgeStruct.ImageBadge imageBadge) {
|
||||||
picture = Picture.map(imageBadge.getImage());
|
picture = Picture.map(imageBadge.getImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PictureBadge{picture=" + picture + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,12 +23,18 @@
|
|||||||
package io.github.jwdeveloper.tiktok.data.models.badges;
|
package io.github.jwdeveloper.tiktok.data.models.badges;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class StringBadge extends Badge {
|
public class StringBadge extends Badge {
|
||||||
|
private final String text;
|
||||||
|
|
||||||
public String text;
|
|
||||||
public StringBadge(BadgeStruct.StringBadge stringBadge) {
|
public StringBadge(BadgeStruct.StringBadge stringBadge) {
|
||||||
|
|
||||||
this.text = stringBadge.getStr();
|
this.text = stringBadge.getStr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "StringBadge{text='" + text + "'}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,13 +23,18 @@
|
|||||||
package io.github.jwdeveloper.tiktok.data.models.badges;
|
package io.github.jwdeveloper.tiktok.data.models.badges;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.BadgeStruct;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
public class TextBadge extends Badge
|
@Getter
|
||||||
{
|
public class TextBadge extends Badge {
|
||||||
private final String text;
|
private final String text;
|
||||||
|
|
||||||
public TextBadge(BadgeStruct.TextBadge textBadge)
|
public TextBadge(BadgeStruct.TextBadge textBadge) {
|
||||||
{
|
|
||||||
this.text = textBadge.getDefaultPattern();
|
this.text = textBadge.getDefaultPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TextBadge{text='" + text + "'}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.data.models.http;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class HttpData {
|
||||||
|
String url;
|
||||||
|
String method;
|
||||||
|
Map<String, List<String>> headers = new TreeMap<>();
|
||||||
|
Map<String, String> parameters = new TreeMap<>();
|
||||||
|
int status;
|
||||||
|
String body = "";
|
||||||
|
|
||||||
|
|
||||||
|
public static HttpData map(HttpRequest request) {
|
||||||
|
var data = new HttpData();
|
||||||
|
data.setUrl(request.uri().getPath());
|
||||||
|
data.setMethod(request.method());
|
||||||
|
data.setParameters(extractQueryParams(request.uri()));
|
||||||
|
data.setStatus(200);
|
||||||
|
if (request.bodyPublisher().isPresent()) {
|
||||||
|
data.setBody(request.bodyPublisher().get().toString());
|
||||||
|
}
|
||||||
|
data.setHeaders(Collections.unmodifiableMap(request.headers().map()));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpData map(HttpResponse<String> response) {
|
||||||
|
var data = new HttpData();
|
||||||
|
data.setUrl(response.uri().getPath());
|
||||||
|
data.setMethod(response.request().method());
|
||||||
|
data.setParameters(extractQueryParams(response.uri()));
|
||||||
|
data.setStatus(200);
|
||||||
|
data.setBody(response.body());
|
||||||
|
data.setHeaders(Collections.unmodifiableMap(response.headers().map()));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Map<String, String> extractQueryParams(URI uri) {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
String query = uri.getQuery();
|
||||||
|
if (query != null && !query.isEmpty()) {
|
||||||
|
for (String param : query.split("&")) {
|
||||||
|
String[] keyValue = param.split("=");
|
||||||
|
if (keyValue.length > 1) {
|
||||||
|
params.put(keyValue[0], keyValue[1]);
|
||||||
|
} else {
|
||||||
|
params.put(keyValue[0], ""); // Empty value for parameter without explicit value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,13 +43,12 @@ public class User {
|
|||||||
private long followers;
|
private long followers;
|
||||||
private List<Badge> badges;
|
private List<Badge> badges;
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.NONE)
|
||||||
private Set<UserAttribute> attributes;
|
private final Set<UserAttribute> attributes = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<UserAttribute> getAttributes() {
|
public List<UserAttribute> getAttributes() {
|
||||||
return attributes.stream().toList();
|
return attributes.stream().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAttribute(UserAttribute userFlag) {
|
public boolean hasAttribute(UserAttribute userFlag) {
|
||||||
return attributes.contains(userFlag);
|
return attributes.contains(userFlag);
|
||||||
}
|
}
|
||||||
@@ -106,7 +105,6 @@ public class User {
|
|||||||
this.following = following;
|
this.following = following;
|
||||||
this.followers = followers;
|
this.followers = followers;
|
||||||
this.badges = badges;
|
this.badges = badges;
|
||||||
this.attributes = new HashSet<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User(Long id,
|
public User(Long id,
|
||||||
@@ -123,14 +121,12 @@ public class User {
|
|||||||
this.following = following;
|
this.following = following;
|
||||||
this.followers = followers;
|
this.followers = followers;
|
||||||
this.badges = badges;
|
this.badges = badges;
|
||||||
this.attributes = new HashSet<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User(Long userId,
|
public User(Long userId,
|
||||||
String nickName) {
|
String nickName) {
|
||||||
this.id = userId;
|
this.id = userId;
|
||||||
this.name = nickName;
|
this.name = nickName;
|
||||||
this.attributes = new HashSet<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User(Long userId,
|
public User(Long userId,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.live;
|
package io.github.jwdeveloper.tiktok.live;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
|
|
||||||
@@ -55,6 +56,11 @@ public interface LiveClient {
|
|||||||
void disconnect();
|
void disconnect();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to manually invoke event
|
||||||
|
*/
|
||||||
|
void publishEvent(TikTokEvent event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about gifts
|
* Get information about gifts
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public interface LiveRoomInfo
|
|||||||
*/
|
*/
|
||||||
int getTotalViewersCount();
|
int getTotalViewersCount();
|
||||||
int getLikesCount();
|
int getLikesCount();
|
||||||
|
long getStartTime();
|
||||||
boolean isAgeRestricted();
|
boolean isAgeRestricted();
|
||||||
String getRoomId();
|
String getRoomId();
|
||||||
String getHostName();
|
String getHostName();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||||
@@ -39,61 +40,140 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandl
|
|||||||
public interface EventsBuilder<T> {
|
public interface EventsBuilder<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to register own custom events
|
* Invoked whenever specified event is triggered
|
||||||
* @param eventClazz event class
|
*
|
||||||
* @param event action
|
* @param eventClass event class
|
||||||
|
* @param action action
|
||||||
*/
|
*/
|
||||||
<E extends TikTokEvent> T onCustomEvent(Class<E> eventClazz, EventConsumer<E> event);
|
<E extends TikTokEvent> T onEvent(Class<E> eventClass, EventConsumer<E> action);
|
||||||
|
|
||||||
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> event);
|
|
||||||
|
|
||||||
T onComment(EventConsumer<TikTokCommentEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> event);
|
|
||||||
|
|
||||||
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> event);
|
|
||||||
|
|
||||||
|
|
||||||
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> event);
|
/**
|
||||||
|
* Invoked whenever any event is triggered
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onEvent(EventConsumer<TikTokEvent> action);
|
||||||
|
|
||||||
T onGift(EventConsumer<TikTokGiftEvent> event);
|
/**
|
||||||
|
* Invoked when information about room (live) got updated such as viewer count, etc..
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action);
|
||||||
|
|
||||||
T onQuestion(EventConsumer<TikTokQuestionEvent> event);
|
/**
|
||||||
|
* Invoked when someone send message to chat
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onComment(EventConsumer<TikTokCommentEvent> action);
|
||||||
|
|
||||||
T onSubscribe(EventConsumer<TikTokSubscribeEvent> event);
|
|
||||||
|
|
||||||
T onFollow(EventConsumer<TikTokFollowEvent> event);
|
/**
|
||||||
|
* Invoked when TikTokLiveJava makes http request and getting response
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action);
|
||||||
|
|
||||||
T onLike(EventConsumer<TikTokLikeEvent> event);
|
/**
|
||||||
|
* Invoked when TikTok protocolBuffer data "message" was successfully mapped to event
|
||||||
|
* events contains protocol-buffer "Message" and TikTokLiveJava "Event"
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action);
|
||||||
|
|
||||||
T onEmote(EventConsumer<TikTokEmoteEvent> event);
|
/**
|
||||||
|
* Invoked when there was not found event mapper for TikTok protocolBuffer data "message"
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action);
|
||||||
|
|
||||||
T onJoin(EventConsumer<TikTokJoinEvent> event);
|
/**
|
||||||
|
* Invoked every time TikTok sends protocolBuffer data to websocket
|
||||||
|
* Response contains list of messages that are later mapped to events
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action);
|
||||||
|
|
||||||
T onShare(EventConsumer<TikTokShareEvent> event);
|
|
||||||
|
|
||||||
// T onChest(EventConsumer<TikTokChestEvent> event);
|
/**
|
||||||
|
* Invoked for gifts that has no combo, or when combo finishes
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onGift(EventConsumer<TikTokGiftEvent> action);
|
||||||
|
|
||||||
T onLivePaused(EventConsumer<TikTokLivePausedEvent> event);
|
/**
|
||||||
|
* Invoked for gifts that has combo options such as roses
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action);
|
||||||
|
|
||||||
T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> event);
|
|
||||||
|
|
||||||
T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> event);
|
T onQuestion(EventConsumer<TikTokQuestionEvent> action);
|
||||||
|
|
||||||
T onConnected(EventConsumer<TikTokConnectedEvent> event);
|
T onSubscribe(EventConsumer<TikTokSubscribeEvent> action);
|
||||||
|
|
||||||
T onReconnecting(EventConsumer<TikTokReconnectingEvent> event);
|
T onFollow(EventConsumer<TikTokFollowEvent> action);
|
||||||
|
|
||||||
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> event);
|
T onLike(EventConsumer<TikTokLikeEvent> action);
|
||||||
|
|
||||||
T onError(EventConsumer<TikTokErrorEvent> event);
|
T onEmote(EventConsumer<TikTokEmoteEvent> action);
|
||||||
|
|
||||||
T onEvent(EventConsumer<TikTokEvent> event);
|
T onJoin(EventConsumer<TikTokJoinEvent> action);
|
||||||
|
|
||||||
|
T onShare(EventConsumer<TikTokShareEvent> action);
|
||||||
|
|
||||||
|
T onLivePaused(EventConsumer<TikTokLivePausedEvent> action);
|
||||||
|
|
||||||
|
T onLiveUnpaused(EventConsumer<TikTokLiveUnpausedEvent> action);
|
||||||
|
|
||||||
|
T onLiveEnded(EventConsumer<TikTokLiveEndedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client has been successfully connected to live
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onConnected(EventConsumer<TikTokConnectedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client tries to reconnect
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onReconnecting(EventConsumer<TikTokReconnectingEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when client disconnected
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when exception was throed inside client or event handler
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onError(EventConsumer<TikTokErrorEvent> action);
|
||||||
|
|
||||||
|
|
||||||
// TODO Figure out how those events works
|
// TODO Figure out how those events works
|
||||||
|
// T onChest(EventConsumer<TikTokChestEvent> event);
|
||||||
|
|
||||||
//T onLinkMicFanTicket(TikTokEventConsumer<TikTokLinkMicFanTicketEvent> event);
|
//T onLinkMicFanTicket(TikTokEventConsumer<TikTokLinkMicFanTicketEvent> event);
|
||||||
|
|
||||||
//T onEnvelope(TikTokEventConsumer<TikTokEnvelopeEvent> event);
|
//T onEnvelope(TikTokEventConsumer<TikTokEnvelopeEvent> event);
|
||||||
|
|||||||
@@ -1,73 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import com.google.protobuf.GeneratedMessageV3;
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public interface TikTokMapper {
|
public interface TikTokMapper {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when `sourceClass` is mapped,
|
* * if mapper is not found for messageName, TikTokLiveException is thrown
|
||||||
* input is bytes that are coming from TikTok in `sourceClass` packet
|
|
||||||
* output is TikTok event we want to create
|
|
||||||
* <p>
|
|
||||||
* bytesToEvent(WebcastGiftMessage.class, bytes ->
|
|
||||||
* {
|
|
||||||
* var giftMessage = WebcastGiftMessage.parseFrom(bytes);
|
|
||||||
* var giftName = giftMessage.getGift().getName();
|
|
||||||
* return new TikTokEvent(Gift.ROSE, giftMessage);
|
|
||||||
* })
|
|
||||||
*
|
*
|
||||||
* @param sourceClass protocol buffer webcast class
|
* @param messageName
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
* @return TikTokMapperModel
|
||||||
*/
|
*/
|
||||||
void bytesToEvent(Class<? extends GeneratedMessageV3> sourceClass, Function<byte[], TikTokEvent> onMapping);
|
TikTokMapperModel forMessage(String messageName);
|
||||||
|
|
||||||
void bytesToEvents(Class<? extends GeneratedMessageV3> sourceClass, Function<byte[], List<TikTokEvent>> onMapping);
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, Function<byte[], TikTokEvent> onMapping);
|
||||||
|
|
||||||
|
TikTokMapperModel forAnyMessage();
|
||||||
|
|
||||||
|
|
||||||
/**
|
boolean isRegistered(String mapperName);
|
||||||
* In case you found some TikTok message that has not Webcast class use this method
|
|
||||||
*
|
|
||||||
* @param messageName Name of TikTok data event
|
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
|
||||||
*/
|
|
||||||
void bytesToEvent(String messageName, Function<byte[], TikTokEvent> onMapping);
|
|
||||||
|
|
||||||
void bytesToEvents(String messageName, Function<byte[], List<TikTokEvent>> onMapping);
|
<T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method can be used to override default mapping for
|
|
||||||
* certain TikTok incoming data message. For this example
|
|
||||||
* we are overriding WebcastGiftMessage and retuning CustomGiftEvent
|
|
||||||
* instead of TikTokGiftEvent
|
|
||||||
* <p>
|
|
||||||
* webcastObjectToEvent(WebcastGiftMessage.class, webcastGiftMessage ->
|
|
||||||
* {
|
|
||||||
* var giftName = webcastGiftMessage.getGift().getName();
|
|
||||||
* var user = webcastGiftMessage.getUser().getNickname();
|
|
||||||
* return new CustomGiftEvent(giftName, user);
|
|
||||||
* })
|
|
||||||
*
|
|
||||||
* @param sourceClass ProtocolBuffer class that represent incoming custom data, hint class should starts with Webcast prefix
|
|
||||||
* @param onMapping lambda function that is triggered on mapping. takes as input ProtocolBuffer object and as output TikTokEvent
|
|
||||||
*/
|
|
||||||
<T extends GeneratedMessageV3> void webcastObjectToEvent(Class<T> sourceClass, Function<T, TikTokEvent> onMapping);
|
|
||||||
|
|
||||||
<T extends GeneratedMessageV3> void webcastObjectToEvents(Class<T> sourceClass, Function<T, List<TikTokEvent>> onMapping);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered when `sourceClass` is mapped,
|
|
||||||
* looking for constructor in `outputClass` with one parameter that is of type `sourceClass`
|
|
||||||
* and created instance of object from this constructor
|
|
||||||
*
|
|
||||||
* @param sourceClass protocol buffer webcast class
|
|
||||||
* @param outputClass TikTok event class
|
|
||||||
*/
|
|
||||||
void webcastObjectToConstructor(Class<? extends GeneratedMessageV3> sourceClass, Class<? extends TikTokEvent> outputClass);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
||||||
|
|
||||||
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
|
||||||
|
|
||||||
|
public interface TikTokMapperHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @param messageClass class that we want to serialize bytes to
|
||||||
|
* @param <T> @messageClass must be class that is made by protocol buffer
|
||||||
|
* @return object of type @messageClass
|
||||||
|
*/
|
||||||
|
<T extends GeneratedMessageV3> T bytesToWebcastObject(byte[] bytes, Class<T> messageClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @param messageName class that we want to serialize bytes to
|
||||||
|
* @return protocol buffer objects if class for @messageName has been found
|
||||||
|
* @throws TikTokMessageMappingException if there is no suitable class for messageName
|
||||||
|
*/
|
||||||
|
Object bytesToWebcastObject(byte[] bytes, String messageName);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param messageName checks wheaten TikTokLiveJava has class representation for certain protocol-buffer message name
|
||||||
|
* @return false if class is not found
|
||||||
|
*/
|
||||||
|
boolean isMessageHasProtoClass(String messageName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes protocol buffer data bytes
|
||||||
|
* @return tree structure of protocol buffer object
|
||||||
|
* @see ProtoBufferObject
|
||||||
|
*/
|
||||||
|
ProtoBufferObject bytesToProtoBufferStructure(byte[] bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts object to json
|
||||||
|
*
|
||||||
|
* @param obj any object
|
||||||
|
* @return pretty formatted json
|
||||||
|
*/
|
||||||
|
String toJson(Object obj);
|
||||||
|
}
|
||||||
@@ -20,24 +20,39 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel;
|
import io.github.jwdeveloper.tiktok.mappers.data.AfterMappingAction;
|
||||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
|
||||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
@RegisterBeanMapper(TikTokResponseModel.class)
|
public interface TikTokMapperModel {
|
||||||
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();
|
* @return name of websocket message that this mapper is mapping from
|
||||||
|
*/
|
||||||
|
|
||||||
|
String getSourceMessageName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action Input bytes from websocket, you can modify it and returns different bytes
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onBeforeMapping(MappingAction<byte[]> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action Input bytes from websocket. As output returns list of tiktok live events
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onMapping(MappingAction<MappingResult> action);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param action You can modify output list of TikTokLive events
|
||||||
|
* @see AfterMappingAction
|
||||||
|
*/
|
||||||
|
TikTokMapperModel onAfterMapping(Function<MappingResult, List<TikTokEvent>> action);
|
||||||
}
|
}
|
||||||
@@ -20,17 +20,18 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
package io.github.jwdeveloper.tiktok.mappers.data;
|
||||||
|
|
||||||
public class TikTokMessageCollectorClient
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
{
|
|
||||||
public static TikTokMessagessCollectorBuilder create(String outputName)
|
|
||||||
{
|
|
||||||
return new TikTokMessagessCollectorBuilder(outputName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TikTokMessagessCollectorBuilder create(MessageCollector messageCollector, String outputName)
|
import java.util.List;
|
||||||
{
|
|
||||||
return new TikTokMessagessCollectorBuilder(messageCollector,outputName);
|
@FunctionalInterface
|
||||||
}
|
public interface AfterMappingAction {
|
||||||
|
/**
|
||||||
|
* @param source object that was used as source to create events
|
||||||
|
* @param events list of events prepared before, could be modified or changed
|
||||||
|
* @return list of events that will be invoked
|
||||||
|
*/
|
||||||
|
List<TikTokEvent> onAfterMapping(Object source, List<TikTokEvent> events);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers.data;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface MappingAction<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inputBytes incoming bytes from TikTok server. The represents protocol buffer message that was send to client
|
||||||
|
* @param messageName name of protocol buffer message
|
||||||
|
* @param mapperHelper utils and helper methods that can be use to debbug/display/deserialize protocol buffer data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onMapping(byte[] inputBytes, String messageName, TikTokMapperHelper mapperHelper);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers.data;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class MappingResult
|
||||||
|
{
|
||||||
|
|
||||||
|
Object source;
|
||||||
|
|
||||||
|
List<TikTokEvent> events;
|
||||||
|
|
||||||
|
String message;
|
||||||
|
|
||||||
|
public static MappingResult of(Object source) {
|
||||||
|
return new MappingResult(source, List.of(),"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MappingResult of(Object source, List<TikTokEvent> events) {
|
||||||
|
return new MappingResult(source, events,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MappingResult of(Object source,TikTokEvent events) {
|
||||||
|
return new MappingResult(source, List.of(events),"");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|||||||
@@ -1000,7 +1000,7 @@ message LinkerCreateContent {
|
|||||||
|
|
||||||
message LinkerEnterContent {
|
message LinkerEnterContent {
|
||||||
repeated User LinkedUsersList = 1;
|
repeated User LinkedUsersList = 1;
|
||||||
//LinkmicMultiLiveEnum AnchorMultiLiveEnum = 2;
|
// LinkmicMultiLiveEnum AnchorMultiLiveEnum = 2;
|
||||||
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 3;
|
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,7 +1018,7 @@ message LinkerInviteContent {
|
|||||||
//Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 11;
|
//Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 11;
|
||||||
//Data.LinkmicUserSettingInfo AnchorSettingInfo = 12;
|
//Data.LinkmicUserSettingInfo AnchorSettingInfo = 12;
|
||||||
string InviterLinkmicIdStr = 13;
|
string InviterLinkmicIdStr = 13;
|
||||||
// InviteTopHostInfo FromTopHostInfo = 16;
|
// InviteTopHostInfo FromTopHostInfo = 16;
|
||||||
int64 ActionId = 17;
|
int64 ActionId = 17;
|
||||||
// repeated LinkmicUserInfo LinkedUsersList = 18;
|
// repeated LinkmicUserInfo LinkedUsersList = 18;
|
||||||
// Data.PerceptionDialogInfo Dialog = 19;
|
// Data.PerceptionDialogInfo Dialog = 19;
|
||||||
@@ -1046,9 +1046,9 @@ message LinkerLinkedListChangeContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message LinkerListChangeContent {
|
message LinkerListChangeContent {
|
||||||
repeated User LinkedUsersList = 1;
|
repeated LinkLayerListUser LinkedUsersList = 1;
|
||||||
repeated User AppliedUsersList = 2;
|
repeated LinkLayerListUser AppliedUsersList = 2;
|
||||||
repeated User ConnectingUsersList = 3;
|
repeated LinkLayerListUser ConnectingUsersList = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkerMediaChangeContent {
|
message LinkerMediaChangeContent {
|
||||||
@@ -1087,7 +1087,7 @@ message LinkerReplyContent {
|
|||||||
int64 FromRoomId = 2;
|
int64 FromRoomId = 2;
|
||||||
// LinkmicInfo FromUserLinkmicInfo = 3;
|
// LinkmicInfo FromUserLinkmicInfo = 3;
|
||||||
int64 ToUserId = 4;
|
int64 ToUserId = 4;
|
||||||
// LinkmicInfo ToUserLinkmicInfo = 5;
|
// LinkmicInfo ToUserLinkmicInfo = 5;
|
||||||
int64 LinkType = 6;
|
int64 LinkType = 6;
|
||||||
int64 ReplyStatus = 7;
|
int64 ReplyStatus = 7;
|
||||||
LinkerSetting LinkerSetting = 8;
|
LinkerSetting LinkerSetting = 8;
|
||||||
@@ -1096,8 +1096,8 @@ message LinkerReplyContent {
|
|||||||
map<int64, string> RtcExtInfoMap = 11;
|
map<int64, string> RtcExtInfoMap = 11;
|
||||||
LinkerMicIdxUpdateInfo InviteeMicIdxUpdateInfo = 12;
|
LinkerMicIdxUpdateInfo InviteeMicIdxUpdateInfo = 12;
|
||||||
map<int64, int64> ApplierMicIdxInfoMap = 13;
|
map<int64, int64> ApplierMicIdxInfoMap = 13;
|
||||||
// Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 14;
|
// Data.LinkmicMultiLiveEnum AnchorMultiLiveEnum = 14;
|
||||||
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 15;
|
// Data.LinkmicUserSettingInfo AnchorSettingInfo = 15;
|
||||||
int64 ActionId = 16;
|
int64 ActionId = 16;
|
||||||
// repeated LinkmicUserInfo LinkedUsersList = 17;
|
// repeated LinkmicUserInfo LinkedUsersList = 17;
|
||||||
int64 SourceType = 18;
|
int64 SourceType = 18;
|
||||||
@@ -1130,3 +1130,388 @@ message LinkerUpdateUserSettingContent {
|
|||||||
message LinkerWaitingListChangeContent {
|
message LinkerWaitingListChangeContent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message LinkmicUserSettingInfo {
|
||||||
|
int64 userId = 1;
|
||||||
|
int64 layout = 2; // @warning Enum not found, should be Layout
|
||||||
|
int64 fixMicNum = 3; // @warning Enum not found, should be FixMicNum
|
||||||
|
int64 allowRequestFromUser = 4; // @warning Enum not found, should be AllowRequestFromUser
|
||||||
|
int64 allowRequestFromFollowerOnly = 5; // @warning Enum not found, should be AllowRequestFromFollowerOnly
|
||||||
|
LinkmicApplierSortSetting applierSortSetting = 7; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message Player {
|
||||||
|
int64 roomId = 1;
|
||||||
|
int64 userId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AllListUser {
|
||||||
|
repeated LinkLayerListUser linkedList = 2;
|
||||||
|
repeated LinkLayerListUser appliedList = 3;
|
||||||
|
repeated LinkLayerListUser invitedList = 4;
|
||||||
|
repeated LinkLayerListUser readyList = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkLayerListUser {
|
||||||
|
User user = 1;
|
||||||
|
int64 linkmicId = 2;
|
||||||
|
Position pos = 3;
|
||||||
|
int64 linkedTimeNano = 4;
|
||||||
|
string appVersion = 5;
|
||||||
|
int64 magicNumber1 = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Position {
|
||||||
|
int32 type = 1;
|
||||||
|
LinkPosition link = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkPosition {
|
||||||
|
int32 position = 1;
|
||||||
|
int32 opt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupPlayer {
|
||||||
|
int64 channelId = 1;
|
||||||
|
User user = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DSLConfig {
|
||||||
|
int32 sceneVersion = 1;
|
||||||
|
string layoutId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupChannelAllUser {
|
||||||
|
int64 groupChannelId = 1;
|
||||||
|
repeated GroupChannelUser userList = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupChannelUser {
|
||||||
|
int64 channelId = 1;
|
||||||
|
GroupStatus status = 2; // Enum
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
AllListUser allUser = 4;
|
||||||
|
int64 joinTime = 5;
|
||||||
|
int64 linkedTime = 6;
|
||||||
|
GroupPlayer ownerUser = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCExtraInfo {
|
||||||
|
RTCEngineConfig liveRtcEngineConfig = 1;
|
||||||
|
repeated RTCLiveVideoParam liveRtcVideoParamList = 2;
|
||||||
|
RTCBitrateMap rtcBitrateMap = 3;
|
||||||
|
int32 rtcFps = 4;
|
||||||
|
string rtcBusinessId = 8;
|
||||||
|
int32 interactClientType = 10;
|
||||||
|
|
||||||
|
message RTCEngineConfig {
|
||||||
|
string rtcAppId = 1;
|
||||||
|
string rtcUserId = 2;
|
||||||
|
string rtcToken = 3;
|
||||||
|
int64 rtcChannelId = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCLiveVideoParam {
|
||||||
|
int32 strategyId = 1;
|
||||||
|
RTCVideoParam params = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCVideoParam {
|
||||||
|
int32 width = 1;
|
||||||
|
int32 height = 2;
|
||||||
|
int32 fps = 3;
|
||||||
|
int32 bitrateKbps = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RTCBitrateMap {
|
||||||
|
int32 xx1 = 1;
|
||||||
|
int32 xx2 = 2;
|
||||||
|
int32 xx3 = 3;
|
||||||
|
int32 xx4 = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateChannelContent {
|
||||||
|
Player owner = 1;
|
||||||
|
string ownerLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListChangeContent {
|
||||||
|
TextType type = 1; // Enum
|
||||||
|
AllListUser list = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiLiveContent {
|
||||||
|
InviteBizContent inviteBizContent = 2;
|
||||||
|
ReplyBizContent replyBizContent = 3;
|
||||||
|
PermitBizContent permitBizContent = 4;
|
||||||
|
KickOutBizContent kickOutBizContent = 6;
|
||||||
|
|
||||||
|
|
||||||
|
message InviteBizContent {
|
||||||
|
LinkmicUserSettingInfo anchorSettingInfo = 1;
|
||||||
|
int64 inviteSource = 2; // @warning Enum not found, should be InviteSource
|
||||||
|
User operatorUserInfo = 3;
|
||||||
|
int64 operatorLinkAdminType = 4; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
User inviteeUserInfo = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message ReplyBizContent {
|
||||||
|
int32 linkType = 1;
|
||||||
|
int32 isTurnOffInvitation = 2;
|
||||||
|
User replyUserInfo = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PermitBizContent {
|
||||||
|
LinkmicUserSettingInfo anchorSettingInfo = 1;
|
||||||
|
int64 expireTimestamp = 2;
|
||||||
|
User operatorUserInfo = 3;
|
||||||
|
int64 operatorLinkAdminType = 4; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
}
|
||||||
|
|
||||||
|
message KickOutBizContent {
|
||||||
|
User operatorUserInfo = 1;
|
||||||
|
int64 operatorLinkAdminType = 2; // @warning Enum not found, should be OperatorLinkAdminType
|
||||||
|
User kickPlayerUserInfo = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message InviteContent {
|
||||||
|
Player invitor = 1;
|
||||||
|
RTCExtraInfo inviteeRtcExtInfo = 2;
|
||||||
|
string invitorLinkMicId = 3;
|
||||||
|
string inviteeLinkMicId = 4;
|
||||||
|
bool isOwner = 5;
|
||||||
|
Position pos = 6;
|
||||||
|
DSLConfig dsl = 7;
|
||||||
|
User invitee = 8;
|
||||||
|
User operator = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @ApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message ApplyContent {
|
||||||
|
Player applier = 1;
|
||||||
|
string applierLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @PermitApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message PermitApplyContent {
|
||||||
|
Player permiter = 1;
|
||||||
|
string permiterLinkMicId = 2;
|
||||||
|
Position applierPos = 3;
|
||||||
|
ReplyStatus replyStatus = 4; // Enum
|
||||||
|
DSLConfig dsl = 5;
|
||||||
|
User applier = 6;
|
||||||
|
User operator = 7;
|
||||||
|
string applierLinkMicId = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @ReplyInviteContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message ReplyInviteContent {
|
||||||
|
Player invitee = 1;
|
||||||
|
ReplyStatus replyStatus = 2; // Enum
|
||||||
|
string inviteeLinkMicId = 3;
|
||||||
|
Position inviteePos = 4;
|
||||||
|
Player inviteOperatorUser = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @KickOutContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message KickOutContent {
|
||||||
|
Player offliner = 1;
|
||||||
|
KickoutReason kickoutReason = 2; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelApplyContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message CancelApplyContent {
|
||||||
|
Player applier = 1;
|
||||||
|
string applierLinkMicId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelInviteContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message CancelInviteContent {
|
||||||
|
Player invitor = 1;
|
||||||
|
string invitorLinkMicId = 2;
|
||||||
|
string inviteeLinkMicId = 3;
|
||||||
|
int64 inviteSeqId = 4;
|
||||||
|
Player invitee = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @LeaveContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message LeaveContent {
|
||||||
|
Player leaver = 1;
|
||||||
|
int64 leaveReason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @FinishChannelContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message FinishChannelContent {
|
||||||
|
Player owner = 1;
|
||||||
|
int64 finishReason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @JoinDirectContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message JoinDirectContent {
|
||||||
|
LinkLayerListUser joiner = 1;
|
||||||
|
AllListUser allUsers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @LeaveJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message LeaveJoinGroupContent {
|
||||||
|
GroupPlayer operator = 1;
|
||||||
|
int64 groupChannelId = 2;
|
||||||
|
string leaveSource = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @PermitJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
message PermitJoinGroupContent {
|
||||||
|
GroupPlayer approver = 1;
|
||||||
|
AgreeStatus agreeStatus = 2; // Enum
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
repeated RTCExtraInfo groupExtInfoList = 4;
|
||||||
|
GroupChannelAllUser groupUser = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @CancelJoinGroupContent
|
||||||
|
// proto.webcast.im
|
||||||
|
message CancelJoinGroupContent {
|
||||||
|
repeated GroupPlayer leaverList = 1;
|
||||||
|
GroupPlayer operator = 2;
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message P2PGroupChangeContent {
|
||||||
|
repeated RTCExtraInfo groupExtInfoList = 1;
|
||||||
|
GroupChannelAllUser groupUser = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message BusinessContent {
|
||||||
|
int64 overLength = 1;
|
||||||
|
MultiLiveContent multiLiveContent = 100;
|
||||||
|
CohostContent cohostContent = 200;
|
||||||
|
|
||||||
|
message CohostContent {
|
||||||
|
JoinGroupBizContent joinGroupBizContent = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupBizContent {
|
||||||
|
int32 fromRoomAgeRestricted = 1;
|
||||||
|
Tag fromTag = 2;
|
||||||
|
PerceptionDialogInfo dialog = 3;
|
||||||
|
PunishEventInfo punishInfo = 4;
|
||||||
|
JoinGroupMessageExtra joinGroupMsgExtra = 101;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Tag {
|
||||||
|
int32 tagType = 1;
|
||||||
|
string tagValue = 2;
|
||||||
|
string tagText = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PerceptionDialogInfo {
|
||||||
|
int64 iconType = 1; // @warning Enum not found, should be IconType
|
||||||
|
Text title = 2;
|
||||||
|
Text subTitle = 3;
|
||||||
|
Text adviceActionText = 4;
|
||||||
|
Text defaultActionText = 5;
|
||||||
|
string violationDetailUrl = 6;
|
||||||
|
int32 scene = 7;
|
||||||
|
int64 targetUserId = 8;
|
||||||
|
int64 targetRoomId = 9;
|
||||||
|
int64 countDownTime = 10;
|
||||||
|
bool showFeedback = 11;
|
||||||
|
repeated PerceptionFeedbackOption feedbackOptionsList = 12;
|
||||||
|
int64 policyTip = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PerceptionFeedbackOption {
|
||||||
|
int64 id = 1;
|
||||||
|
string contentKey = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupMessageExtra {
|
||||||
|
int64 sourceType = 1;
|
||||||
|
RivalExtra extra = 2;
|
||||||
|
repeated RivalExtra otherUsersList = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// @RivalExtra
|
||||||
|
// proto.webcast.im.JoinGroupMessageExtra
|
||||||
|
// C:\Users\ja\RiderProjects\TikTokProBufferGenerator\Application\output\sources\test.js
|
||||||
|
message RivalExtra {
|
||||||
|
int64 userCount = 4;
|
||||||
|
Image avatarThumb = 5;
|
||||||
|
string displayId = 6;
|
||||||
|
AuthenticationInfo authenticationInfo = 7;
|
||||||
|
string nickname = 8;
|
||||||
|
int64 followStatus = 9;
|
||||||
|
Hashtag hashtag = 10;
|
||||||
|
TopHostInfo topHostInfo = 11;
|
||||||
|
int64 userId = 12;
|
||||||
|
bool isBestTeammate = 13;
|
||||||
|
|
||||||
|
message AuthenticationInfo {
|
||||||
|
string customVerify = 1;
|
||||||
|
string enterpriseVerifyReason = 2;
|
||||||
|
Image authenticationBadge = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message Hashtag {
|
||||||
|
int64 id = 1;
|
||||||
|
string title = 2;
|
||||||
|
Image image = 3;
|
||||||
|
HashtagNamespace namespace = 4; // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
message TopHostInfo {
|
||||||
|
string rankType = 1;
|
||||||
|
int64 topIndex = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message JoinGroupContent {
|
||||||
|
GroupChannelAllUser groupUser = 1;
|
||||||
|
GroupPlayer joinUser = 2;
|
||||||
|
TextType type = 3; // Enum
|
||||||
|
}
|
||||||
@@ -25,6 +25,85 @@ enum EmotePrivateType {
|
|||||||
EMOTE_PRIVATE_TYPE_SUB_WAVE = 1;
|
EMOTE_PRIVATE_TYPE_SUB_WAVE = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TextType {
|
||||||
|
DISPLAY_TEXT = 0;
|
||||||
|
CONTENT = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LinkmicApplierSortSetting {
|
||||||
|
LINKMIC_APPLIER_SORT_SETTING_NONE = 0;
|
||||||
|
LINKMIC_APPLIER_SORT_SETTING_BY_GIFT_SCORE = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum HashtagNamespace {
|
||||||
|
GLOBAL = 0;
|
||||||
|
GAMING = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AgreeStatus {
|
||||||
|
AGREE_UNKNOWN = 0;
|
||||||
|
AGREE = 1;
|
||||||
|
REJECT = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KickoutReason {
|
||||||
|
KICKOUT_REASON_UNKNOWN = 0;
|
||||||
|
KICKOUT_REASON_FIRST_FRAME_TIMEOUT = 1;
|
||||||
|
KICKOUT_REASON_BY_HOST = 2;
|
||||||
|
KICKOUT_REASON_RTC_LOST_CONNECTION = 3;
|
||||||
|
KICKOUT_REASON_BY_PUNISH = 4;
|
||||||
|
KICKOUT_REASON_BY_ADMIN = 5;
|
||||||
|
KICKOUT_REASON_HOST_REMOVE_ALL_GUESTS = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GroupStatus {
|
||||||
|
GROUP_STATUS_UNKNOWN = 0;
|
||||||
|
GROUP_STATUS_WAITING = 1;
|
||||||
|
GROUP_STATUS_LINKED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BusinessCase {
|
||||||
|
BUSINESS_NOT_SET = 0;
|
||||||
|
APPLY_BIZ_CONTENT = 1;
|
||||||
|
INVITE_BIZ_CONTENT = 2;
|
||||||
|
REPLY_BIZ_CONTENT = 3;
|
||||||
|
PERMIT_BIZ_CONTENT = 4;
|
||||||
|
JOIN_DIRECT_BIZ_CONTENT = 5;
|
||||||
|
KICK_OUT_BIZ_CONTENT = 6;
|
||||||
|
LIST_CHANGE_BIZ_CONTENT = 11;
|
||||||
|
MULTI_LIVE_CONTENT = 100;
|
||||||
|
COHOST_CONTENT = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ReplyStatus {
|
||||||
|
REPLY_STATUS_UNKNOWN = 0;
|
||||||
|
REPLY_STATUS_AGREE = 1;
|
||||||
|
REPLY_STATUS_REFUSE_PERSONALLY = 2;
|
||||||
|
REPLY_STATUS_REFUSE_TYPE_NOT_SUPPORT = 3;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_INVITATION = 4;
|
||||||
|
REPLY_STATUS_REFUSE_BY_TIMEOUT = 5;
|
||||||
|
REPLY_STATUS_REFUSE_EXCEPTION = 6;
|
||||||
|
REPLY_STATUS_REFUSE_SYSTEM_NOT_SUPPORTED = 7;
|
||||||
|
REPLY_STATUS_REFUSE_SUBTYPE_DIFFERENCE = 8;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MICROOM = 9;
|
||||||
|
REPLY_STATUS_REFUSE_NOT_LOAD_PLUGIN = 10;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MULTI_GUEST = 11;
|
||||||
|
REPLY_STATUS_REFUSE_PAUSE_LIVE = 12;
|
||||||
|
REPLY_STATUS_REFUSE_OPEN_CAMERA_DIALOG_SHOWING = 13;
|
||||||
|
REPLY_STATUS_REFUSE_DRAW_GUESSING = 14;
|
||||||
|
REPLY_STATUS_REFUSE_RANDOM_MATCHING = 15;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MATCH_PROCESSING = 16;
|
||||||
|
REPLY_STATUS_REFUSE_IN_MICROOM_FOR_MULTI_COHOST = 17;
|
||||||
|
REPLY_STATUS_REFUSE_COHOST_FINISHED = 18;
|
||||||
|
REPLY_STATUS_REFUSE_NOT_CONNECTED = 19;
|
||||||
|
REPLY_STATUS_REFUSE_LINKMIC_FULL = 20;
|
||||||
|
REPLY_STATUS_REFUSE_ARC_INCOMPATIBLE = 21;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_OTHER_INVITE = 22;
|
||||||
|
REPLY_STATUS_REFUSE_PROCESSING_OTHER_APPLY = 23;
|
||||||
|
REPLY_STATUS_REFUSE_IN_ANCHOR_COHOST = 24;
|
||||||
|
REPLY_STATUS_REFUSE_TOPIC_PAIRING = 25;
|
||||||
|
}
|
||||||
|
|
||||||
enum SubscribeType {
|
enum SubscribeType {
|
||||||
SUBSCRIBETYPE_ONCE = 0;
|
SUBSCRIBETYPE_ONCE = 0;
|
||||||
@@ -137,3 +216,50 @@ enum EnvelopeDisplay
|
|||||||
EnvelopeDisplayNew = 1;
|
EnvelopeDisplayNew = 1;
|
||||||
EnvelopeDisplayHide = 2;
|
EnvelopeDisplayHide = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum CommonContentCase {
|
||||||
|
COMMON_CONTENT_NOT_SET = 0;
|
||||||
|
CREATE_CHANNEL_CONTENT = 100;
|
||||||
|
LIST_CHANGE_CONTENT = 102;
|
||||||
|
INVITE_CONTENT = 103;
|
||||||
|
APPLY_CONTENT = 104;
|
||||||
|
PERMIT_APPLY_CONTENT = 105;
|
||||||
|
REPLY_INVITE_CONTENT = 106;
|
||||||
|
KICK_OUT_CONTENT = 107;
|
||||||
|
CANCEL_APPLY_CONTENT = 108;
|
||||||
|
CANCEL_INVITE_CONTENT = 109;
|
||||||
|
LEAVE_CONTENT = 110;
|
||||||
|
FINISH_CONTENT = 111;
|
||||||
|
JOIN_DIRECT_CONTENT = 112;
|
||||||
|
JOIN_GROUP_CONTENT = 113;
|
||||||
|
PERMIT_GROUP_CONTENT = 114;
|
||||||
|
CANCEL_GROUP_CONTENT = 115;
|
||||||
|
LEAVE_GROUP_CONTENT = 116;
|
||||||
|
P2P_GROUP_CHANGE_CONTENT = 117;
|
||||||
|
GROUP_CHANGE_CONTENT = 118;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum MessageType {
|
||||||
|
MESSAGETYPE_SUBSUCCESS = 0;
|
||||||
|
MESSAGETYPE_ANCHORREMINDER = 1;
|
||||||
|
MESSAGETYPE_ENTERROOMEXPIRESOON = 2;
|
||||||
|
MESSAGETYPE_SUBGOALCREATETOANCHOR = 3;
|
||||||
|
MESSAGETYPE_SUBGOALCOMPLETETOAUDIENCE = 4;
|
||||||
|
MESSAGETYPE_SUBGOALCOMPLETETOANCHOR = 5;
|
||||||
|
MESSAGETYPE_SUBGIFTTIKTOK2USERNOTICE = 6;
|
||||||
|
MESSAGETYPE_SUBGIFTTIKTOK2ANCHORNOTICE = 7;
|
||||||
|
MESSAGETYPE_SUBGIFTTRECEIVESENDNOTICE = 8;
|
||||||
|
MESSAGETYPE_SUBGIFTSENDSUCCEEDROOMMESSAGE = 9;
|
||||||
|
MESSAGETYPE_SUBGIFTSENDSUCCEEDANCHORNOTICE = 10;
|
||||||
|
MESSAGETYPE_SUBGIFTLOWVERSIONUPGRADENOTICE = 11;
|
||||||
|
MESSAGETYPE_SUBGIFTUSERBUYAUTHNOTICE = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Scene {
|
||||||
|
SCENE_UNKNOWN = 0;
|
||||||
|
SCENE_CO_HOST = 2;
|
||||||
|
SCENE_MULTI_LIVE = 4;
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ message WebcastPushFrame {
|
|||||||
uint64 LogId = 2;
|
uint64 LogId = 2;
|
||||||
uint64 Service = 3;
|
uint64 Service = 3;
|
||||||
uint64 Method = 4;
|
uint64 Method = 4;
|
||||||
map<string,string> headers = 5;
|
map<string, string> headers = 5;
|
||||||
string PayloadEncoding = 6;
|
string PayloadEncoding = 6;
|
||||||
string PayloadType = 7;
|
string PayloadType = 7;
|
||||||
bytes Payload = 8;
|
bytes Payload = 8;
|
||||||
@@ -81,6 +81,13 @@ message WebcastGiftMessage {
|
|||||||
bool isFirstSent = 25;
|
bool isFirstSent = 25;
|
||||||
string orderId = 28;
|
string orderId = 28;
|
||||||
UserIdentity userIdentity = 32;
|
UserIdentity userIdentity = 32;
|
||||||
|
UserGiftReciever userGiftReciever = 23;
|
||||||
|
|
||||||
|
message UserGiftReciever
|
||||||
|
{
|
||||||
|
int64 userId = 1;
|
||||||
|
string deviceName = 10;
|
||||||
|
}
|
||||||
|
|
||||||
message GiftIMPriority {
|
message GiftIMPriority {
|
||||||
repeated int64 queueSizesList = 1;
|
repeated int64 queueSizesList = 1;
|
||||||
@@ -197,7 +204,7 @@ message WebcastChatMessage {
|
|||||||
int32 quickChatScene = 16;
|
int32 quickChatScene = 16;
|
||||||
int32 communityFlaggedStatus = 17;
|
int32 communityFlaggedStatus = 17;
|
||||||
UserIdentity UserIdentity = 18;
|
UserIdentity UserIdentity = 18;
|
||||||
map<int32,string> CommentQualityScores = 19;
|
map<int32, string> CommentQualityScores = 19;
|
||||||
|
|
||||||
// @EmoteWithIndex
|
// @EmoteWithIndex
|
||||||
// proto.webcast.im.ChatMessage
|
// proto.webcast.im.ChatMessage
|
||||||
@@ -277,7 +284,7 @@ message WebcastGoalUpdateMessage {
|
|||||||
int64 contributorId = 4;
|
int64 contributorId = 4;
|
||||||
Image contributorAvatar = 5;
|
Image contributorAvatar = 5;
|
||||||
string contributorDisplayId = 6;
|
string contributorDisplayId = 6;
|
||||||
// SubGoal contributeSubgoal = 7;
|
// SubGoal contributeSubgoal = 7;
|
||||||
int64 contributeCount = 9;
|
int64 contributeCount = 9;
|
||||||
int64 contributeScore = 10;
|
int64 contributeScore = 10;
|
||||||
int64 giftRepeatCount = 11;
|
int64 giftRepeatCount = 11;
|
||||||
@@ -348,7 +355,7 @@ message WebcastSocialMessage {
|
|||||||
message WebcastSubNotifyMessage {
|
message WebcastSubNotifyMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
User user = 2;
|
User user = 2;
|
||||||
// ExhibitionType exhibitionType = 3; // Enum
|
// ExhibitionType exhibitionType = 3; // Enum
|
||||||
int64 subMonth = 4;
|
int64 subMonth = 4;
|
||||||
SubscribeType subscribeType = 5; // Enum
|
SubscribeType subscribeType = 5; // Enum
|
||||||
OldSubscribeStatus oldSubscribeStatus = 6; // Enum
|
OldSubscribeStatus oldSubscribeStatus = 6; // Enum
|
||||||
@@ -442,7 +449,7 @@ message WebcastMemberMessage {
|
|||||||
//@WebcastPollMessage
|
//@WebcastPollMessage
|
||||||
message WebcastPollMessage {
|
message WebcastPollMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int32 messageType = 2;
|
MessageType messageType = 2;
|
||||||
int64 pollId = 3;
|
int64 pollId = 3;
|
||||||
PollStartContent startContent = 4;
|
PollStartContent startContent = 4;
|
||||||
PollEndContent endContent = 5;
|
PollEndContent endContent = 5;
|
||||||
@@ -507,6 +514,9 @@ message WebcastHourlyRankMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//<Battles>
|
||||||
|
|
||||||
//@WebcastLinkMicArmies
|
//@WebcastLinkMicArmies
|
||||||
message WebcastLinkMicArmies {
|
message WebcastLinkMicArmies {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -523,6 +533,45 @@ message WebcastLinkMicArmies {
|
|||||||
uint32 data4 = 12;
|
uint32 data4 = 12;
|
||||||
uint32 data5 = 13;
|
uint32 data5 = 13;
|
||||||
}
|
}
|
||||||
|
//@WebcastLinkMicBattlePunishFinish
|
||||||
|
message WebcastLinkMicBattlePunishFinish {
|
||||||
|
Common Header = 1;
|
||||||
|
uint64 Id1 = 2;
|
||||||
|
uint64 Timestamp = 3;
|
||||||
|
uint32 Data4 = 4;
|
||||||
|
uint64 Id2 = 5;
|
||||||
|
LinkMicBattlePunishFinishData Data6 = 6;
|
||||||
|
|
||||||
|
message LinkMicBattlePunishFinishData {
|
||||||
|
uint64 Id2 = 1; // Same as Id2 in outer object (loser?)
|
||||||
|
uint64 Timestamp = 2;
|
||||||
|
uint32 Data3 = 3;
|
||||||
|
uint64 Id1 = 4; // Same as Id1 in outer object (winner?)
|
||||||
|
uint32 Data5 = 5;
|
||||||
|
uint32 Data6 = 6;
|
||||||
|
uint32 Data8 = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@WebcastLinkmicBattleTaskMessage
|
||||||
|
message WebcastLinkmicBattleTaskMessage {
|
||||||
|
Common Header = 1;
|
||||||
|
uint32 Data2 = 2;
|
||||||
|
LinkmicBattleTaskData Data3 = 3;
|
||||||
|
LinkmicBattleTaskData2 Data5 = 5;
|
||||||
|
|
||||||
|
message LinkmicBattleTaskData {
|
||||||
|
BattleTaskData Data1 = 1;
|
||||||
|
}
|
||||||
|
message BattleTaskData {
|
||||||
|
uint32 Data1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkmicBattleTaskData2 {
|
||||||
|
uint32 Data1 = 1;
|
||||||
|
uint32 Data2 = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//@WebcastLinkMicBattle
|
//@WebcastLinkMicBattle
|
||||||
message WebcastLinkMicBattle {
|
message WebcastLinkMicBattle {
|
||||||
@@ -572,11 +621,10 @@ message WebcastLinkMicFanTicketMethod {
|
|||||||
Common common = 1;
|
Common common = 1;
|
||||||
FanTicketRoomNoticeContent FanTicketRoomNotice = 2;
|
FanTicketRoomNoticeContent FanTicketRoomNotice = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastLinkMicMethod
|
//@WebcastLinkMicMethod
|
||||||
message WebcastLinkMicMethod {
|
message WebcastLinkMicMethod {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int64 messageType = 2;
|
MessageType messageType = 2;
|
||||||
string accessKey = 3;
|
string accessKey = 3;
|
||||||
int64 anchorLinkmicId = 4;
|
int64 anchorLinkmicId = 4;
|
||||||
int64 userId = 5;
|
int64 userId = 5;
|
||||||
@@ -590,6 +638,8 @@ message WebcastLinkMicMethod {
|
|||||||
int64 inviteUid = 13;
|
int64 inviteUid = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//<Battles>
|
||||||
|
|
||||||
//@WebcastLiveIntroMessage
|
//@WebcastLiveIntroMessage
|
||||||
message WebcastLiveIntroMessage {
|
message WebcastLiveIntroMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -610,7 +660,7 @@ message WebcastUnauthorizedMemberMessage {
|
|||||||
string nickName = 4;
|
string nickName = 4;
|
||||||
Text enterText = 5;
|
Text enterText = 5;
|
||||||
}
|
}
|
||||||
S
|
|
||||||
//@WebcastMsgDetectMessage
|
//@WebcastMsgDetectMessage
|
||||||
message WebcastMsgDetectMessage {
|
message WebcastMsgDetectMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
@@ -632,7 +682,7 @@ message WebcastMsgDetectMessage {
|
|||||||
bool detectP2PMsg = 3;
|
bool detectP2PMsg = 3;
|
||||||
bool detectRoomMsg = 4;
|
bool detectRoomMsg = 4;
|
||||||
bool httpOptimize = 5;
|
bool httpOptimize = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastOecLiveShoppingMessage
|
//@WebcastOecLiveShoppingMessage
|
||||||
@@ -683,9 +733,9 @@ message WebcastSystemMessage {
|
|||||||
//@WebcastLinkMessage
|
//@WebcastLinkMessage
|
||||||
message WebcastLinkMessage {
|
message WebcastLinkMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int64 MessageType = 2;
|
MessageType MessageType = 2;
|
||||||
int64 LinkerId = 3;
|
int64 LinkerId = 3;
|
||||||
int64 Scene = 4;
|
Scene Scene = 4;
|
||||||
LinkerInviteContent InviteContent = 5;
|
LinkerInviteContent InviteContent = 5;
|
||||||
LinkerReplyContent ReplyContent = 6;
|
LinkerReplyContent ReplyContent = 6;
|
||||||
LinkerCreateContent CreateContent = 7;
|
LinkerCreateContent CreateContent = 7;
|
||||||
@@ -712,14 +762,34 @@ message WebcastLinkMessage {
|
|||||||
string TransferExtra = 202;
|
string TransferExtra = 202;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@WebcastLinkLayerMessage
|
|
||||||
|
// @WebcastLinkLayerMessage
|
||||||
message WebcastLinkLayerMessage {
|
message WebcastLinkLayerMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
LinkLayerMessageType messageType = 2;
|
MessageType messageType = 2; // Enum
|
||||||
int64 channelId = 3;
|
int64 channelId = 3;
|
||||||
|
Scene scene = 4; // Enum
|
||||||
|
CreateChannelContent createChannelContent = 100;
|
||||||
|
ListChangeContent listChangeContent = 102;
|
||||||
|
InviteContent inviteContent = 103;
|
||||||
|
ApplyContent applyContent = 104;
|
||||||
|
PermitApplyContent permitApplyContent = 105;
|
||||||
|
ReplyInviteContent replyInviteContent = 106;
|
||||||
|
KickOutContent kickOutContent = 107;
|
||||||
|
CancelApplyContent cancelApplyContent = 108;
|
||||||
|
CancelInviteContent cancelInviteContent = 109;
|
||||||
|
LeaveContent leaveContent = 110;
|
||||||
|
FinishChannelContent finishContent = 111;
|
||||||
|
JoinDirectContent joinDirectContent = 112;
|
||||||
|
JoinGroupContent joinGroupContent = 113;
|
||||||
|
PermitJoinGroupContent permitGroupContent = 114;
|
||||||
|
CancelJoinGroupContent cancelGroupContent = 115;
|
||||||
|
LeaveJoinGroupContent leaveGroupContent = 116;
|
||||||
|
P2PGroupChangeContent p2pGroupChangeContent = 117;
|
||||||
|
BusinessContent businessContent = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @RoomVerifyMessage
|
||||||
message RoomVerifyMessage {
|
message RoomVerifyMessage {
|
||||||
Common common = 1;
|
Common common = 1;
|
||||||
int32 action = 2;
|
int32 action = 2;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -87,4 +87,5 @@ public class TikTokLive
|
|||||||
{
|
{
|
||||||
return new TikTokDataChecker().isHostNameValidAsync(hostName);
|
return new TikTokDataChecker().isHostNameValidAsync(hostName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
||||||
@@ -134,13 +136,15 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
|
|
||||||
apiService.updateSessionId();
|
apiService.updateSessionId();
|
||||||
|
|
||||||
|
TikTokUserInfo info = apiService.fetchUserInfoFromTikTokApi(liveRoomInfo.getHostName());
|
||||||
|
liveRoomInfo.setStartTime(info.getStartTime());
|
||||||
if (clientSettings.getRoomId() != null) {
|
if (clientSettings.getRoomId() != null) {
|
||||||
liveRoomInfo.setRoomId(clientSettings.getRoomId());
|
liveRoomInfo.setRoomId(clientSettings.getRoomId());
|
||||||
logger.info("Using roomID from settings: " + clientSettings.getRoomId());
|
logger.info("Using roomID from settings: " + clientSettings.getRoomId());
|
||||||
} else {
|
} else {
|
||||||
var roomId = apiService.fetchRoomId(liveRoomInfo.getHostName());
|
liveRoomInfo.setRoomId(info.getRoomId());
|
||||||
liveRoomInfo.setRoomId(roomId);
|
|
||||||
}
|
}
|
||||||
|
apiService.updateRoomId(liveRoomInfo.getRoomId());
|
||||||
|
|
||||||
|
|
||||||
var liveRoomMeta = apiService.fetchRoomInfo();
|
var liveRoomMeta = apiService.fetchRoomInfo();
|
||||||
@@ -189,4 +193,8 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
liveRoomInfo.setConnectionState(connectionState);
|
liveRoomInfo.setConnectionState(connectionState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void publishEvent(TikTokEvent event)
|
||||||
|
{
|
||||||
|
tikTokEventHandler.publish(this, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomPinEvent;
|
||||||
@@ -41,23 +42,25 @@ import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
|||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
||||||
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokCommonEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokRoomInfoEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokSocialMediaEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokCommonEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokRoomInfoEventHandler;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokSocialMediaEventHandler;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
import io.github.jwdeveloper.tiktok.messages.webcast.*;
|
||||||
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
||||||
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
||||||
@@ -88,12 +91,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) {
|
public LiveClientBuilder onMapping(Consumer<TikTokMapper> onCustomMappings) {
|
||||||
this.onCustomMappings = onCustomMappings;
|
this.onCustomMappings = onCustomMappings;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> onConfigure) {
|
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> onConfigure) {
|
||||||
onConfigure.accept(clientSettings);
|
onConfigure.accept(clientSettings);
|
||||||
return this;
|
return this;
|
||||||
@@ -110,12 +113,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
clientSettings.setTimeout(Duration.ofSeconds(Constants.DEFAULT_TIMEOUT));
|
clientSettings.setTimeout(Duration.ofSeconds(Constants.DEFAULT_TIMEOUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientSettings.getClientLanguage() == null || clientSettings.getClientLanguage().equals("")) {
|
if (clientSettings.getClientLanguage() == null || clientSettings.getClientLanguage().isEmpty()) {
|
||||||
clientSettings.setClientLanguage(Constants.DefaultClientSettings().getClientLanguage());
|
clientSettings.setClientLanguage(Constants.DefaultClientSettings().getClientLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (clientSettings.getHostName() == null || clientSettings.getHostName().equals("")) {
|
if (clientSettings.getHostName() == null || clientSettings.getHostName().isEmpty()) {
|
||||||
throw new TikTokLiveException("HostName can not be null");
|
throw new TikTokLiveException("HostName can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +162,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||||
var cookieJar = new TikTokCookieJar();
|
var cookieJar = new TikTokCookieJar();
|
||||||
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
|
var requestFactory = new TikTokHttpRequestFactory(cookieJar, tikTokEventHandler);
|
||||||
var apiClient = new TikTokHttpClient(cookieJar, requestFactory);
|
var apiClient = new TikTokHttpClient(cookieJar, requestFactory);
|
||||||
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
|
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
|
||||||
var giftManager = new TikTokGiftManager(logger);
|
var giftManager = new TikTokGiftManager(logger);
|
||||||
@@ -167,7 +170,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
var messageHandler = new TikTokMessageHandler(tikTokEventHandler, eventsMapper);
|
var messageHandler = new TikTokMessageHandler(tikTokEventHandler, eventsMapper);
|
||||||
|
|
||||||
|
|
||||||
var webSocketClient = new TikTokWebSocketClient(logger,
|
var webSocketClient = new TikTokWebSocketClient(
|
||||||
cookieJar,
|
cookieJar,
|
||||||
clientSettings,
|
clientSettings,
|
||||||
messageHandler,
|
messageHandler,
|
||||||
@@ -185,56 +188,85 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
|
|
||||||
public TikTokLiveMapper createMapper(GiftManager giftManager, TikTokRoomInfo roomInfo) {
|
public TikTokLiveMapper createMapper(GiftManager giftManager, TikTokRoomInfo roomInfo) {
|
||||||
var eventMapper = new TikTokGenericEventMapper();
|
var eventMapper = new TikTokGenericEventMapper();
|
||||||
var mapper = new TikTokLiveMapper(eventMapper);
|
var mapper = new TikTokLiveMapper(new TikTokLiveMapperHelper(eventMapper));
|
||||||
|
|
||||||
//ConnectionEvents events
|
//ConnectionEvents events
|
||||||
var commonHandler = new TikTokCommonEventHandler();
|
var commonHandler = new TikTokCommonEventHandler();
|
||||||
var giftHandler = new TikTokGiftEventHandler(giftManager);
|
var giftHandler = new TikTokGiftEventHandler(giftManager, roomInfo);
|
||||||
var roomInfoHandler = new TikTokRoomInfoEventHandler(roomInfo);
|
var roomInfoHandler = new TikTokRoomInfoEventHandler(roomInfo);
|
||||||
var socialHandler = new TikTokSocialMediaEventHandler(roomInfo);
|
var socialHandler = new TikTokSocialMediaEventHandler(roomInfo);
|
||||||
|
|
||||||
mapper.bytesToEvent(WebcastControlMessage.class, commonHandler::handleWebcastControlMessage);
|
|
||||||
|
mapper.forMessage(WebcastControlMessage.class, commonHandler::handleWebcastControlMessage);
|
||||||
|
|
||||||
//Room status events
|
//Room status events
|
||||||
mapper.bytesToEvent(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
|
mapper.forMessage(WebcastLiveIntroMessage.class, roomInfoHandler::handleIntro);
|
||||||
mapper.bytesToEvent(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
|
mapper.forMessage(WebcastRoomUserSeqMessage.class, roomInfoHandler::handleUserRanking);
|
||||||
|
mapper.forMessage(WebcastCaptionMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastCaptionMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokCaptionEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
mapper.webcastObjectToConstructor(WebcastCaptionMessage.class, TikTokCaptionEvent.class);
|
|
||||||
|
|
||||||
//User Interactions events
|
//User Interactions events
|
||||||
mapper.webcastObjectToConstructor(WebcastChatMessage.class, TikTokCommentEvent.class);
|
mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
mapper.bytesToEvents(WebcastLikeMessage.class, roomInfoHandler::handleLike);
|
{
|
||||||
mapper.bytesToEvents(WebcastGiftMessage.class, giftHandler::handleGift);
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
mapper.bytesToEvent(WebcastSocialMessage.class, socialHandler::handle);
|
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
|
||||||
mapper.bytesToEvents(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
|
});
|
||||||
|
mapper.forMessage(WebcastSubNotifyMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastSubNotifyMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokSubscribeEvent(messageObject));
|
||||||
|
});
|
||||||
|
mapper.forMessage(WebcastEmoteChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastEmoteChatMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokEmoteEvent(messageObject));
|
||||||
|
});
|
||||||
|
mapper.forMessage(WebcastQuestionNewMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastQuestionNewMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokQuestionEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
|
mapper.forMessage(WebcastLikeMessage.class, roomInfoHandler::handleLike);
|
||||||
|
mapper.forMessage(WebcastGiftMessage.class, giftHandler::handleGifts);
|
||||||
|
mapper.forMessage(WebcastSocialMessage.class, socialHandler::handle);
|
||||||
|
mapper.forMessage(WebcastMemberMessage.class, roomInfoHandler::handleMemberMessage);
|
||||||
|
|
||||||
|
|
||||||
//Host Interaction events
|
//Host Interaction events
|
||||||
mapper.bytesToEvent(WebcastPollMessage.class, commonHandler::handlePollEvent);
|
mapper.forMessage(WebcastPollMessage.class, commonHandler::handlePollEvent);
|
||||||
mapper.bytesToEvent(WebcastRoomPinMessage.class, commonHandler::handlePinMessage);
|
mapper.forMessage(WebcastRoomPinMessage.class, commonHandler::handlePinMessage);
|
||||||
mapper.webcastObjectToConstructor(WebcastGoalUpdateMessage.class, TikTokGoalUpdateEvent.class);
|
mapper.forMessage(WebcastChatMessage.class, (inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
|
return MappingResult.of(messageObject, new TikTokCommentEvent(messageObject));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//LinkMic events
|
//LinkMic events
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicBattle.class, TikTokLinkMicBattleEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicArmies.class, TikTokLinkMicArmiesEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicMethod.class, TikTokLinkMicMethodEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastLinkMicFanTicketMethod.class, TikTokLinkMicFanTicketEvent.class);
|
||||||
|
|
||||||
//Rank events
|
//Rank events
|
||||||
mapper.webcastObjectToConstructor(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastRankTextMessage.class, TikTokRankTextEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastRankUpdateMessage.class, TikTokRankUpdateEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastHourlyRankMessage.class, TikTokRankUpdateEvent.class);
|
||||||
|
|
||||||
//Others events
|
//Others events
|
||||||
mapper.webcastObjectToConstructor(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastInRoomBannerMessage.class, TikTokInRoomBannerEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastMsgDetectMessage.class, TikTokDetectEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastBarrageMessage.class, TikTokBarrageEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastUnauthorizedMemberMessage.class, TikTokUnauthorizedMemberEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastOecLiveShoppingMessage.class, TikTokShopEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
// mapper.webcastObjectToConstructor(WebcastImDeleteMessage.class, TikTokIMDeleteEvent.class);
|
||||||
mapper.webcastObjectToConstructor(WebcastQuestionNewMessage.class, TikTokQuestionEvent.class);
|
// mapper.bytesToEvents(WebcastEnvelopeMessage.class, commonHandler::handleEnvelop);
|
||||||
mapper.bytesToEvents(WebcastEnvelopeMessage.class, commonHandler::handleEnvelop);
|
|
||||||
mapper.webcastObjectToConstructor(WebcastSubNotifyMessage.class, TikTokSubscribeEvent.class);
|
|
||||||
mapper.webcastObjectToConstructor(WebcastEmoteChatMessage.class, TikTokEmoteEvent.class);
|
|
||||||
|
|
||||||
onCustomMappings.accept(mapper);
|
onCustomMappings.accept(mapper);
|
||||||
return mapper;
|
return mapper;
|
||||||
@@ -315,8 +347,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <E extends TikTokEvent> LiveClientBuilder onCustomEvent(Class<E> eventClazz, EventConsumer<E> event) {
|
public <E extends TikTokEvent> LiveClientBuilder onEvent(Class<E> eventClass, EventConsumer<E> event) {
|
||||||
tikTokEventHandler.subscribe(eventClazz, event);
|
tikTokEventHandler.subscribe(eventClass, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +448,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LiveClientBuilder onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action) {
|
||||||
|
tikTokEventHandler.subscribe(TikTokHttpResponseEvent.class, action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
|
public TikTokLiveClientBuilder onGoalUpdate(EventConsumer<TikTokGoalUpdateEvent> event) {
|
||||||
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
@@ -515,10 +553,3 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.models.ConnectionState;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
|
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
|
||||||
|
import io.github.jwdeveloper.tiktok.models.ConnectionState;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -42,6 +41,8 @@ public class TikTokRoomInfo implements LiveRoomInfo {
|
|||||||
|
|
||||||
private int totalViewersCount;
|
private int totalViewersCount;
|
||||||
|
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
private boolean ageRestricted;
|
private boolean ageRestricted;
|
||||||
|
|
||||||
private User host;
|
private User host;
|
||||||
@@ -62,12 +63,11 @@ public class TikTokRoomInfo implements LiveRoomInfo {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getHostUser() {
|
public User getHostUser() {
|
||||||
return null;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRanking(List<RankingUser> rankingUsers) {
|
public void updateRanking(List<RankingUser> rankingUsers) {
|
||||||
usersRanking.clear();
|
usersRanking.clear();
|
||||||
usersRanking.addAll(rankingUsers);
|
usersRanking.addAll(rankingUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,14 +22,12 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.gifts;
|
package io.github.jwdeveloper.tiktok.gifts;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -89,23 +87,17 @@ public class TikTokGiftManager implements GiftManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Gift findById(int giftId) {
|
public Gift findById(int giftId) {
|
||||||
if (!indexById.containsKey(giftId)) {
|
Gift gift = indexById.get(giftId);
|
||||||
return Gift.UNDEFINED;
|
return gift == null ? Gift.UNDEFINED : gift;
|
||||||
}
|
|
||||||
return indexById.get(giftId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gift findByName(String giftName) {
|
public Gift findByName(String giftName) {
|
||||||
if (!indexByName.containsKey(giftName)) {
|
Gift gift = indexByName.get(giftName);
|
||||||
return Gift.UNDEFINED;
|
return gift == null ? Gift.UNDEFINED : gift;
|
||||||
}
|
|
||||||
return indexByName.get(giftName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Gift> getGifts()
|
public List<Gift> getGifts() {
|
||||||
{
|
|
||||||
return indexById.values().stream().toList();
|
return indexById.values().stream().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,58 +22,30 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.http;
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class HttpUtils
|
public class HttpUtils
|
||||||
{
|
{
|
||||||
public static String parseParameters(String url, Map<String,Object> parameters)
|
public static String parseParameters(String url, Map<String,Object> parameters)
|
||||||
{
|
{
|
||||||
var parameterString = "";
|
if (parameters.isEmpty())
|
||||||
if (!parameters.isEmpty()) {
|
return url;
|
||||||
var builder = new StringBuilder();
|
|
||||||
builder.append("?");
|
|
||||||
var first = false;
|
|
||||||
for (var param : parameters.entrySet()) {
|
|
||||||
|
|
||||||
if (first) {
|
return url+ "?" + parameters.entrySet().stream().map(entry -> entry.getKey()+"="+entry.getValue()).collect(Collectors.joining("&"));
|
||||||
builder.append("&");
|
|
||||||
}
|
|
||||||
builder.append(param.getKey()).append("=").append(param.getValue());
|
|
||||||
first = true;
|
|
||||||
}
|
|
||||||
parameterString = builder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return url+parameterString;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static String parseParametersEncode(String url, Map<String,Object> parameters)
|
public static String parseParametersEncode(String url, Map<String,Object> parameters)
|
||||||
{
|
{
|
||||||
|
if (parameters.isEmpty())
|
||||||
|
return url;
|
||||||
|
|
||||||
var parameterString = "";
|
return url+ "?" + parameters.entrySet().stream().map(entry -> {
|
||||||
if (!parameters.isEmpty()) {
|
String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8);
|
||||||
var builder = new StringBuilder();
|
String encodedValue = URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8);
|
||||||
builder.append("?");
|
return encodedKey+"="+encodedValue;
|
||||||
var first = false;
|
}).collect(Collectors.joining("&"));
|
||||||
for (var param : parameters.entrySet()) {
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
builder.append("&");
|
|
||||||
}
|
|
||||||
|
|
||||||
final String encodedKey = URLEncoder.encode(param.getKey(), StandardCharsets.UTF_8);
|
|
||||||
final String encodedValue = URLEncoder.encode(param.getValue().toString(), StandardCharsets.UTF_8);
|
|
||||||
builder.append(encodedKey).append("=").append(encodedValue);
|
|
||||||
first = true;
|
|
||||||
}
|
|
||||||
parameterString = builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return url+parameterString;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,12 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.http;
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.*;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.LiveRoomMetaMapper;
|
import io.github.jwdeveloper.tiktok.mappers.LiveRoomMetaMapper;
|
||||||
@@ -35,7 +32,6 @@ import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class TikTokApiService {
|
public class TikTokApiService {
|
||||||
private final TikTokHttpClient tiktokHttpClient;
|
private final TikTokHttpClient tiktokHttpClient;
|
||||||
@@ -48,7 +44,6 @@ public class TikTokApiService {
|
|||||||
this.clientSettings = clientSettings;
|
this.clientSettings = clientSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateSessionId() {
|
public void updateSessionId() {
|
||||||
if (clientSettings.getSessionId() == null) {
|
if (clientSettings.getSessionId() == null) {
|
||||||
return;
|
return;
|
||||||
@@ -59,43 +54,45 @@ public class TikTokApiService {
|
|||||||
tiktokHttpClient.setSessionId(clientSettings.getSessionId());
|
tiktokHttpClient.setSessionId(clientSettings.getSessionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String fetchRoomId(String userName) {
|
public void updateRoomId(String roomId)
|
||||||
var userInfo = fetchUserInfoFromTikTokApi(userName);
|
{
|
||||||
clientSettings.getClientParameters().put("room_id", userInfo.getRoomId());
|
clientSettings.getClientParameters().put("room_id", roomId);
|
||||||
logger.info("RoomID -> " + userInfo.getRoomId());
|
|
||||||
return userInfo.getRoomId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokUserInfo fetchUserInfoFromTikTokApi(String userName) {
|
public TikTokUserInfo fetchUserInfoFromTikTokApi(String userName) {
|
||||||
|
|
||||||
var params = new HashMap<>(clientSettings.getClientParameters());
|
var params = new HashMap<>(clientSettings.getClientParameters());
|
||||||
params.put("uniqueId", userName);
|
params.put("uniqueId", userName);
|
||||||
params.put("sourceType", 54);
|
params.put("sourceType", 54);
|
||||||
JsonObject roomData = null;
|
JsonObject roomData;
|
||||||
try {
|
try {
|
||||||
roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
|
roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
|
||||||
throw new TikTokLiveRequestException("Failed to fetch pre connection room information, it happens when TikTok temporary blocks you. Try to connect again in few minutes");
|
throw new TikTokLiveRequestException("Failed to fetch pre connection room information, it happens when TikTok temporary blocks you. Try to connect again in few minutes");
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = roomData.get("message").getAsString();
|
var message = roomData.get("message").getAsString();
|
||||||
|
|
||||||
if (message.equals("params_error")) {
|
if (message.equals("params_error")) {
|
||||||
throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact with developer");
|
throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact the developer");
|
||||||
}
|
}
|
||||||
if (message.equals("user_not_found")) {
|
if (message.equals("user_not_found")) {
|
||||||
return new TikTokUserInfo(TikTokUserInfo.UserStatus.NotFound, "");
|
return new TikTokUserInfo(TikTokUserInfo.UserStatus.NotFound, "", -1);
|
||||||
}
|
}
|
||||||
//live -> status 2
|
//live -> status 2
|
||||||
//live paused -> 3
|
//live paused -> 3
|
||||||
//not live -> status 4
|
//not live -> status 4
|
||||||
var data = roomData.getAsJsonObject("data");
|
var element = roomData.get("data");
|
||||||
|
if (element.isJsonNull()) {
|
||||||
|
return new TikTokUserInfo(TikTokUserInfo.UserStatus.NotFound, "", -1);
|
||||||
|
}
|
||||||
|
var data = element.getAsJsonObject();
|
||||||
var user = data.getAsJsonObject("user");
|
var user = data.getAsJsonObject("user");
|
||||||
var roomId = user.get("roomId").getAsString();
|
var roomId = user.get("roomId").getAsString();
|
||||||
var status = user.get("status").getAsInt();
|
var status = user.get("status").getAsInt();
|
||||||
|
|
||||||
|
var liveRoom = data.getAsJsonObject("liveRoom");
|
||||||
|
long startTime = liveRoom.get("startTime").getAsLong();
|
||||||
|
|
||||||
var statusEnum = switch (status) {
|
var statusEnum = switch (status) {
|
||||||
case 2 -> TikTokUserInfo.UserStatus.Live;
|
case 2 -> TikTokUserInfo.UserStatus.Live;
|
||||||
case 3 -> TikTokUserInfo.UserStatus.LivePaused;
|
case 3 -> TikTokUserInfo.UserStatus.LivePaused;
|
||||||
@@ -103,7 +100,7 @@ public class TikTokApiService {
|
|||||||
default -> TikTokUserInfo.UserStatus.NotFound;
|
default -> TikTokUserInfo.UserStatus.NotFound;
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TikTokUserInfo(statusEnum, roomId);
|
return new TikTokUserInfo(statusEnum, roomId, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.http;
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class TikTokCookieJar {
|
public class TikTokCookieJar {
|
||||||
private final Map<String, String> cookies;
|
private final Map<String, String> cookies;
|
||||||
@@ -40,13 +39,10 @@ public class TikTokCookieJar {
|
|||||||
cookies.put(key, value);
|
cookies.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String parseCookies()
|
public String parseCookies() {
|
||||||
{
|
return cookies.entrySet()
|
||||||
var sb = new StringBuilder();
|
.stream()
|
||||||
for(var entry : cookies.entrySet())
|
.map(entry -> entry.getKey()+"="+entry.getValue()+";")
|
||||||
{
|
.collect(Collectors.joining());
|
||||||
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(";");
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,7 @@ import io.github.jwdeveloper.tiktok.ClientSettings;
|
|||||||
import io.github.jwdeveloper.tiktok.Constants;
|
import io.github.jwdeveloper.tiktok.Constants;
|
||||||
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -54,7 +55,7 @@ public class TikTokDataChecker {
|
|||||||
|
|
||||||
public TikTokApiService getApiService() {
|
public TikTokApiService getApiService() {
|
||||||
var jar = new TikTokCookieJar();
|
var jar = new TikTokCookieJar();
|
||||||
var factory = new TikTokHttpRequestFactory(jar);
|
var factory = new TikTokHttpRequestFactory(jar,new TikTokEventObserver());
|
||||||
var client = new TikTokHttpClient(jar, factory);
|
var client = new TikTokHttpClient(jar, factory);
|
||||||
var settings = new ClientSettings();
|
var settings = new ClientSettings();
|
||||||
settings.setClientParameters(Constants.DefaultClientParams());
|
settings.setClientParameters(Constants.DefaultClientParams());
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ public class TikTokHttpClient {
|
|||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSessionId(String sessionId)
|
public void setSessionId(String sessionId) {
|
||||||
{
|
|
||||||
tikTokCookieJar.set("sessionid", sessionId);
|
tikTokCookieJar.set("sessionid", sessionId);
|
||||||
tikTokCookieJar.set("sessionid_ss", sessionId);
|
tikTokCookieJar.set("sessionid_ss", sessionId);
|
||||||
tikTokCookieJar.set("sid_tt", sessionId);
|
tikTokCookieJar.set("sid_tt", sessionId);
|
||||||
@@ -54,14 +53,12 @@ public class TikTokHttpClient {
|
|||||||
|
|
||||||
|
|
||||||
public String getLivestreamPage(String userName) {
|
public String getLivestreamPage(String userName) {
|
||||||
|
|
||||||
var url = Constants.TIKTOK_URL_WEB + "@" + userName + "/live/";
|
var url = Constants.TIKTOK_URL_WEB + "@" + userName + "/live/";
|
||||||
var get = getRequest(url, null);
|
var get = getRequest(url, null);
|
||||||
return get;
|
return get;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonObject getJsonFromTikTokApi(String path, Map<String,Object> params)
|
public JsonObject getJsonFromTikTokApi(String path, Map<String,Object> params) {
|
||||||
{
|
|
||||||
var get = getRequest(Constants.TIKTOK_URL_WEB + path, params);
|
var get = getRequest(Constants.TIKTOK_URL_WEB + path, params);
|
||||||
var json = JsonParser.parseString(get);
|
var json = JsonParser.parseString(get);
|
||||||
var jsonObject = json.getAsJsonObject();
|
var jsonObject = json.getAsJsonObject();
|
||||||
@@ -91,7 +88,6 @@ public class TikTokHttpClient {
|
|||||||
if (parameters == null) {
|
if (parameters == null) {
|
||||||
parameters = new HashMap<>();
|
parameters = new HashMap<>();
|
||||||
}
|
}
|
||||||
System.out.println("RomMID: "+parameters.get("room_id"));
|
|
||||||
var request = requestFactory.setQueries(parameters);
|
var request = requestFactory.setQueries(parameters);
|
||||||
return request.post(url);
|
return request.post(url);
|
||||||
}
|
}
|
||||||
@@ -118,7 +114,6 @@ public class TikTokHttpClient {
|
|||||||
{
|
{
|
||||||
var split = cookie.split(";")[0].split("=");
|
var split = cookie.split(";")[0].split("=");
|
||||||
|
|
||||||
|
|
||||||
var key = split[0];
|
var key = split[0];
|
||||||
var value = split[1];
|
var value = split[1];
|
||||||
tikTokCookieJar.set(key, value);
|
tikTokCookieJar.set(key, value);
|
||||||
@@ -134,7 +129,6 @@ public class TikTokHttpClient {
|
|||||||
|
|
||||||
|
|
||||||
private String getSignedUrl(String url, Map<String, Object> parameters) {
|
private String getSignedUrl(String url, Map<String, Object> parameters) {
|
||||||
|
|
||||||
var fullUrl = HttpUtils.parseParameters(url,parameters);
|
var fullUrl = HttpUtils.parseParameters(url,parameters);
|
||||||
var signParams = new TreeMap<String,Object>();
|
var signParams = new TreeMap<String,Object>();
|
||||||
signParams.put("client", "ttlive-java");
|
signParams.put("client", "ttlive-java");
|
||||||
@@ -144,7 +138,6 @@ public class TikTokHttpClient {
|
|||||||
var request = requestFactory.setQueries(signParams);
|
var request = requestFactory.setQueries(signParams);
|
||||||
var content = request.get(Constants.TIKTOK_SIGN_API);
|
var content = request.get(Constants.TIKTOK_SIGN_API);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var json = JsonParser.parseString(content);
|
var json = JsonParser.parseString(content);
|
||||||
var jsonObject = json.getAsJsonObject();
|
var jsonObject = json.getAsJsonObject();
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ package io.github.jwdeveloper.tiktok.http;
|
|||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.Constants;
|
import io.github.jwdeveloper.tiktok.Constants;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.http.HttpData;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
@@ -39,32 +42,34 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
||||||
private final CookieManager cookieManager;
|
private final CookieManager cookieManager;
|
||||||
private final Map<String, String> defaultHeaders;
|
private final Map<String, String> defaultHeaders;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final HttpClient client;
|
private final HttpClient client;
|
||||||
|
private final TikTokEventObserver eventHandler;
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) {
|
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar, TikTokEventObserver eventHandler) {
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.cookieManager = new CookieManager();
|
this.cookieManager = new CookieManager();
|
||||||
|
this.eventHandler = eventHandler;
|
||||||
defaultHeaders = Constants.DefaultRequestHeaders();
|
defaultHeaders = Constants.DefaultRequestHeaders();
|
||||||
client = HttpClient.newBuilder()
|
client = HttpClient.newBuilder()
|
||||||
.cookieHandler(cookieManager)
|
.cookieHandler(cookieManager)
|
||||||
.connectTimeout(Duration.ofSeconds(2))
|
.connectTimeout(Duration.ofSeconds(2))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String get(String url) {
|
public String get(String url) {
|
||||||
var uri = URI.create(url);
|
var uri = URI.create(url);
|
||||||
var requestBuilder = HttpRequest.newBuilder().GET();
|
var requestBuilder = HttpRequest.newBuilder().GET();
|
||||||
|
|
||||||
for (var header : defaultHeaders.entrySet())
|
for (var header : defaultHeaders.entrySet()) {
|
||||||
{
|
if (header.getKey().equals("Connection") || header.getKey().equals("Accept-Encoding")) {
|
||||||
if(header.getKey().equals("Connection") || header.getKey().equals("Accept-Encoding"))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
requestBuilder.setHeader(header.getKey(), header.getValue());
|
requestBuilder.setHeader(header.getKey(), header.getValue());
|
||||||
@@ -73,9 +78,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
var baseUri = uri.toString();
|
var baseUri = uri.toString();
|
||||||
var requestUri = URI.create(baseUri + "?" + query);
|
var requestUri = URI.create(baseUri + "?" + query);
|
||||||
requestBuilder.uri(requestUri);
|
requestBuilder.uri(requestUri);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
requestBuilder.uri(uri);
|
requestBuilder.uri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,15 +91,13 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
public String post(String url) {
|
public String post(String url) {
|
||||||
var uri = URI.create(url);
|
var uri = URI.create(url);
|
||||||
var request = HttpRequest.newBuilder().POST(HttpRequest.BodyPublishers.ofString(""));
|
var request = HttpRequest.newBuilder().POST(HttpRequest.BodyPublishers.ofString(""));
|
||||||
for (var header : defaultHeaders.entrySet())
|
for (var header : defaultHeaders.entrySet()) {
|
||||||
{
|
if (header.getKey().equals("Connection")) {
|
||||||
if(header.getKey().equals("Connection"))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
request.setHeader(header.getKey(), header.getValue());
|
request.setHeader(header.getKey(), header.getValue());
|
||||||
}
|
}
|
||||||
request.setHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
|
request.setHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||||
request.setHeader("Cookie", tikTokCookieJar.parseCookies());
|
request.setHeader("Cookie", tikTokCookieJar.parseCookies());
|
||||||
|
|
||||||
|
|
||||||
@@ -104,11 +105,8 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
var baseUri = uri.toString();
|
var baseUri = uri.toString();
|
||||||
var requestUri = URI.create(baseUri + "?" + query);
|
var requestUri = URI.create(baseUri + "?" + query);
|
||||||
request.uri(requestUri);
|
request.uri(requestUri);
|
||||||
System.out.println(requestUri.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return getContent(request.build());
|
return getContent(request.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,24 +123,25 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
public TikTokHttpRequest setQueries(Map<String, Object> queries) {
|
public TikTokHttpRequest setQueries(Map<String, Object> queries) {
|
||||||
if (queries == null)
|
if (queries == null)
|
||||||
return this;
|
return this;
|
||||||
var testMap = new TreeMap<String,Object>(queries);
|
var testMap = new TreeMap<>(queries);
|
||||||
query = String.join("&", testMap.entrySet().stream().map(x ->
|
query = testMap.entrySet().stream().map(x -> {
|
||||||
{
|
|
||||||
var key = x.getKey();
|
var key = x.getKey();
|
||||||
var value = "";
|
|
||||||
try {
|
try {
|
||||||
value = URLEncoder.encode(x.getValue().toString(), StandardCharsets.UTF_8);
|
return key+"="+URLEncoder.encode(x.getValue().toString(), StandardCharsets.UTF_8);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
return key + "=";
|
||||||
}
|
}
|
||||||
return key + "=" + value;
|
}).collect(Collectors.joining("&"));
|
||||||
}).toList());
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getContent(HttpRequest request) throws Exception {
|
private String getContent(HttpRequest request) throws Exception {
|
||||||
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
|
var event = new TikTokHttpResponseEvent(response.uri().toString(), HttpData.map(response), HttpData.map(request));
|
||||||
|
eventHandler.publish(null, event);
|
||||||
if (response.statusCode() == 404) {
|
if (response.statusCode() == 404) {
|
||||||
throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND");
|
throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND");
|
||||||
}
|
}
|
||||||
@@ -155,8 +154,6 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
for (var cookie : cookies) {
|
for (var cookie : cookies) {
|
||||||
var split = cookie.split(";")[0].split("=");
|
var split = cookie.split(";")[0].split("=");
|
||||||
var uri = request.uri();
|
var uri = request.uri();
|
||||||
|
|
||||||
|
|
||||||
var key = split[0];
|
var key = split[0];
|
||||||
var value = split[1];
|
var value = split[1];
|
||||||
tikTokCookieJar.set(key, value);
|
tikTokCookieJar.set(key, value);
|
||||||
@@ -164,10 +161,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest {
|
|||||||
var map = new HashMap<String, List<String>>();
|
var map = new HashMap<String, List<String>>();
|
||||||
map.put(key, List.of(value));
|
map.put(key, List.of(value));
|
||||||
cookieManager.put(uri, map);
|
cookieManager.put(uri, map);
|
||||||
|
|
||||||
}
|
}
|
||||||
return response.body();
|
return response.body();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -23,11 +23,10 @@
|
|||||||
package io.github.jwdeveloper.tiktok.listener;
|
package io.github.jwdeveloper.tiktok.listener;
|
||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokEventListenerMethodException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
||||||
|
|
||||||
@@ -37,10 +36,10 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TikTokListenersManager implements ListenersManager {
|
public class TikTokListenersManager implements ListenersManager {
|
||||||
private final TikTokEventObserver eventObserver;
|
private final io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver eventObserver;
|
||||||
private final List<ListenerBindingModel> bindingModels;
|
private final List<ListenerBindingModel> bindingModels;
|
||||||
|
|
||||||
public TikTokListenersManager(List<TikTokEventListener> listeners, TikTokEventObserver tikTokEventHandler) {
|
public TikTokListenersManager(List<TikTokEventListener> listeners, io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver tikTokEventHandler) {
|
||||||
this.eventObserver = tikTokEventHandler;
|
this.eventObserver = tikTokEventHandler;
|
||||||
this.bindingModels = new ArrayList<>(listeners.size());
|
this.bindingModels = new ArrayList<>(listeners.size());
|
||||||
for (var listener : listeners) {
|
for (var listener : listeners) {
|
||||||
@@ -93,7 +92,7 @@ public class TikTokListenersManager implements ListenersManager {
|
|||||||
var clazz = listener.getClass();
|
var clazz = listener.getClass();
|
||||||
var methods = Arrays.stream(clazz.getDeclaredMethods()).filter(m ->
|
var methods = Arrays.stream(clazz.getDeclaredMethods()).filter(m ->
|
||||||
m.getParameterCount() == 2 &&
|
m.getParameterCount() == 2 &&
|
||||||
m.isAnnotationPresent(TikTokEventHandler.class)).toList();
|
m.isAnnotationPresent(TikTokEventObserver.class)).toList();
|
||||||
var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>();
|
var eventsMap = new HashMap<Class<?>, List<EventConsumer<?>>>();
|
||||||
for (var method : methods) {
|
for (var method : methods) {
|
||||||
var eventClazz = method.getParameterTypes()[1];
|
var eventClazz = method.getParameterTypes()[1];
|
||||||
@@ -116,7 +115,7 @@ public class TikTokListenersManager implements ListenersManager {
|
|||||||
throw new TikTokEventListenerMethodException(e);
|
throw new TikTokEventListenerMethodException(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
eventsMap.computeIfAbsent(eventClazz, (a) -> new ArrayList<EventConsumer<?>>()).add(eventMethodRef);
|
eventsMap.computeIfAbsent(eventClazz, (a) -> new ArrayList<>()).add(eventMethodRef);
|
||||||
}
|
}
|
||||||
return new ListenerBindingModel(listener, eventsMap);
|
return new ListenerBindingModel(listener, eventsMap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
|
|||||||
@@ -1,8 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
package io.github.jwdeveloper.tiktok.mappers;
|
||||||
|
|
||||||
import com.google.protobuf.GeneratedMessageV3;
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -10,79 +34,83 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class TikTokLiveMapper implements TikTokMapper {
|
public class TikTokLiveMapper implements TikTokMapper {
|
||||||
private final Map<String, Function<byte[], List<TikTokEvent>>> mappers;
|
|
||||||
private final TikTokGenericEventMapper genericMapper;
|
|
||||||
|
|
||||||
public TikTokLiveMapper(TikTokGenericEventMapper genericMapper) {
|
private final Map<String, TikTokLiveMapperModel> mappers;
|
||||||
|
private final TikTokMapperHelper mapperUtils;
|
||||||
|
private final TikTokLiveMapperModel globalMapperModel;
|
||||||
|
|
||||||
|
public TikTokLiveMapper(TikTokMapperHelper mapperUtils) {
|
||||||
this.mappers = new HashMap<>();
|
this.mappers = new HashMap<>();
|
||||||
this.genericMapper = genericMapper;
|
this.mapperUtils = mapperUtils;
|
||||||
|
this.globalMapperModel = new TikTokLiveMapperModel("any message");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bytesToEvent(String messageName, Function<byte[], TikTokEvent> onMapping) {
|
public TikTokMapperModel forMessage(String messageName) {
|
||||||
mappers.put(messageName, messagePayload -> List.of(onMapping.apply(messagePayload)));
|
if (!isRegistered(messageName)) {
|
||||||
|
var model = new TikTokLiveMapperModel(messageName);
|
||||||
|
mappers.put(messageName, model);
|
||||||
|
}
|
||||||
|
return mappers.get(messageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bytesToEvents(String messageName, Function<byte[], List<TikTokEvent>> onMapping) {
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName) {
|
||||||
mappers.put(messageName, onMapping::apply);
|
return forMessage(mapperName.getSimpleName());
|
||||||
}
|
|
||||||
|
|
||||||
public void bytesToEvent(Class<? extends GeneratedMessageV3> clazz, Function<byte[], TikTokEvent> onMapping) {
|
|
||||||
mappers.put(clazz.getSimpleName(), messagePayload -> List.of(onMapping.apply(messagePayload)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void bytesToEvents(Class<? extends GeneratedMessageV3> clazz, Function<byte[], List<TikTokEvent>> onMapping) {
|
|
||||||
mappers.put(clazz.getSimpleName(), onMapping::apply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void webcastObjectToConstructor(Class<? extends GeneratedMessageV3> sourceClass, Class<? extends TikTokEvent> outputClass) {
|
public TikTokMapperModel forMessage(String mapperName, MappingAction<MappingResult> onMapping) {
|
||||||
bytesToEvent(sourceClass, (e) -> genericMapper.mapToEvent(sourceClass, outputClass, e));
|
var model = forMessage(mapperName);
|
||||||
|
model.onMapping(onMapping);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping) {
|
||||||
|
var model = forMessage(mapperName);
|
||||||
|
model.onMapping(onMapping);
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GeneratedMessageV3> void webcastObjectToEvent(Class<T> source, Function<T, TikTokEvent> onMapping) {
|
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, Function<byte[], TikTokEvent> onMapping) {
|
||||||
bytesToEvent(source, (bytes) ->
|
return forMessage(mapperName, (inputBytes, messageName, mapperHelper) -> MappingResult.of(inputBytes, onMapping.apply(inputBytes)));
|
||||||
{
|
|
||||||
try {
|
|
||||||
var parsingMethod = genericMapper.getParsingMethod(source);
|
|
||||||
var sourceObject = parsingMethod.invoke(null, bytes);
|
|
||||||
var event = onMapping.apply((T) sourceObject);
|
|
||||||
return event;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException(source, "can't find parsing method", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GeneratedMessageV3> void webcastObjectToEvents(Class<T> source, Function<T, List<TikTokEvent>> onMapping) {
|
public TikTokMapperModel forAnyMessage() {
|
||||||
bytesToEvents(source, (bytes) ->
|
return globalMapperModel;
|
||||||
{
|
|
||||||
try {
|
|
||||||
var parsingMethod = genericMapper.getParsingMethod(source);
|
|
||||||
var sourceObject = parsingMethod.invoke(null, bytes);
|
|
||||||
var event = onMapping.apply((T) sourceObject);
|
|
||||||
return event;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException(source, "can't find parsing method", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRegistered(String input) {
|
|
||||||
return mappers.containsKey(input);
|
public boolean isRegistered(String mapperName) {
|
||||||
|
return mappers.containsKey(mapperName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TikTokEvent> handleMapping(String input, byte[] bytes) {
|
public <T extends GeneratedMessageV3> boolean isRegistered(Class<T> mapperName) {
|
||||||
if (!isRegistered(input)) {
|
return mappers.containsKey(mapperName.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TikTokEvent> handleMapping(String messageName, byte[] bytes) {
|
||||||
|
if (!isRegistered(messageName)) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
var mapper = mappers.get(input);
|
var mapperModel = mappers.get(messageName);
|
||||||
var events = mapper.apply(bytes);
|
|
||||||
return events;
|
var inputBytes = mapperModel.getOnBeforeMapping().onMapping(bytes, messageName, mapperUtils);
|
||||||
|
var globalInputBytes = globalMapperModel.getOnBeforeMapping().onMapping(inputBytes, messageName, mapperUtils);
|
||||||
|
|
||||||
|
|
||||||
|
var mappingResult = mapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||||
|
|
||||||
|
if (mappingResult == null) {
|
||||||
|
mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
var afterMappingResult = mapperModel.getOnAfterMapping().apply(mappingResult);
|
||||||
|
var globalAfterMappingResult = globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult));
|
||||||
|
return globalAfterMappingResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
||||||
|
|
||||||
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtoBufferObject;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
||||||
|
|
||||||
|
public class TikTokLiveMapperHelper implements TikTokMapperHelper {
|
||||||
|
private final TikTokGenericEventMapper genericMapper;
|
||||||
|
|
||||||
|
public TikTokLiveMapperHelper(TikTokGenericEventMapper genericMapper) {
|
||||||
|
this.genericMapper = genericMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends GeneratedMessageV3> T bytesToWebcastObject(byte[] bytes, Class<T> messageClass) {
|
||||||
|
try {
|
||||||
|
var parsingMethod = genericMapper.getParsingMethod(messageClass);
|
||||||
|
var sourceObject = parsingMethod.invoke(null, bytes);
|
||||||
|
return (T) sourceObject;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TikTokMessageMappingException(messageClass, "can't find parsing method", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object bytesToWebcastObject(byte[] bytes, String messageName) {
|
||||||
|
try {
|
||||||
|
var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName;
|
||||||
|
var clazz = Class.forName(packageName);
|
||||||
|
return bytesToWebcastObject(bytes, (Class<? extends GeneratedMessageV3>) clazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TikTokMessageMappingException(messageName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMessageHasProtoClass(String messageName) {
|
||||||
|
try {
|
||||||
|
var packageName = "io.github.jwdeveloper.tiktok.messages.webcast." + messageName;
|
||||||
|
Class.forName(packageName);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProtoBufferObject bytesToProtoBufferStructure(byte[] bytes) {
|
||||||
|
return ProtocolUtils.getProtocolBufferStructure(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJson(Object obj) {
|
||||||
|
return JsonUtil.toJson(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.mappers;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TikTokLiveMapperModel implements TikTokMapperModel {
|
||||||
|
@Getter
|
||||||
|
private String sourceMessageName;
|
||||||
|
|
||||||
|
private MappingAction<byte[]> onBeforeMapping;
|
||||||
|
|
||||||
|
private MappingAction<MappingResult> onMapping;
|
||||||
|
|
||||||
|
private Function<MappingResult, List<TikTokEvent>> onAfterMapping;
|
||||||
|
|
||||||
|
public TikTokLiveMapperModel(String sourceMessageName, MappingAction onMapping) {
|
||||||
|
this.sourceMessageName = sourceMessageName;
|
||||||
|
this.onBeforeMapping = (inputBytes, mesasgeName, mapperHelper) -> inputBytes;
|
||||||
|
this.onMapping = onMapping;
|
||||||
|
this.onAfterMapping = MappingResult::getEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokLiveMapperModel(String sourceMessageName) {
|
||||||
|
this.sourceMessageName = sourceMessageName;
|
||||||
|
this.onBeforeMapping = (inputBytes, mesasgeName, mapperHelper) -> inputBytes;
|
||||||
|
this.onMapping = (inputBytes, mesasgeName, mapperHelper) -> MappingResult.of(inputBytes, List.of());
|
||||||
|
this.onAfterMapping = MappingResult::getEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onBeforeMapping(MappingAction<byte[]> action) {
|
||||||
|
this.onBeforeMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onMapping(MappingAction<MappingResult> action) {
|
||||||
|
this.onMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokMapperModel onAfterMapping(Function<MappingResult, List<TikTokEvent>> action) {
|
||||||
|
this.onAfterMapping = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
public class TikTokChestEventHandler {
|
public class TikTokChestEventHandler {
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,26 @@
|
|||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
/*
|
||||||
|
* 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.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
@@ -43,9 +65,9 @@ public class TikTokCommonEventHandler
|
|||||||
public TikTokEvent handlePollEvent(byte[] msg) {
|
public TikTokEvent handlePollEvent(byte[] msg) {
|
||||||
var poolMessage = WebcastPollMessage.parseFrom(msg);
|
var poolMessage = WebcastPollMessage.parseFrom(msg);
|
||||||
return switch (poolMessage.getMessageType()) {
|
return switch (poolMessage.getMessageType()) {
|
||||||
case 0 -> new TikTokPollStartEvent(poolMessage);
|
case MESSAGETYPE_SUBSUCCESS -> new TikTokPollStartEvent(poolMessage);
|
||||||
case 1 -> new TikTokPollEndEvent(poolMessage);
|
case MESSAGETYPE_ANCHORREMINDER -> new TikTokPollEndEvent(poolMessage);
|
||||||
case 2 -> new TikTokPollUpdateEvent(poolMessage);
|
case MESSAGETYPE_ENTERROOMEXPIRESOON -> new TikTokPollUpdateEvent(poolMessage);
|
||||||
default -> new TikTokPollEvent(poolMessage);
|
default -> new TikTokPollEvent(poolMessage);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -20,8 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
@@ -30,6 +31,8 @@ import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
@@ -41,16 +44,19 @@ import java.util.Map;
|
|||||||
public class TikTokGiftEventHandler {
|
public class TikTokGiftEventHandler {
|
||||||
private final GiftManager giftManager;
|
private final GiftManager giftManager;
|
||||||
private final Map<Long, WebcastGiftMessage> giftsMessages;
|
private final Map<Long, WebcastGiftMessage> giftsMessages;
|
||||||
|
private final TikTokRoomInfo tikTokRoomInfo;
|
||||||
|
|
||||||
public TikTokGiftEventHandler(GiftManager giftManager) {
|
public TikTokGiftEventHandler(GiftManager giftManager, TikTokRoomInfo tikTokRoomInfo) {
|
||||||
this.giftManager = giftManager;
|
this.giftManager = giftManager;
|
||||||
giftsMessages = new HashMap<>();
|
giftsMessages = new HashMap<>();
|
||||||
|
this.tikTokRoomInfo = tikTokRoomInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleGift(byte[] msg) {
|
public MappingResult handleGifts(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
var currentMessage = WebcastGiftMessage.parseFrom(msg);
|
var currentMessage = WebcastGiftMessage.parseFrom(msg);
|
||||||
return handleGift(currentMessage);
|
var gifts = handleGift(currentMessage);
|
||||||
|
return MappingResult.of(currentMessage, gifts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
public List<TikTokEvent> handleGift(WebcastGiftMessage currentMessage) {
|
||||||
@@ -98,12 +104,12 @@ public class TikTokGiftEventHandler {
|
|||||||
|
|
||||||
private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) {
|
private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) {
|
||||||
var gift = getGiftObject(message);
|
var gift = getGiftObject(message);
|
||||||
return new TikTokGiftEvent(gift, message);
|
return new TikTokGiftEvent(gift, tikTokRoomInfo.getHost(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) {
|
private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) {
|
||||||
var gift = getGiftObject(message);
|
var gift = getGiftObject(message);
|
||||||
return new TikTokGiftComboEvent(gift, message, state);
|
return new TikTokGiftComboEvent(gift, tikTokRoomInfo.getHost(), message, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gift getGiftObject(WebcastGiftMessage giftMessage) {
|
private Gift getGiftObject(WebcastGiftMessage giftMessage) {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
||||||
@@ -31,6 +31,8 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
import io.github.jwdeveloper.tiktok.data.models.RankingUser;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.TikTokMapperHelper;
|
||||||
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLikeMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastLiveIntroMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastMemberMessage;
|
||||||
@@ -76,8 +78,7 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
|
|
||||||
return handleRoomInfo(tikTokRoomInfo ->
|
return handleRoomInfo(tikTokRoomInfo ->
|
||||||
{
|
{
|
||||||
if(tikTokRoomInfo.getHost() == null)
|
if (tikTokRoomInfo.getHost() == null) {
|
||||||
{
|
|
||||||
tikTokRoomInfo.setHost(hostUser);
|
tikTokRoomInfo.setHost(hostUser);
|
||||||
}
|
}
|
||||||
tikTokRoomInfo.setLanguage(language);
|
tikTokRoomInfo.setLanguage(language);
|
||||||
@@ -85,7 +86,7 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleMemberMessage(byte[] msg) {
|
public MappingResult handleMemberMessage(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
var message = WebcastMemberMessage.parseFrom(msg);
|
var message = WebcastMemberMessage.parseFrom(msg);
|
||||||
|
|
||||||
var event = switch (message.getAction()) {
|
var event = switch (message.getAction()) {
|
||||||
@@ -98,18 +99,17 @@ public class TikTokRoomInfoEventHandler {
|
|||||||
{
|
{
|
||||||
tikTokRoomInfo.setViewersCount(message.getMemberCount());
|
tikTokRoomInfo.setViewersCount(message.getMemberCount());
|
||||||
});
|
});
|
||||||
|
return MappingResult.of(message, List.of(event, roomInfoEvent));
|
||||||
return List.of(event, roomInfoEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public List<TikTokEvent> handleLike(byte[] msg)
|
public MappingResult handleLike(byte[] msg, String name, TikTokMapperHelper helper) {
|
||||||
{
|
|
||||||
var message = WebcastLikeMessage.parseFrom(msg);
|
var message = WebcastLikeMessage.parseFrom(msg);
|
||||||
var event = new TikTokLikeEvent(message);
|
var event = new TikTokLikeEvent(message);
|
||||||
var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo ->
|
var roomInfoEvent = this.handleRoomInfo(tikTokRoomInfo ->
|
||||||
{
|
{
|
||||||
tikTokRoomInfo.setLikesCount(event.getTotalLikes());
|
tikTokRoomInfo.setLikesCount(event.getTotalLikes());
|
||||||
});
|
});
|
||||||
return List.of(event, roomInfoEvent);
|
return MappingResult.of(message, List.of(event, roomInfoEvent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mappers.events;
|
package io.github.jwdeveloper.tiktok.mappers.handlers;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokUnhandledSocialEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokUnhandledSocialEvent;
|
||||||
@@ -39,7 +39,6 @@ import java.util.TreeMap;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class TikTokWebSocketClient implements SocketClient {
|
public class TikTokWebSocketClient implements SocketClient {
|
||||||
private final Logger logger;
|
|
||||||
private final ClientSettings clientSettings;
|
private final ClientSettings clientSettings;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final TikTokMessageHandler messageHandler;
|
private final TikTokMessageHandler messageHandler;
|
||||||
@@ -48,12 +47,11 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
private TikTokWebSocketPingingTask pingingTask;
|
private TikTokWebSocketPingingTask pingingTask;
|
||||||
private boolean isConnected;
|
private boolean isConnected;
|
||||||
|
|
||||||
public TikTokWebSocketClient(Logger logger,
|
public TikTokWebSocketClient(
|
||||||
TikTokCookieJar tikTokCookieJar,
|
TikTokCookieJar tikTokCookieJar,
|
||||||
ClientSettings clientSettings,
|
ClientSettings clientSettings,
|
||||||
TikTokMessageHandler messageHandler,
|
TikTokMessageHandler messageHandler,
|
||||||
TikTokEventObserver tikTokEventHandler) {
|
TikTokEventObserver tikTokEventHandler) {
|
||||||
this.logger = logger;
|
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.clientSettings = clientSettings;
|
this.clientSettings = clientSettings;
|
||||||
this.messageHandler = messageHandler;
|
this.messageHandler = messageHandler;
|
||||||
|
|||||||
@@ -22,12 +22,13 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.handlers.events;
|
package io.github.jwdeveloper.tiktok.handlers.events;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType;
|
||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
import io.github.jwdeveloper.tiktok.mappers.handlers.TikTokGiftEventHandler;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
import io.github.jwdeveloper.tiktok.messages.data.GiftStruct;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.Image;
|
import io.github.jwdeveloper.tiktok.messages.data.Image;
|
||||||
import io.github.jwdeveloper.tiktok.messages.data.User;
|
import io.github.jwdeveloper.tiktok.messages.data.User;
|
||||||
@@ -49,42 +50,43 @@ class TikTokGiftEventHandlerTest {
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
public void before() {
|
public void before() {
|
||||||
var manager = new TikTokGiftManager(Logger.getLogger("x"));
|
var manager = new TikTokGiftManager(Logger.getLogger("x"));
|
||||||
|
var info = new TikTokRoomInfo();
|
||||||
|
info.setHost(new io.github.jwdeveloper.tiktok.data.models.users.User(123L, "test", new Picture("")));
|
||||||
manager.registerGift(123, "example", 123, new Picture("image.webp"));
|
manager.registerGift(123, "example", 123, new Picture("image.webp"));
|
||||||
handler = new TikTokGiftEventHandler(manager);
|
handler = new TikTokGiftEventHandler(manager, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleGifts() {
|
void shouldHandleGifts() {
|
||||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,false);
|
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, false);
|
||||||
var result = handler.handleGift(message);
|
var result = handler.handleGift(message);
|
||||||
|
|
||||||
Assertions.assertEquals(2, result.size());
|
Assertions.assertEquals(2, result.size());
|
||||||
|
|
||||||
var event = (TikTokGiftEvent) result.get(0);
|
var event = (TikTokGiftEvent) result.get(0);
|
||||||
var gift = event.getGift();
|
var gift = event.getGift();
|
||||||
Assertions.assertEquals("image-new.png",gift.getPicture().getLink());
|
Assertions.assertEquals("image-new.png", gift.getPicture().getLink());
|
||||||
Assertions.assertEquals(123,gift.getId());
|
Assertions.assertEquals(123, gift.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleStrakableGift() {
|
void shouldHandleStrakableGift() {
|
||||||
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
var message = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, true);
|
||||||
var result = handler.handleGift(message);
|
var result = handler.handleGift(message);
|
||||||
|
|
||||||
Assertions.assertEquals(1, result.size());
|
Assertions.assertEquals(1, result.size());
|
||||||
|
|
||||||
var event = (TikTokGiftEvent) result.get(0);
|
var event = (TikTokGiftEvent) result.get(0);
|
||||||
var gift = event.getGift();
|
var gift = event.getGift();
|
||||||
Assertions.assertEquals("image-new.png",gift.getPicture().getLink());
|
Assertions.assertEquals("image-new.png", gift.getPicture().getLink());
|
||||||
Assertions.assertEquals(123,gift.getId());
|
Assertions.assertEquals(123, gift.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleStrike()
|
void shouldHandleStrike() {
|
||||||
{
|
var message1 = getGiftMessage("example-new-name", 123, "image-new.png", 1, 1, true);
|
||||||
var message1 = getGiftMessage("example-new-name", 123, "image-new.png", 1, 1,true);
|
var message2 = getGiftMessage("example-new-name", 123, "image-new.png", 2, 1, true);
|
||||||
var message2 = getGiftMessage("example-new-name", 123, "image-new.png", 2, 1,true);
|
var message3 = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1, true);
|
||||||
var message3 = getGiftMessage("example-new-name", 123, "image-new.png", 0, 1,true);
|
|
||||||
|
|
||||||
var result1 = handler.handleGift(message1);
|
var result1 = handler.handleGift(message1);
|
||||||
var result2 = handler.handleGift(message2);
|
var result2 = handler.handleGift(message2);
|
||||||
@@ -96,9 +98,9 @@ class TikTokGiftEventHandlerTest {
|
|||||||
Assertions.assertEquals(2, result3.size());
|
Assertions.assertEquals(2, result3.size());
|
||||||
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
var event3 = (TikTokGiftComboEvent) result3.get(0);
|
||||||
|
|
||||||
Assertions.assertEquals(GiftSendType.Begin,event1.getComboState());
|
Assertions.assertEquals(GiftSendType.Begin, event1.getComboState());
|
||||||
Assertions.assertEquals(GiftSendType.Active,event2.getComboState());
|
Assertions.assertEquals(GiftSendType.Active, event2.getComboState());
|
||||||
Assertions.assertEquals(GiftSendType.Finished,event3.getComboState());
|
Assertions.assertEquals(GiftSendType.Finished, event3.getComboState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +118,7 @@ class TikTokGiftEventHandlerTest {
|
|||||||
giftBuilder.setId(giftId);
|
giftBuilder.setId(giftId);
|
||||||
giftBuilder.setName(giftName);
|
giftBuilder.setName(giftName);
|
||||||
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
|
giftBuilder.setImage(Image.newBuilder().addUrlList(giftImage).build());
|
||||||
giftBuilder.setType(streakable?1:0);
|
giftBuilder.setType(streakable ? 1 : 0);
|
||||||
userBuilder.setId(userId);
|
userBuilder.setId(userId);
|
||||||
|
|
||||||
builder.setGiftId(giftId);
|
builder.setGiftId(giftId);
|
||||||
@@ -127,5 +129,4 @@ class TikTokGiftEventHandlerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class HttpUtilsTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void parseParameters_EmptyParameters_ShouldHaveNoParameters()
|
||||||
|
{
|
||||||
|
String parsed = HttpUtils.parseParameters("https://webcast.tiktok.com/webcast/im/fetch/", new HashMap<>());
|
||||||
|
|
||||||
|
Assertions.assertEquals("https://webcast.tiktok.com/webcast/im/fetch/", parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseParameters_ValidParameters_ShouldConstructValidURL()
|
||||||
|
{
|
||||||
|
LinkedHashMap<String, Object> testMap = new LinkedHashMap<>();
|
||||||
|
testMap.put("room_id", 1);
|
||||||
|
testMap.put("uniqueId", "randomName");
|
||||||
|
String parsed = HttpUtils.parseParameters("https://webcast.tiktok.com/webcast/im/fetch/", testMap);
|
||||||
|
|
||||||
|
Assertions.assertEquals("https://webcast.tiktok.com/webcast/im/fetch/?room_id=1&uniqueId=randomName", parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseParametersEncode_EmptyParameters_ShouldHaveNoParameters()
|
||||||
|
{
|
||||||
|
String parsed = HttpUtils.parseParametersEncode("https://webcast.tiktok.com/webcast/im/fetch/", new HashMap<>());
|
||||||
|
|
||||||
|
Assertions.assertEquals("https://webcast.tiktok.com/webcast/im/fetch/", parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseParametersEncode_ValidParameters_ShouldConstructValidURL()
|
||||||
|
{
|
||||||
|
LinkedHashMap<String, Object> testMap = new LinkedHashMap<>();
|
||||||
|
testMap.put("room_id", 1);
|
||||||
|
testMap.put("root_referer", "https://www.tiktok.com/");
|
||||||
|
String parsed = HttpUtils.parseParametersEncode("https://webcast.tiktok.com/webcast/im/fetch/", testMap);
|
||||||
|
|
||||||
|
Assertions.assertEquals("https://webcast.tiktok.com/webcast/im/fetch/?room_id=1&root_referer=https%3A%2F%2Fwww.tiktok.com%2F", parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,6 @@ package io.github.jwdeveloper.tiktok.http;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.LiveRoomMetaMapper;
|
import io.github.jwdeveloper.tiktok.mappers.LiveRoomMetaMapper;
|
||||||
@@ -84,28 +83,6 @@ public class TikTokApiServiceTest
|
|||||||
verify(tiktokHttpClient, times(1)).setSessionId("validSessionId");
|
verify(tiktokHttpClient, times(1)).setSessionId("validSessionId");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Test
|
|
||||||
void fetchRoomId_ValidResponse_ReturnsRoomId() throws Exception {
|
|
||||||
String expectedRoomId = "123456";
|
|
||||||
String htmlResponse = "room_id=" + expectedRoomId ;
|
|
||||||
when(tiktokHttpClient.getLivestreamPage(anyString())).thenReturn(htmlResponse);
|
|
||||||
|
|
||||||
String roomId = tikTokApiService.fetchRoomId("username");
|
|
||||||
|
|
||||||
assertEquals(expectedRoomId, roomId);
|
|
||||||
verify(clientSettings.getClientParameters()).put("room_id", expectedRoomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Test
|
|
||||||
void fetchRoomId_ExceptionThrown_ThrowsTikTokLiveRequestException() throws Exception {
|
|
||||||
when(tiktokHttpClient.getLivestreamPage(anyString())).thenThrow(new Exception("some exception"));
|
|
||||||
|
|
||||||
assertThrows(TikTokLiveRequestException.class, () -> {
|
|
||||||
tikTokApiService.fetchRoomId("username");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Test
|
//@Test
|
||||||
void fetchRoomInfo_ValidResponse_ReturnsLiveRoomMeta() throws Exception {
|
void fetchRoomInfo_ValidResponse_ReturnsLiveRoomMeta() throws Exception {
|
||||||
HashMap<String, Object> clientParameters = new HashMap<>();
|
HashMap<String, Object> clientParameters = new HashMap<>();
|
||||||
|
|||||||
@@ -22,12 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.listener;
|
package io.github.jwdeveloper.tiktok.listener;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -42,12 +41,12 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
class TikTokListenersManagerTest {
|
class TikTokListenersManagerTest {
|
||||||
|
|
||||||
private TikTokEventObserver eventObserver;
|
private io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver eventObserver;
|
||||||
private TikTokListenersManager tikTokListenersManager;
|
private TikTokListenersManager tikTokListenersManager;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
eventObserver = Mockito.mock(TikTokEventObserver.class);
|
eventObserver = Mockito.mock(io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver.class);
|
||||||
List<TikTokEventListener> listeners = new ArrayList<>();
|
List<TikTokEventListener> listeners = new ArrayList<>();
|
||||||
tikTokListenersManager = new TikTokListenersManager(listeners, eventObserver);
|
tikTokListenersManager = new TikTokListenersManager(listeners, eventObserver);
|
||||||
}
|
}
|
||||||
@@ -93,19 +92,19 @@ class TikTokListenersManagerTest {
|
|||||||
|
|
||||||
public static class TikTokEventListenerTest implements TikTokEventListener
|
public static class TikTokEventListenerTest implements TikTokEventListener
|
||||||
{
|
{
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onJoin(LiveClient client, TikTokJoinEvent joinEvent)
|
public void onJoin(LiveClient client, TikTokJoinEvent joinEvent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent)
|
public void onGift(LiveClient client, TikTokGiftEvent giftMessageEvent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onEvent(LiveClient client, TikTokEvent event)
|
public void onEvent(LiveClient client, TikTokEvent event)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.GiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
public class CustomEventExample {
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CheapGiftEvent extends TikTokEvent {
|
||||||
|
Gift gift;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ExpensiveGiftEvent extends TikTokEvent {
|
||||||
|
Gift gift;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||||
|
.onGift((liveClient, event) ->
|
||||||
|
{
|
||||||
|
if (event.getGift().getDiamondCost() > 100)
|
||||||
|
liveClient.publishEvent(new ExpensiveGiftEvent(event.getGift()));
|
||||||
|
else
|
||||||
|
liveClient.publishEvent(new CheapGiftEvent(event.getGift()));
|
||||||
|
})
|
||||||
|
.onEvent(CheapGiftEvent.class,(liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Thanks for cheap gift");
|
||||||
|
})
|
||||||
|
.onEvent(ExpensiveGiftEvent.class,(liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Thanks for expensive gift!");
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastChatMessage;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastChatMessage;
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
|
||||||
import io.github.jwdeveloper.tiktok.utils.ProtocolUtils;
|
|
||||||
|
|
||||||
public class CustomMappingExample {
|
public class CustomMappingExample {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TikTokLive.newClient("vadimpyrography")
|
TikTokLive.newClient("saszareznikow")
|
||||||
.onCustomEvent(CustomChatEvent.class, (liveClient, event) ->
|
.onMapping(mapper ->
|
||||||
{
|
{
|
||||||
System.out.println("hello world!");
|
mapper.forMessage(WebcastChatMessage.class)
|
||||||
|
.onBeforeMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
System.out.println("===============================");
|
||||||
|
System.out.println("OnBefore mapping: " + messageName);
|
||||||
|
return inputBytes;
|
||||||
|
})
|
||||||
|
.onMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
System.out.println("onMapping mapping: " + messageName);
|
||||||
|
var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
|
||||||
|
var language = message.getContentLanguage();
|
||||||
|
var userName = message.getUser().getNickname();
|
||||||
|
var content = message.getContent();
|
||||||
|
var event = new CustomChatEvent(language, userName, content);
|
||||||
|
return MappingResult.of(message, event);
|
||||||
|
})
|
||||||
|
.onAfterMapping(mappingResult ->
|
||||||
|
{
|
||||||
|
var source = mappingResult.getSource();
|
||||||
|
var events = mappingResult.getEvents();
|
||||||
|
System.out.println("onAfter mapping, " + source.getClass().getSimpleName() + " was mapped to " + events.size() + " events");
|
||||||
|
return events;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
There might be cast that we don't have Webcast class for incoming message from TikTok
|
||||||
|
`mapperHelper.bytesToProtoBufferStructure` but you can still investigate message structure
|
||||||
|
by using helper methods
|
||||||
|
*/
|
||||||
|
mapper.forMessage("WebcastMemberMessage")
|
||||||
|
.onBeforeMapping((inputBytes, messageName, mapperHelper) ->
|
||||||
|
{
|
||||||
|
if (mapperHelper.isMessageHasProtoClass(messageName)) {
|
||||||
|
var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, messageName);
|
||||||
|
// System.out.println(mapperHelper.toJson(messageObject));
|
||||||
|
} else {
|
||||||
|
var structure = mapperHelper.bytesToProtoBufferStructure(inputBytes);
|
||||||
|
// System.out.println(structure.toJson());
|
||||||
|
}
|
||||||
|
return inputBytes;
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.onError((liveClient, event) ->
|
.onError((liveClient, event) ->
|
||||||
{
|
{
|
||||||
event.getException().printStackTrace();
|
event.getException().printStackTrace();
|
||||||
})
|
})
|
||||||
.onMapping(mapper ->
|
.buildAndConnect();
|
||||||
{
|
|
||||||
mapper.webcastObjectToEvent(WebcastChatMessage.class, chatMessage ->
|
|
||||||
{
|
|
||||||
var language = chatMessage.getContentLanguage();
|
|
||||||
var userName = chatMessage.getUser().getNickname();
|
|
||||||
var message = chatMessage.getContent();
|
|
||||||
return new CustomChatEvent(language, userName, message);
|
|
||||||
});
|
|
||||||
mapper.bytesToEvent("WebcastGiftMessage", bytes ->
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var event = WebcastGiftMessage.parseFrom(bytes);
|
|
||||||
return new TikTokGiftEvent(Gift.ROSA, event);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokMessageMappingException("unable to map gift message!", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mapper.bytesToEvent("WebcastMemberMessage",bytes ->
|
|
||||||
{
|
|
||||||
//displaying unknown messages from tiktok
|
|
||||||
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
|
||||||
System.out.println(structure.toJson());
|
|
||||||
return new TikTokErrorEvent(new RuntimeException("Message not implemented"));
|
|
||||||
});
|
|
||||||
}).buildAndConnect();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventHandler;
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
@@ -65,24 +65,24 @@ public class ListenerExample
|
|||||||
|
|
||||||
public static class CustomListener implements TikTokEventListener {
|
public static class CustomListener implements TikTokEventListener {
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||||
System.out.println(event.toString());
|
System.out.println(event.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||||
// event.getException().printStackTrace();
|
// event.getException().printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||||
var userName = event.getUser().getName();
|
var userName = event.getUser().getName();
|
||||||
var text = event.getText();
|
var text = event.getText();
|
||||||
liveClient.getLogger().info(userName + ": " + text);
|
liveClient.getLogger().info(userName + ": " + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||||
var message = switch (event.getGift()) {
|
var message = switch (event.getGift()) {
|
||||||
case ROSE -> "Thanks :)";
|
case ROSE -> "Thanks :)";
|
||||||
@@ -95,7 +95,7 @@ public class ListenerExample
|
|||||||
liveClient.getLogger().info(message);
|
liveClient.getLogger().info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -1,7 +1,6 @@
|
|||||||
<div align="center" >
|
<div align="center" >
|
||||||
<a target="blank" >
|
<a target="blank" >
|
||||||
<img src="https://raw.githubusercontent.com/jwdeveloper/TikTokLiveJava/develop-1_0_0/Tools-ReadmeGenerator/src/main/resources/logo.svg" width="15%" >
|
<img src="https://raw.githubusercontent.com/jwdeveloper/TikTokLiveJava/develop-1_0_0/Tools-ReadmeGenerator/src/main/resources/logo.svg" width="15%" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div align="center" >
|
<div align="center" >
|
||||||
@@ -12,18 +11,15 @@
|
|||||||
<div align="center" >
|
<div align="center" >
|
||||||
<a href="https://jitpack.io/#jwdeveloper/TikTok-Live-Java" target="blank" >
|
<a href="https://jitpack.io/#jwdeveloper/TikTok-Live-Java" target="blank" >
|
||||||
<img src="https://jitpack.io/v/jwdeveloper/TikTok-Live-Java.svg" width="20%" >
|
<img src="https://jitpack.io/v/jwdeveloper/TikTok-Live-Java.svg" width="20%" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a href="https://discord.gg/e2XwPNTBBr" target="blank" >
|
<a href="https://discord.gg/e2XwPNTBBr" target="blank" >
|
||||||
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white" >
|
<img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a target="blank" >
|
<a target="blank" >
|
||||||
<img src="https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge&logo=openjdk&logoColor=white" >
|
<img src="https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge&logo=openjdk&logoColor=white" >
|
||||||
</img>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,6 +29,9 @@ A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive
|
|||||||
The library includes a wrapper that connects to the WebCast service using just the username (`uniqueId`). This allows you to connect to your own live chat as well as the live chat of other streamers.
|
The library includes a wrapper that connects to the WebCast service using just the username (`uniqueId`). This allows you to connect to your own live chat as well as the live chat of other streamers.
|
||||||
No credentials are required. Events such as [Members Joining](#member), [Gifts](#gift), [Subscriptions](#subscribe), [Viewers](#roomuser), [Follows](#social), [Shares](#social), [Questions](#questionnew), [Likes](#like) and [Battles](#linkmicbattle) can be tracked.
|
No credentials are required. Events such as [Members Joining](#member), [Gifts](#gift), [Subscriptions](#subscribe), [Viewers](#roomuser), [Follows](#social), [Shares](#social), [Questions](#questionnew), [Likes](#like) and [Battles](#linkmicbattle) can be tracked.
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
[Library documentation for contributors](https://github.com/jwdeveloper/TikTokLiveJava/wiki)
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,8 +54,9 @@ Do you prefer other programming languages?
|
|||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
1. Install the package via Maven
|
1. Install the package
|
||||||
|
|
||||||
|
Maven
|
||||||
```xml
|
```xml
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
@@ -69,12 +69,27 @@ Do you prefer other programming languages?
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
<artifactId>Client</artifactId>
|
<artifactId>Client</artifactId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.12-Release</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Gradle
|
||||||
|
```gradle
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.0.12-Release'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
2. Create your first chat connection
|
2. Create your first chat connection
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@@ -419,9 +434,9 @@ Triggered every time gift is sent
|
|||||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
<p>Combo: 12 -> comboState = GiftSendType.Finished</p>
|
||||||
|
|
||||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
Remember if comboState is Finished both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.6-Release</version>
|
<version>1.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokDataCollectorBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollectorBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.TikTokDataTesterBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterBuilder;
|
||||||
|
|
||||||
|
public class TikTokLiveTools
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param databaseName dataCollector use sql-lite database to store message
|
||||||
|
* if database not exits it creates new one
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static DataCollectorBuilder createCollector(String databaseName)
|
||||||
|
{
|
||||||
|
return new TikTokDataCollectorBuilder(databaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param databaseName dataTester will read messages for database
|
||||||
|
* before using dataTester, use dataCollector to create database
|
||||||
|
* if database not exits exception will be thrown
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static DataTesterBuilder createTester(String databaseName)
|
||||||
|
{
|
||||||
|
return new TikTokDataTesterBuilder(databaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Returns browser application that collects and display Events, Messages, WebcastResponses
|
||||||
|
* in online web editor so it's easier to read and analyze data structures
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static void createWebViewer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,93 +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.collector;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.gifts.Gift;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
public class RunCollector {
|
|
||||||
|
|
||||||
//https://protobuf-decoder.netlify.app/
|
|
||||||
//https://streamdps.com/tiktok-widgets/gifts/
|
|
||||||
|
|
||||||
//WebcastLinkMicBattleItemCard does streamer win battle?
|
|
||||||
|
|
||||||
public static void main(String[] args) throws SQLException, IOException {
|
|
||||||
|
|
||||||
TikTokMessageCollectorClient.create("giftsCollector")
|
|
||||||
//.addUser("crece.sara")
|
|
||||||
//.addUser("moniczkka")
|
|
||||||
.addUser("valeria.viral")
|
|
||||||
// .addUser("cbcgod")
|
|
||||||
// .addUser("psychotropnazywo")
|
|
||||||
// .addUser("accordionistka")
|
|
||||||
//.addEventFilter(WebcastGiftMessage.class)
|
|
||||||
.addOnBuilder(liveClientBuilder ->
|
|
||||||
{
|
|
||||||
liveClientBuilder.onGiftCombo((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().setLevel(Level.OFF);
|
|
||||||
var gifts = liveClient.getGiftManager().getGifts();
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("GIFT COMBO User: " + event.getUser().getProfileName()+" ");
|
|
||||||
sb.append("Name: " + event.getGift().getName() + " ");
|
|
||||||
sb.append("Combo: " + event.getCombo() + " ");
|
|
||||||
sb.append("COST: " + event.getGift().getDiamondCost() + " ");
|
|
||||||
sb.append("STATE: " + event.getComboState() + " ");
|
|
||||||
System.out.println(sb.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
liveClientBuilder.onGift((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().setLevel(Level.OFF);
|
|
||||||
var gifts = liveClient.getGiftManager().getGifts();
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("GIFT User: " + event.getUser().getProfileName()+" ");
|
|
||||||
sb.append("Name: " + event.getGift().getName() + " ");
|
|
||||||
sb.append("COST: " + event.getGift().getDiamondCost() + " ");
|
|
||||||
sb.append("Combo: " + event.getCombo() + " ");
|
|
||||||
System.out.println(sb.toString());
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.buildAndRun();
|
|
||||||
|
|
||||||
System.in.read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
public interface DataCollector {
|
||||||
|
|
||||||
|
void connect();
|
||||||
|
|
||||||
|
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
|
void disconnect(boolean keepDatabase);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public interface DataCollectorBuilder extends DataFilters<DataCollectorBuilder> {
|
||||||
|
DataCollectorBuilder setOutputPath(String path);
|
||||||
|
DataCollectorBuilder setSessionTag(String sessionTimestamp);
|
||||||
|
|
||||||
|
DataCollectorBuilder setDatabase(TikTokDatabase database);
|
||||||
|
|
||||||
|
DataCollectorBuilder configureLiveClient(Consumer<LiveClientBuilder> consumer);
|
||||||
|
|
||||||
|
DataCollectorBuilder addUser(String user);
|
||||||
|
|
||||||
|
DataCollector buildAndRun();
|
||||||
|
|
||||||
|
DataCollector build();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
|
||||||
|
public interface DataFilters<T> {
|
||||||
|
T addMessageFilter(Class<? extends com.google.protobuf.GeneratedMessageV3> message);
|
||||||
|
|
||||||
|
T addMessageFilter(String message);
|
||||||
|
|
||||||
|
T addEventFilter(Class<? extends TikTokEvent> event);
|
||||||
|
|
||||||
|
T addEventFilter(String event);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TikTokDataCollectorModel {
|
||||||
|
private List<String> users;
|
||||||
|
private String outputPath;
|
||||||
|
private String outputName;
|
||||||
|
private Set<String> eventsFilter;
|
||||||
|
private Set<String> messagesFilter;
|
||||||
|
private String sessionTag ="";
|
||||||
|
private Consumer<LiveClientBuilder> onConfigureLiveClient;
|
||||||
|
}
|
||||||
@@ -37,14 +37,14 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class MessageCollector {
|
public class MessagesManager {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
Map<String, Queue<MessageData>> messages;
|
Map<String, Queue<MessageData>> messages;
|
||||||
String outputName;
|
String outputName;
|
||||||
|
|
||||||
int limit = 20;
|
int limit = 20;
|
||||||
public MessageCollector(String outputName) {
|
public MessagesManager(String outputName) {
|
||||||
this.messages = new TreeMap<>();
|
this.messages = new TreeMap<>();
|
||||||
this.outputName = outputName;
|
this.outputName = outputName;
|
||||||
load();
|
load();
|
||||||
@@ -22,104 +22,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
package io.github.jwdeveloper.tiktok.tools.collector.client;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
|
||||||
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.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class TikTokClientFactory {
|
public class TikTokClientFactory {
|
||||||
private final MessageCollector messageCollector;
|
private final MessagesManager messageCollector;
|
||||||
private final TikTokDatabase tikTokDatabase;
|
private final TikTokDatabase tikTokDatabase;
|
||||||
|
|
||||||
public TikTokClientFactory(MessageCollector messageCollector, TikTokDatabase tikTokDatabase) {
|
public TikTokClientFactory(MessagesManager messageCollector, TikTokDatabase tikTokDatabase) {
|
||||||
this.messageCollector = messageCollector;
|
this.messageCollector = messageCollector;
|
||||||
this.tikTokDatabase = tikTokDatabase;
|
this.tikTokDatabase = tikTokDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<LiveClient> runClientAsync(String tiktokUser, List<Class<?>> filters, Consumer<LiveClientBuilder> onBuilder) {
|
|
||||||
var builder = TikTokLive.newClient(tiktokUser);
|
|
||||||
var msgFilter = filters.stream().map(Class::getSimpleName).toList();
|
|
||||||
onBuilder.accept(builder);
|
|
||||||
return builder.onConnected((liveClient, event) ->
|
|
||||||
{
|
|
||||||
liveClient.getLogger().info("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);
|
|
||||||
liveClient.getLogger().info("Response");
|
|
||||||
for (var message : event.getResponse().getMessagesList())
|
|
||||||
{
|
|
||||||
if(msgFilter.size() > 0 && !msgFilter.contains(message.getMethod()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
messageCollector.addMessage(liveClient.getLogger(), liveClient.getRoomInfo().getHostName(), message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onWebsocketMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var eventName = event.getEvent().getClass().getSimpleName();
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (msgFilter.size() != 0 && !msgFilter.contains(event.getEvent().getClass())) {
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var messageBinary = Base64.getEncoder().encodeToString(event.getMessage().toByteArray());
|
|
||||||
var model = new TikTokMessageModel();
|
|
||||||
model.setType("messsage");
|
|
||||||
model.setHostName(tiktokUser);
|
|
||||||
model.setEventName(eventName);
|
|
||||||
model.setMessage(messageBinary);
|
|
||||||
|
|
||||||
// tikTokDatabase.insertMessage(model);
|
|
||||||
// liveClient.getLogger().info("EVENT: [" + tiktokUser + "] " + eventName);
|
|
||||||
})
|
|
||||||
.onError((liveClient, event) ->
|
|
||||||
{
|
|
||||||
event.getException().printStackTrace();
|
|
||||||
var exception = event.getException();
|
|
||||||
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
|
|
||||||
var errorModel = new TikTokErrorModel();
|
|
||||||
if (exception instanceof TikTokLiveMessageException ex) {
|
|
||||||
errorModel.setHostName(tiktokUser);
|
|
||||||
errorModel.setErrorName(ex.messageMethod());
|
|
||||||
errorModel.setErrorType("error-message");
|
|
||||||
errorModel.setExceptionContent(exceptionContent);
|
|
||||||
errorModel.setMessage(ex.messageToBase64());
|
|
||||||
errorModel.setResponse(ex.webcastResponseToBase64());
|
|
||||||
} else {
|
|
||||||
errorModel.setHostName(tiktokUser);
|
|
||||||
errorModel.setErrorName(exception.getClass().getSimpleName());
|
|
||||||
errorModel.setErrorType("error-system");
|
|
||||||
errorModel.setExceptionContent(exceptionContent);
|
|
||||||
errorModel.setMessage("");
|
|
||||||
errorModel.setResponse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tikTokDatabase.insertError(errorModel);
|
|
||||||
liveClient.getLogger().info("ERROR: " + errorModel.getErrorName());
|
|
||||||
exception.printStackTrace();
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnectAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* 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.client;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollector;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.TikTokDataCollectorModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.ExceptionInfoModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TikTokDataCollector implements DataCollector {
|
||||||
|
private final TikTokDataCollectorModel dataCollectorModel;
|
||||||
|
private final TikTokDatabase tikTokDatabase;
|
||||||
|
private final List<LiveClient> tiktokClients;
|
||||||
|
|
||||||
|
public TikTokDataCollector(TikTokDataCollectorModel dataCollectorModel, TikTokDatabase tikTokDatabase) {
|
||||||
|
this.dataCollectorModel = dataCollectorModel;
|
||||||
|
this.tikTokDatabase = tikTokDatabase;
|
||||||
|
this.tiktokClients = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
try {
|
||||||
|
if (!tikTokDatabase.isConnected()) {
|
||||||
|
tikTokDatabase.connect();
|
||||||
|
}
|
||||||
|
for (var user : dataCollectorModel.getUsers()) {
|
||||||
|
var client = createLiveClient(user);
|
||||||
|
tiktokClients.add(client);
|
||||||
|
client.connectAsync();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Unable to start tiktok connector", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
disconnect(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(boolean keepDatabase) {
|
||||||
|
try {
|
||||||
|
for (var client : tiktokClients) {
|
||||||
|
client.disconnect();
|
||||||
|
}
|
||||||
|
if (!keepDatabase) {
|
||||||
|
tikTokDatabase.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Unable to stop tiktok connector", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveClient createLiveClient(String tiktokUser) {
|
||||||
|
var builder = TikTokLive.newClient(tiktokUser);
|
||||||
|
builder.onConnected((liveClient, event) ->
|
||||||
|
{
|
||||||
|
liveClient.getLogger().info("Connected to " + liveClient.getRoomInfo().getHostName());
|
||||||
|
})
|
||||||
|
.onDisconnected((liveClient, event) ->
|
||||||
|
{
|
||||||
|
liveClient.getLogger().info("Disconnected " + liveClient.getRoomInfo().getHostName());
|
||||||
|
})
|
||||||
|
.onWebsocketResponse(this::handleResponseAndMessages)
|
||||||
|
.onWebsocketMessage(this::handleMappedEvent)
|
||||||
|
.onHttpResponse((liveClient, event) ->
|
||||||
|
{
|
||||||
|
var data = createHttpResponseData(event, tiktokUser);
|
||||||
|
tikTokDatabase.insertData(data);
|
||||||
|
})
|
||||||
|
.onError(this::handleError);
|
||||||
|
dataCollectorModel.getOnConfigureLiveClient().accept(builder);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleResponseAndMessages(LiveClient client, TikTokWebsocketResponseEvent event) {
|
||||||
|
var responseData = createResponseData(event.getResponse(), client.getRoomInfo().getHostName());
|
||||||
|
tikTokDatabase.insertData(responseData);
|
||||||
|
|
||||||
|
var filter = dataCollectorModel.getMessagesFilter();
|
||||||
|
for (var message : event.getResponse().getMessagesList()) {
|
||||||
|
if (filter.isEmpty()) {
|
||||||
|
var data = createMessageData(message, client.getRoomInfo().getHostName());
|
||||||
|
tikTokDatabase.insertData(data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!filter.contains(message.getMethod())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var data = createMessageData(message, client.getRoomInfo().getHostName());
|
||||||
|
tikTokDatabase.insertData(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleMappedEvent(LiveClient client, TikTokWebsocketMessageEvent messageEvent) {
|
||||||
|
var event = messageEvent.getEvent();
|
||||||
|
var eventName = event.getClass().getSimpleName();
|
||||||
|
|
||||||
|
var filter = dataCollectorModel.getEventsFilter();
|
||||||
|
|
||||||
|
if (filter.isEmpty()) {
|
||||||
|
var data = createEventData(event, client.getRoomInfo().getHostName());
|
||||||
|
tikTokDatabase.insertData(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filter.contains(eventName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = createEventData(event, client.getRoomInfo().getHostName());
|
||||||
|
tikTokDatabase.insertData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleError(LiveClient client, TikTokErrorEvent event) {
|
||||||
|
var exception = event.getException();
|
||||||
|
var userName = client.getRoomInfo().getHostName();
|
||||||
|
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
|
||||||
|
var errorModel = new TikTokErrorModel();
|
||||||
|
if (exception instanceof TikTokLiveMessageException ex) {
|
||||||
|
errorModel.setHostName(userName);
|
||||||
|
errorModel.setErrorName(ex.messageMethod());
|
||||||
|
errorModel.setErrorType("error-message");
|
||||||
|
errorModel.setExceptionContent(exceptionContent);
|
||||||
|
errorModel.setMessage(ex.messageToBase64());
|
||||||
|
errorModel.setResponse(ex.webcastResponseToBase64());
|
||||||
|
} else {
|
||||||
|
errorModel.setHostName(userName);
|
||||||
|
errorModel.setErrorName(exception.getClass().getSimpleName());
|
||||||
|
errorModel.setErrorType("error-system");
|
||||||
|
errorModel.setExceptionContent(exceptionContent);
|
||||||
|
errorModel.setMessage("");
|
||||||
|
errorModel.setResponse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tikTokDatabase.insertError(errorModel);
|
||||||
|
client.getLogger().info("ERROR: " + errorModel.getErrorName());
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TikTokDataTable createHttpResponseData(TikTokHttpResponseEvent response, String tiktokUser) {
|
||||||
|
var base64 = JsonUtil.toJson(response);
|
||||||
|
var data = new TikTokDataTable();
|
||||||
|
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||||
|
data.setTiktokUser(tiktokUser);
|
||||||
|
data.setDataType("response");
|
||||||
|
data.setDataTypeName("Http");
|
||||||
|
data.setContent(base64);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private TikTokDataTable createResponseData(WebcastResponse response, String tiktokUser) {
|
||||||
|
var base64 = Base64.getEncoder().encodeToString(response.toByteArray());
|
||||||
|
var data = new TikTokDataTable();
|
||||||
|
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||||
|
data.setTiktokUser(tiktokUser);
|
||||||
|
data.setDataType("response");
|
||||||
|
data.setDataTypeName("WebcastResponse");
|
||||||
|
data.setContent(base64);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TikTokDataTable createMessageData(WebcastResponse.Message message, String tiktokUser) {
|
||||||
|
var base64 = Base64.getEncoder().encodeToString(message.getPayload().toByteArray());
|
||||||
|
var data = new TikTokDataTable();
|
||||||
|
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||||
|
data.setTiktokUser(tiktokUser);
|
||||||
|
data.setDataType("message");
|
||||||
|
data.setDataTypeName(message.getMethod());
|
||||||
|
data.setContent(base64);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TikTokDataTable createEventData(TikTokEvent event, String tiktokUser) {
|
||||||
|
var base64 = JsonUtil.toJson(event);
|
||||||
|
var data = new TikTokDataTable();
|
||||||
|
data.setSessionTag(dataCollectorModel.getSessionTag());
|
||||||
|
data.setTiktokUser(tiktokUser);
|
||||||
|
data.setDataType("event");
|
||||||
|
data.setDataTypeName(event.getClass().getSimpleName());
|
||||||
|
data.setContent(base64);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* 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.client;
|
||||||
|
|
||||||
|
import com.google.protobuf.GeneratedMessageV3;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollectorBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.DataCollector;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.api.TikTokDataCollectorModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.TikTokDatabase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class TikTokDataCollectorBuilder implements DataCollectorBuilder {
|
||||||
|
|
||||||
|
|
||||||
|
TikTokDataCollectorModel dataModel;
|
||||||
|
|
||||||
|
TikTokDatabase database;
|
||||||
|
|
||||||
|
public TikTokDataCollectorBuilder(String outputName) {
|
||||||
|
|
||||||
|
dataModel = new TikTokDataCollectorModel();
|
||||||
|
dataModel.setOutputName(outputName);
|
||||||
|
dataModel.setUsers(new ArrayList<>());
|
||||||
|
dataModel.setEventsFilter(new HashSet<>());
|
||||||
|
dataModel.setMessagesFilter(new HashSet<>());
|
||||||
|
dataModel.setOutputPath("...");
|
||||||
|
dataModel.setOnConfigureLiveClient((e) -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollectorBuilder addUser(String user) {
|
||||||
|
dataModel.getUsers().add(user);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokDataCollectorBuilder addMessageFilter(Class<? extends GeneratedMessageV3> message) {
|
||||||
|
dataModel.getMessagesFilter().add(message.getSimpleName());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokDataCollectorBuilder addMessageFilter(String message) {
|
||||||
|
dataModel.getMessagesFilter().add(message);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokDataCollectorBuilder addEventFilter(Class<? extends TikTokEvent> event) {
|
||||||
|
dataModel.getEventsFilter().add(event.getSimpleName());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokDataCollectorBuilder addEventFilter(String event) {
|
||||||
|
dataModel.getEventsFilter().add(event);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollectorBuilder setOutputPath(String path) {
|
||||||
|
dataModel.setOutputPath(path);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollectorBuilder setSessionTag(String sessionTimestamp) {
|
||||||
|
dataModel.setSessionTag(sessionTimestamp);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollectorBuilder setDatabase(TikTokDatabase database)
|
||||||
|
{
|
||||||
|
this.database =database;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollectorBuilder configureLiveClient(Consumer<LiveClientBuilder> consumer) {
|
||||||
|
dataModel.setOnConfigureLiveClient(consumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollector buildAndRun() {
|
||||||
|
|
||||||
|
var collector = build();
|
||||||
|
collector.connect();
|
||||||
|
return collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataCollector build() {
|
||||||
|
|
||||||
|
if (dataModel.getSessionTag().isEmpty()) {
|
||||||
|
dataModel.setSessionTag(UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(database == null)
|
||||||
|
{
|
||||||
|
database = new TikTokDatabase(dataModel.getOutputName());
|
||||||
|
}
|
||||||
|
var dataCollector = new TikTokDataCollector(dataModel, database);
|
||||||
|
return dataCollector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,99 +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.collector.client;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
|
||||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class TikTokMessagessCollectorBuilder {
|
|
||||||
List<String> users;
|
|
||||||
String outputFileName;
|
|
||||||
List<Class<?>> filters;
|
|
||||||
Consumer<LiveClientBuilder> onBuilder;
|
|
||||||
List<LiveClient> tiktokclients;
|
|
||||||
|
|
||||||
MessageCollector messageCollector;
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder(String outputName) {
|
|
||||||
users = new ArrayList<>();
|
|
||||||
outputFileName = outputName;
|
|
||||||
filters = new ArrayList<>();
|
|
||||||
onBuilder = (e) -> {
|
|
||||||
};
|
|
||||||
tiktokclients = new ArrayList<>();
|
|
||||||
messageCollector = new MessageCollector(outputName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder(MessageCollector messageCollector, String outputFileName) {
|
|
||||||
this(outputFileName);
|
|
||||||
this.messageCollector = messageCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder setOutputName(String name) {
|
|
||||||
outputFileName = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addOnBuilder(Consumer<LiveClientBuilder> consumer) {
|
|
||||||
onBuilder = consumer;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addUser(String user) {
|
|
||||||
users.add(user);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TikTokMessagessCollectorBuilder addEventFilter(Class<?> event) {
|
|
||||||
filters.add(event);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageCollector buildAndRun() throws SQLException {
|
|
||||||
var db = new TikTokDatabase(outputFileName);
|
|
||||||
db.init();
|
|
||||||
var factory = new TikTokClientFactory(messageCollector, db);
|
|
||||||
for (var user : users) {
|
|
||||||
var client = factory.runClientAsync(user,filters, onBuilder);
|
|
||||||
client.thenAccept(liveClient ->
|
|
||||||
{
|
|
||||||
tiktokclients.add(liveClient);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return messageCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
for (var client : tiktokclients) {
|
|
||||||
client.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.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;
|
|
||||||
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TikTokDatabase {
|
|
||||||
private final String database;
|
|
||||||
private TikTokMessageModelDAO messagesTable;
|
|
||||||
private TikTokErrorModelDAO errorTable;
|
|
||||||
private TikTokResponseModelDAO responseTable;
|
|
||||||
|
|
||||||
public TikTokDatabase(String database) {
|
|
||||||
this.database = database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() throws SQLException {
|
|
||||||
var jdbcUrl = "jdbc:sqlite:" + database + ".db";
|
|
||||||
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) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
messagesTable.insertTikTokMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertError(TikTokErrorModel message) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
errorTable.insertTikTokMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertResponse(TikTokResponseModel message) {
|
|
||||||
message.setCreatedAt(getTime());
|
|
||||||
responseTable.insert(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TikTokErrorModel> selectErrors() {
|
|
||||||
return errorTable.selectErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +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.collector.db;
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
|
||||||
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(TikTokMessageModel.class)
|
|
||||||
public interface TikTokMessageModelDAO
|
|
||||||
{
|
|
||||||
@SqlUpdate("INSERT INTO TikTokMessageModel (hostName, eventName,type, eventContent, createdAt) " +
|
|
||||||
"VALUES (:hostName, :eventName, :type, :eventContent, :createdAt)")
|
|
||||||
void insertTikTokMessage(@BindBean TikTokMessageModel message);
|
|
||||||
|
|
||||||
@SqlQuery("SELECT * FROM TikTokMessageModel")
|
|
||||||
List<TikTokMessageModel> select();
|
|
||||||
}
|
|
||||||
@@ -20,17 +20,19 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.tools.db;
|
||||||
|
|
||||||
public class SqlConsts
|
public class SqlConsts
|
||||||
{
|
{
|
||||||
public static String CREATE_MESSAGES_TABLE = """
|
|
||||||
CREATE TABLE IF NOT EXISTS TikTokMessageModel (
|
public static String CREATE_DATA_TABLE = """
|
||||||
|
CREATE TABLE IF NOT EXISTS TikTokData (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
hostName TEXT,
|
sessionTag TEXT,
|
||||||
type TEXT,
|
tiktokUser TEXT,
|
||||||
eventName TEXT,
|
dataType TEXT,
|
||||||
eventContent TEXT,
|
dataTypeName TEXT,
|
||||||
|
content TEXT,
|
||||||
createdAt TEXT
|
createdAt TEXT
|
||||||
);
|
);
|
||||||
""";
|
""";
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.db;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||||
|
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||||
|
import org.jdbi.v3.sqlobject.customizer.Bind;
|
||||||
|
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;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RegisterBeanMapper(TikTokDataTable.class)
|
||||||
|
public interface TikTokDataTableDAO {
|
||||||
|
String query = """
|
||||||
|
INSERT INTO TikTokData (sessionTag, tiktokUser, dataType, dataTypeName, content, createdAt) VALUES (:sessionTag, :tiktokUser, :dataType, :dataTypeName, :content, :createdAt)
|
||||||
|
""";
|
||||||
|
|
||||||
|
@SqlUpdate(query)
|
||||||
|
void insertData(@BindBean TikTokDataTable data);
|
||||||
|
|
||||||
|
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag")
|
||||||
|
List<TikTokDataTable> selectBySession(@Bind("sessionTag") String sessionTag);
|
||||||
|
|
||||||
|
@SqlQuery("SELECT * FROM TikTokData WHERE dataType = :dataType AND sessionTag = :sessionTag AND tiktokUser = :tiktokUser")
|
||||||
|
List<TikTokDataTable> selectSessionData(@Bind("dataType") String dataType,
|
||||||
|
@Bind("sessionTag") String sessionTag,
|
||||||
|
@Bind("tiktokUser") String user);
|
||||||
|
|
||||||
|
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"response\"")
|
||||||
|
List<TikTokDataTable> selectResponces(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String user);
|
||||||
|
|
||||||
|
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"event\"")
|
||||||
|
List<TikTokDataTable> selectBySessionEvents(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String userName);
|
||||||
|
|
||||||
|
@SqlQuery("SELECT * FROM TikTokData WHERE sessionTag = :sessionTag AND tiktokUser = :tiktokUser AND dataType = \"message\"")
|
||||||
|
List<TikTokDataTable> selectBySessionMessages(@Bind("sessionTag") String sessionTag, @Bind("tiktokUser") String userName);
|
||||||
|
|
||||||
|
|
||||||
|
@SqlQuery("SELECT tiktokUser FROM TikTokData GROUP BY tiktokUser")
|
||||||
|
List<String> getUsers();
|
||||||
|
|
||||||
|
|
||||||
|
@SqlQuery("SELECT sessionTag FROM TikTokData WHERE tiktokUser = :tiktokUser GROUP BY sessionTag")
|
||||||
|
List<String> getSessionTagByUser(@Bind("tiktokUser") String tiktokUser);
|
||||||
|
|
||||||
|
String groupByDataTypeNameQuery = """
|
||||||
|
SELECT dataTypeName, COUNT(*) as count
|
||||||
|
FROM TikTokData
|
||||||
|
WHERE dataType = 'message' AND sessionTag = :sessionTag AND tiktokUser = :userName
|
||||||
|
GROUP BY dataTypeName
|
||||||
|
""";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* 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.db;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
|
||||||
|
import org.sqlite.SQLiteConfig;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TikTokDatabase {
|
||||||
|
private final String database;
|
||||||
|
|
||||||
|
private TikTokErrorModelDAO errorTable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private TikTokDataTableDAO dataTableDAO;
|
||||||
|
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
|
||||||
|
public TikTokDatabase(String database) {
|
||||||
|
this.database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected()
|
||||||
|
{
|
||||||
|
return connection != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() throws SQLException {
|
||||||
|
var jdbcUrl = "jdbc:sqlite:" + database + ".db";
|
||||||
|
var config = new SQLiteConfig();
|
||||||
|
config.setEncoding(SQLiteConfig.Encoding.UTF8);
|
||||||
|
connection = DriverManager.getConnection(jdbcUrl, config.toProperties());
|
||||||
|
var jdbi = Jdbi.create(jdbcUrl).installPlugin(new SqlObjectPlugin());
|
||||||
|
jdbi.useHandle(handle -> {
|
||||||
|
handle.execute(SqlConsts.CREATE_DATA_TABLE);
|
||||||
|
handle.execute(SqlConsts.CREATE_ERROR_TABLE);
|
||||||
|
});
|
||||||
|
dataTableDAO = jdbi.onDemand(TikTokDataTableDAO.class);
|
||||||
|
errorTable = jdbi.onDemand(TikTokErrorModelDAO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws SQLException {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertData(TikTokDataTable tikTokDataTable) {
|
||||||
|
tikTokDataTable.setCreatedAt(getTime());
|
||||||
|
dataTableDAO.insertData(tikTokDataTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TikTokDataTable> getSessionResponces(String sessionTag, String userName) {
|
||||||
|
return dataTableDAO.selectResponces(sessionTag, userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getDataNames(String dataType, String sessionTag, String userName) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.append("""
|
||||||
|
SELECT dataTypeName, COUNT(*) as count
|
||||||
|
FROM TikTokData
|
||||||
|
""");
|
||||||
|
sb.append(" WHERE dataType = \""+dataType+"\" ");
|
||||||
|
sb.append(" AND tiktokUser = \"" + userName + "\" ");
|
||||||
|
sb.append(" AND sessionTag = \"" + sessionTag + "\" ");
|
||||||
|
sb.append("GROUP BY dataTypeName");
|
||||||
|
var statement = connection.prepareStatement(sb.toString());
|
||||||
|
var resultSet = statement.executeQuery();
|
||||||
|
List<String> dataTypeCounts = new ArrayList<>();
|
||||||
|
while (resultSet.next()) {
|
||||||
|
var dataTypeName = resultSet.getString("dataTypeName");
|
||||||
|
dataTypeCounts.add(dataTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
resultSet.close();
|
||||||
|
statement.close();
|
||||||
|
|
||||||
|
return dataTypeCounts;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<TikTokDataTable> getSessionMessages(String sessionTag, String userName, int count) {
|
||||||
|
return dataTableDAO.selectBySessionMessages(sessionTag, userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertError(TikTokErrorModel message) {
|
||||||
|
message.setCreatedAt(getTime());
|
||||||
|
errorTable.insertTikTokMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<TikTokErrorModel> selectErrors() {
|
||||||
|
return errorTable.selectErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTime() {
|
||||||
|
return new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS").format(new Date());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
package io.github.jwdeveloper.tiktok.tools.db;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokErrorModel;
|
||||||
|
|
||||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@@ -20,23 +20,24 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TikTokMessageModel
|
public class TikTokDataTable
|
||||||
{
|
{
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
private String hostName;
|
private String sessionTag;
|
||||||
|
|
||||||
private String eventName;
|
private String tiktokUser;
|
||||||
|
|
||||||
private String type;
|
private String dataType;
|
||||||
|
|
||||||
private String message;
|
private String dataTypeName;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
|
||||||
private String createdAt;
|
private String createdAt;
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
package io.github.jwdeveloper.tiktok.tools.db.tables;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -1,77 +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 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.tools.util.MessageUtil;
|
|
||||||
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) ->
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("Unhandled Message! " );
|
|
||||||
sb.append(event.getData().getMethod());
|
|
||||||
sb.append(MessageUtil.getContent(event.getData()));
|
|
||||||
|
|
||||||
liveClient.getLogger().info(sb.toString());
|
|
||||||
})
|
|
||||||
.onWebsocketMessage((liveClient, event) ->
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append(event.getEvent().getClass().getSimpleName());
|
|
||||||
sb.append(event.getEvent().toJson());
|
|
||||||
liveClient.getLogger().fine(sb.toString());
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
client.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
package io.github.jwdeveloper.tiktok.tools.tester;
|
package io.github.jwdeveloper.tiktok.tools.tester;
|
||||||
|
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.TikTokClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.TikTokLiveMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.LiveClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||||
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
import io.github.jwdeveloper.tiktok.tools.util.MessageUtil;
|
||||||
|
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
@@ -37,7 +37,7 @@ public class RunJsonTester {
|
|||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
var messages = getMessages();
|
var messages = getMessages();
|
||||||
var client =(LiveClientMock) TikTokClientMock.create()
|
var client =(LiveClientMock) TikTokLiveMock.create()
|
||||||
.onWebsocketUnhandledMessage((liveClient, event) ->
|
.onWebsocketUnhandledMessage((liveClient, event) ->
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.tools.db.TikTokDatabase;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.db.tables.TikTokDataTable;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTester;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.TikTokLiveMock;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
public class TikTokDataTester implements DataTester {
|
||||||
|
private DataTesterModel model;
|
||||||
|
|
||||||
|
private LiveClientMock client;
|
||||||
|
|
||||||
|
private Queue<TikTokDataTable> data;
|
||||||
|
|
||||||
|
private TikTokDatabase database;
|
||||||
|
|
||||||
|
public TikTokDataTester(DataTesterModel model) {
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
database = new TikTokDatabase(model.getDatabaseName());
|
||||||
|
database.connect();
|
||||||
|
var mockBuilder = TikTokLiveMock.create();
|
||||||
|
model.getBuilderConsumer().accept(mockBuilder);
|
||||||
|
client = mockBuilder.build();
|
||||||
|
var respocnes = database.getSessionResponces(model.getSessionTag(), model.getUser());
|
||||||
|
data = new LinkedList<>(respocnes);
|
||||||
|
client.connect();
|
||||||
|
while (!data.isEmpty()) {
|
||||||
|
nextResponse();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while running tester", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextResponse() {
|
||||||
|
try {
|
||||||
|
var responce = data.poll();
|
||||||
|
client.publishResponse(responce.getContent());
|
||||||
|
Thread.sleep(1);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Unable to run response!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.disconnect();
|
||||||
|
database.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.live.builder.LiveClientBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTester;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterBuilder;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.tester.api.DataTesterModel;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class TikTokDataTesterBuilder implements DataTesterBuilder {
|
||||||
|
private final DataTesterModel model;
|
||||||
|
|
||||||
|
public TikTokDataTesterBuilder(String databaseName) {
|
||||||
|
this.model = new DataTesterModel();
|
||||||
|
this.model.setDatabaseName(databaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTesterBuilder setSessionTag(String sessionTag) {
|
||||||
|
model.setSessionTag(sessionTag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTesterBuilder setUser(String user) {
|
||||||
|
model.setUser(user);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTesterBuilder configureLiveClient(Consumer<LiveClientBuilder> builderConsumer) {
|
||||||
|
model.setBuilderConsumer(builderConsumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTester build() {
|
||||||
|
return new TikTokDataTester(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataTester buildAndRun()
|
||||||
|
{
|
||||||
|
var tester = build();
|
||||||
|
tester.connect();
|
||||||
|
return tester;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
public interface DataTester
|
||||||
|
{
|
||||||
|
void connect();
|
||||||
|
|
||||||
|
void nextResponse();
|
||||||
|
|
||||||
|
void disconnect();
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public interface DataTesterBuilder {
|
||||||
|
|
||||||
|
DataTesterBuilder setSessionTag(String sessionTag);
|
||||||
|
|
||||||
|
DataTesterBuilder setUser(String user);
|
||||||
|
|
||||||
|
DataTesterBuilder configureLiveClient(Consumer<LiveClientBuilder> builderConsumer);
|
||||||
|
|
||||||
|
DataTester build();
|
||||||
|
|
||||||
|
DataTester buildAndRun();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DataTesterModel {
|
||||||
|
|
||||||
|
|
||||||
|
String databaseName;
|
||||||
|
String sessionTag;
|
||||||
|
String user;
|
||||||
|
Consumer<LiveClientBuilder> builderConsumer = (a) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||||
|
|
||||||
public class TikTokClientMock
|
public class TikTokLiveMock
|
||||||
{
|
{
|
||||||
public static TikTokMockBuilder create(String host)
|
public static TikTokMockBuilder create(String host)
|
||||||
{
|
{
|
||||||
@@ -20,25 +20,22 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
import io.github.jwdeveloper.tiktok.TikTokRoomInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
|
import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver;
|
||||||
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandler;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokGiftEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokRoomInfoEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.mappers.events.TikTokSocialMediaEventHandler;
|
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||||
import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.ApiServiceMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.ApiServiceMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.LiveClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.LiveClientMock;
|
||||||
import io.github.jwdeveloper.tiktok.mockClient.mocks.WebsocketClientMock;
|
import io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks.WebsocketClientMock;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -96,7 +93,7 @@ public class TikTokMockBuilder extends TikTokLiveClientBuilder {
|
|||||||
|
|
||||||
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
var listenerManager = new TikTokListenersManager(listeners, tikTokEventHandler);
|
||||||
var giftManager = new TikTokGiftManager(logger);
|
var giftManager = new TikTokGiftManager(logger);
|
||||||
var requestFactory = new TikTokHttpRequestFactory(cookie);
|
var requestFactory = new TikTokHttpRequestFactory(cookie, new TikTokEventObserver());
|
||||||
var apiClient = new TikTokHttpClient(cookie, requestFactory);
|
var apiClient = new TikTokHttpClient(cookie, requestFactory);
|
||||||
var apiService = new ApiServiceMock(apiClient, logger, clientSettings);
|
var apiService = new ApiServiceMock(apiClient, logger, clientSettings);
|
||||||
var mapper = createMapper(giftManager, tiktokRoomInfo);
|
var mapper = createMapper(giftManager, tiktokRoomInfo);
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
import io.github.jwdeveloper.tiktok.http.TikTokApiService;
|
||||||
@@ -55,9 +55,4 @@ public class ApiServiceMock extends TikTokApiService {
|
|||||||
return WebcastResponse.newBuilder().build();
|
return WebcastResponse.newBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String fetchRoomId(String userName) {
|
|
||||||
return "mock-room-id";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||||
@@ -54,8 +54,11 @@ public class LiveClientMock extends TikTokLiveClient {
|
|||||||
listenersManager,
|
listenersManager,
|
||||||
logger);
|
logger);
|
||||||
this.websocketClientMock = webSocketClient;
|
this.websocketClientMock = webSocketClient;
|
||||||
|
websocketClientMock.setClient(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void publishMessage(String type, String base64) {
|
public void publishMessage(String type, String base64) {
|
||||||
websocketClientMock.addMessage(type, base64);
|
websocketClientMock.addMessage(type, base64);
|
||||||
}
|
}
|
||||||
@@ -75,5 +78,4 @@ public class LiveClientMock extends TikTokLiveClient {
|
|||||||
public void publishResponse(WebcastResponse message) {
|
public void publishResponse(WebcastResponse message) {
|
||||||
websocketClientMock.addResponse(message);
|
websocketClientMock.addResponse(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.mockClient.mocks;
|
package io.github.jwdeveloper.tiktok.tools.tester.mockClient.mocks;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
@@ -39,12 +39,19 @@ import java.util.logging.Logger;
|
|||||||
public class WebsocketClientMock implements SocketClient {
|
public class WebsocketClientMock implements SocketClient {
|
||||||
Logger logger;
|
Logger logger;
|
||||||
Stack<WebcastResponse> responses;
|
Stack<WebcastResponse> responses;
|
||||||
|
|
||||||
Stack<MsgStruct> messages;
|
Stack<MsgStruct> messages;
|
||||||
TikTokMessageHandler messageHandler;
|
TikTokMessageHandler messageHandler;
|
||||||
|
|
||||||
|
LiveClient client;
|
||||||
|
|
||||||
|
Thread thread;
|
||||||
|
|
||||||
private boolean isRunning;
|
private boolean isRunning;
|
||||||
|
|
||||||
|
public void setClient(LiveClientMock liveClientMock) {
|
||||||
|
this.client = liveClientMock;
|
||||||
|
}
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public static class MsgStruct {
|
public static class MsgStruct {
|
||||||
String messageType;
|
String messageType;
|
||||||
@@ -87,38 +94,28 @@ public class WebsocketClientMock implements SocketClient {
|
|||||||
@Override
|
@Override
|
||||||
public void start(WebcastResponse webcastResponse, LiveClient tikTokLiveClient) {
|
public void start(WebcastResponse webcastResponse, LiveClient tikTokLiveClient) {
|
||||||
logger.info("Running message: " + responses.size());
|
logger.info("Running message: " + responses.size());
|
||||||
isRunning = true;
|
|
||||||
while (!responses.isEmpty() || !messages.isEmpty()) {
|
|
||||||
if (!responses.isEmpty()) {
|
thread = new Thread(() ->
|
||||||
|
{
|
||||||
|
|
||||||
|
while (isRunning)
|
||||||
|
{
|
||||||
|
while (!responses.isEmpty()) {
|
||||||
var response = responses.pop();
|
var response = responses.pop();
|
||||||
for (var message : response.getMessagesList()) {
|
messageHandler.handle(client, response);
|
||||||
try {
|
|
||||||
messageHandler.handleSingleMessage(tikTokLiveClient, message);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Unable to parse message for response " + response.getCursor());
|
|
||||||
throw new TikTokLiveMessageException(message, response, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!messages.isEmpty()) {
|
|
||||||
var messageStr = messages.pop();
|
|
||||||
try {
|
|
||||||
var msg = WebcastResponse.Message.newBuilder()
|
|
||||||
.setMethod(messageStr.messageType)
|
|
||||||
.setPayload(ByteString.copyFrom(messageStr.getMessageValue()))
|
|
||||||
.build();
|
|
||||||
messageHandler.handleSingleMessage(tikTokLiveClient, msg);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.info("Unable to parse message for response " + messageStr.getMessageType());
|
|
||||||
throw new TikTokLiveException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
isRunning = true;
|
||||||
|
thread.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
isRunning = true;
|
isRunning = false;
|
||||||
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,16 +42,16 @@ public class MessageUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getContent(String methodName, byte[] bytes) {
|
public static String getContent(String messageName, byte[] bytes) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + methodName);
|
var inputClazz = Class.forName("io.github.jwdeveloper.tiktok.messages.webcast." + messageName);
|
||||||
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class);
|
var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class);
|
||||||
var deserialized = parseMethod.invoke(null, bytes);
|
var deserialized = parseMethod.invoke(null, bytes);
|
||||||
return JsonUtil.messageToJson(deserialized);
|
return JsonUtil.messageToJson(deserialized);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.append("Can not find protocolbuffer file message representation for " + methodName);
|
sb.append("Can not find protocol-buffer file message representation for " + messageName);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
var structure = ProtocolUtils.getProtocolBufferStructure(bytes);
|
||||||
var json =structure.toJson();
|
var json =structure.toJson();
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user