Compare commits

..

4 Commits

Author SHA1 Message Date
JW
b82c7184b3 Removed unused projects. 2024-03-01 01:52:54 +01:00
kohlerpop1
d3004d76c1 Merge remote-tracking branch 'origin/develop-1.5.0' into develop-1.5.0/messages-to-file 2024-02-28 12:27:05 -05:00
kohlerpop1
3ae73072ff Working on collecting to files! 2024-02-28 12:24:34 -05:00
Jacek W
9c5f97157a Merge pull request #61 from jwdeveloper/develop-1.5.0-remove-old-stuff
Develop 1.5.0 remove old stuff
2024-02-28 16:45:49 +01:00
12 changed files with 257 additions and 149 deletions

View File

@@ -40,12 +40,11 @@ public class CollectorExample {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
var collector = TikTokLiveCollector.use(settings -> var collector = TikTokLiveCollector.useMongo(settings ->
{ {
settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority"); settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority");
settings.setDatabaseName("tiktok");
}); });
collector.connectDatabase(); collector.connect();
var users = List.of("tehila_723", "dino123597", "domaxyzx", "dash4214", "obserwacje_live"); var users = List.of("tehila_723", "dino123597", "domaxyzx", "dash4214", "obserwacje_live");
Map<String, Object> additionalDataFields = Map.of("sessionTag", "ExampleTag"); Map<String, Object> additionalDataFields = Map.of("sessionTag", "ExampleTag");
@@ -71,6 +70,6 @@ public class CollectorExample {
} }
System.in.read(); System.in.read();
collector.disconnectDatabase(); collector.disconnect();
} }
} }

View File

@@ -22,19 +22,34 @@
*/ */
package io.github.jwdeveloper.tiktok.extension.collector; package io.github.jwdeveloper.tiktok.extension.collector;
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector; import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings;
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings; import io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo.MongoDataCollectorSettings;
import io.github.jwdeveloper.tiktok.extension.collector.impl.TikTokLiveDataCollector; import io.github.jwdeveloper.tiktok.extension.collector.impl.*;
import io.github.jwdeveloper.tiktok.extension.collector.impl.storages.FileStorage;
import io.github.jwdeveloper.tiktok.extension.collector.impl.storages.MongoStorage;
import java.util.function.Consumer; import java.util.function.Consumer;
/**
*
*/
public class TikTokLiveCollector public class TikTokLiveCollector
{ {
public static TikTokLiveDataCollector use(Consumer<LiveDataCollectorSettings> consumer) public static DataCollector useMongo(Consumer<MongoDataCollectorSettings> consumer) {
{ var settings = new MongoDataCollectorSettings();
var settings = new LiveDataCollectorSettings();
consumer.accept(settings); consumer.accept(settings);
return new TikTokLiveDataCollector(settings);
var storage = new MongoStorage(settings);
return new DataCollector(storage);
} }
}
public static DataCollector useFile(Consumer<FileDataCollectorSettings> consumer) {
var settings = new FileDataCollectorSettings();
consumer.accept(settings);
var storage = new FileStorage(settings);
return new DataCollector(storage);
}
}

View File

@@ -0,0 +1,11 @@
package io.github.jwdeveloper.tiktok.extension.collector.api;
import org.bson.Document;
public interface Storage {
void connect();
void disconnect();
void insert(Document document);
}

View File

@@ -1,4 +1,4 @@
package io.github.jwdeveloper.tiktok.extension.collector.api.data; package io.github.jwdeveloper.tiktok.extension.collector.api.settings;
import lombok.Data; import lombok.Data;
import org.bson.Document; import org.bson.Document;
@@ -10,4 +10,4 @@ import java.util.function.Function;
public class CollectorListenerSettings { public class CollectorListenerSettings {
private Map<String, Object> extraFields; private Map<String, Object> extraFields;
private Function<Document, Boolean> filter; private Function<Document, Boolean> filter;
} }

View File

@@ -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.extension.collector.api.settings;
import lombok.Data;
import java.io.File;
@Data
public class FileDataCollectorSettings {
private File parentFile;
}

View File

@@ -20,36 +20,21 @@
* 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.extension.collector.api.data; package io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo;
import lombok.Setter;
import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
public class MongoDBConnectionStringBuilder { public class MongoDBConnectionStringBuilder {
private String username; private String username;
private String password; private String password;
private String database; private String database;
private String cluster; private String cluster;
public MongoDBConnectionStringBuilder setUsername(String username) {
this.username = username;
return this;
}
public MongoDBConnectionStringBuilder setPassword(String password) {
this.password = password;
return this;
}
public MongoDBConnectionStringBuilder setDatabase(String database) {
this.database = database;
return this;
}
public MongoDBConnectionStringBuilder setCluster(String cluster) {
this.cluster = cluster;
return this;
}
public String build() { public String build() {
return String.format("mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority", return String.format("mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority",
username, password, cluster, database); username, password, cluster, database);
} }
} }

View File

@@ -20,29 +20,25 @@
* 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.extension.collector.api.data; package io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo;
import lombok.Data; import lombok.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@Data @Data
public class LiveDataCollectorSettings { public class MongoDataCollectorSettings {
@Setter
private String connectionUrl; private String connectionUrl;
private String databaseName; private String databaseName = "tiktok";
private String sessionTag; private String collectionName = "data";
public void connectionBuilder(Consumer<MongoDBConnectionStringBuilder> consumer) {
public void setConnectionUrl(String connectionUrl) {
this.connectionUrl = connectionUrl;
}
public void setConnectionUrl(Consumer<MongoDBConnectionStringBuilder> consumer) {
var builder = new MongoDBConnectionStringBuilder(); var builder = new MongoDBConnectionStringBuilder();
consumer.accept(builder); consumer.accept(builder);
connectionUrl = builder.build(); connectionUrl = builder.build();
} }
} }

View File

@@ -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.extension.collector.impl;
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings;
import org.bson.Document;
import java.util.Map;
import java.util.function.Function;
public class DataCollector {
private final Storage storage;
public DataCollector(Storage storage) {
this.storage = storage;
}
public void connect() {
storage.connect();
}
public void disconnect() {
storage.disconnect();
}
public DataCollectorListener newListener() {
return newListener(Map.of());
}
public DataCollectorListener newListener(Map<String, Object> additionalFields) {
return newListener(additionalFields, (e) -> true);
}
public DataCollectorListener newListener(Map<String, Object> additionalFields,
Function<Document, Boolean> filter) {
var settings = new CollectorListenerSettings();
settings.setExtraFields(additionalFields);
settings.setFilter(filter);
return new DataCollectorListener(storage, settings);
}
}

View File

@@ -1,6 +1,5 @@
package io.github.jwdeveloper.tiktok.extension.collector.impl; package io.github.jwdeveloper.tiktok.extension.collector.impl;
import com.mongodb.client.MongoCollection;
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver; import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
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;
@@ -8,7 +7,8 @@ import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent;
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector; import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector;
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings; import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.utils.JsonUtil; import io.github.jwdeveloper.tiktok.utils.JsonUtil;
@@ -19,15 +19,15 @@ import java.io.StringWriter;
import java.util.Base64; import java.util.Base64;
import java.util.UUID; import java.util.UUID;
public class TikTokLiveDataCollectorListener implements LiveDataCollector { public class DataCollectorListener implements LiveDataCollector {
private final MongoCollection<Document> collection; private final Storage storage;
private final CollectorListenerSettings settings; private final CollectorListenerSettings settings;
private String sessionId; private String sessionId;
private String userName; private String userName;
public TikTokLiveDataCollectorListener(MongoCollection<Document> collection, CollectorListenerSettings settings) { public DataCollectorListener(Storage collection, CollectorListenerSettings settings) {
this.collection = collection; this.storage = collection;
this.settings = settings; this.settings = settings;
} }
@@ -35,10 +35,7 @@ public class TikTokLiveDataCollectorListener implements LiveDataCollector {
@TikTokEventObserver @TikTokEventObserver
private void onResponse(LiveClient liveClient, TikTokWebsocketResponseEvent event) { private void onResponse(LiveClient liveClient, TikTokWebsocketResponseEvent event) {
includeResponse(liveClient, event.getResponse()); includeResponse(liveClient, event.getResponse());
event.getResponse().getMessagesList().forEach(message -> event.getResponse().getMessagesList().forEach(message -> includeMessage(liveClient, message));
{
includeMessage(liveClient, message);
});
} }
@TikTokEventObserver @TikTokEventObserver
@@ -103,7 +100,7 @@ public class TikTokLiveDataCollectorListener implements LiveDataCollector {
if (!settings.getFilter().apply(document)) { if (!settings.getFilter().apply(document)) {
return; return;
} }
collection.insertOne(document); storage.insert(document);
} }
@@ -119,4 +116,4 @@ public class TikTokLiveDataCollectorListener implements LiveDataCollector {
doc.append("content", content); doc.append("content", content);
return doc; return doc;
} }
} }

View File

@@ -1,89 +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.extension.collector.impl;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.ServerApi;
import com.mongodb.ServerApiVersion;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Indexes;
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings;
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings;
import org.bson.Document;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
public class TikTokLiveDataCollector {
private final LiveDataCollectorSettings settings;
private MongoClient mongoClient;
private MongoDatabase database;
private MongoCollection<Document> collection;
public TikTokLiveDataCollector(LiveDataCollectorSettings settings) {
this.settings = settings;
}
public void connectDatabase() {
var serverApi = ServerApi.builder()
.version(ServerApiVersion.V1)
.build();
var mongoSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(settings.getConnectionUrl()))
.serverApi(serverApi)
.build();
mongoClient = MongoClients.create(mongoSettings);
database = mongoClient.getDatabase(settings.getDatabaseName());
collection = database.getCollection("data");
collection.createIndex(Indexes.hashed("session"));
collection.createIndex(Indexes.hashed("dataType"));
}
public void disconnectDatabase() {
mongoClient.close();
}
public TikTokLiveDataCollectorListener newListener() {
return newListener(Map.of());
}
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields) {
return newListener(additionalFields, (e)->true);
}
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields,
Function<Document, Boolean> filter) {
var settings = new CollectorListenerSettings();
settings.setExtraFields(additionalFields);
settings.setFilter(filter);
return new TikTokLiveDataCollectorListener(collection, settings);
}
}

View File

@@ -0,0 +1,41 @@
package io.github.jwdeveloper.tiktok.extension.collector.impl.storages;
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings;
import org.bson.Document;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
public class FileStorage implements Storage {
private final FileDataCollectorSettings settings;
public FileStorage(FileDataCollectorSettings fileDataCollectorSettings) {
this.settings = fileDataCollectorSettings;
}
@Override
public void connect() {
}
@Override
public void disconnect() {
}
@Override
public void insert(Document document) {
var fileName = document.get("dataType") + ":" + document.get("dataTypeName") + ".json";
try {
var file = new File(settings.getParentFile(), fileName);
file.createNewFile();
Files.writeString(file.toPath(), document.toJson(), StandardOpenOption.APPEND);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,58 @@
package io.github.jwdeveloper.tiktok.extension.collector.impl.storages;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.ServerApi;
import com.mongodb.ServerApiVersion;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Indexes;
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.mongo.MongoDataCollectorSettings;
import org.bson.Document;
public class MongoStorage implements Storage {
private MongoClient mongoClient;
private MongoDatabase database;
private MongoCollection<Document> collection;
private final MongoDataCollectorSettings settings;
public MongoStorage(MongoDataCollectorSettings settings) {
this.settings = settings;
}
@Override
public void connect() {
var serverApi = ServerApi.builder()
.version(ServerApiVersion.V1)
.build();
var mongoSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(settings.getConnectionUrl()))
.serverApi(serverApi)
.build();
mongoClient = MongoClients.create(mongoSettings);
database = mongoClient.getDatabase(settings.getDatabaseName());
collection = database.getCollection(settings.getCollectionName());
collection.createIndex(Indexes.hashed("session"));
collection.createIndex(Indexes.hashed("dataType"));
}
@Override
public void disconnect() {
if (mongoClient == null) {
return;
}
mongoClient.close();
}
@Override
public void insert(Document document) {
collection.insertOne(document);
}
}