Compare commits
40 Commits
Author | SHA1 | Date |
---|---|---|
|
ceceb4dd6e | |
|
1c1066d399 | |
|
a4984b02f1 | |
|
98d6ece1a6 | |
|
b1e1f9b2c7 | |
|
45434afd96 | |
|
2a0a3ad4a6 | |
|
e7aae593cc | |
|
2622305951 | |
|
41ddc25cc9 | |
|
809325ebac | |
|
e58f491887 | |
|
ec4e5e9ba2 | |
|
819c80ca30 | |
|
674a84dcb0 | |
|
733cdc6da4 | |
|
f59bf26d54 | |
|
6dbbde9d80 | |
|
6aec3a2354 | |
|
4cf096ff1a | |
|
9c1cd6b073 | |
|
bb91a319c4 | |
|
0dc8bbc870 | |
|
3f1a8f5b0a | |
|
bb9e679970 | |
|
3f4ae44bae | |
|
daa192c42b | |
|
c47d7f7077 | |
|
d747e4cf7a | |
|
4753ad2eb4 | |
|
713b95d05b | |
|
1a51c1b1bb | |
|
9b0acfa1a2 | |
|
226a8316e2 | |
|
f49f2dae43 | |
|
ad386bd5df | |
|
9a5a469ad0 | |
|
7a1d0ae197 | |
|
a92c8b7753 | |
|
20ebde9b73 |
|
@ -7,3 +7,4 @@
|
|||
.project
|
||||
*/.factorypath
|
||||
**/.antlr/
|
||||
*.code-workspace
|
||||
|
|
|
@ -19,7 +19,8 @@ Support me:<br>
|
|||
|
||||
Bitcoin: bc1q7fvtkx8wklvd4zttsec7sfgxqh9zadk0x236lt <br>
|
||||
Ether: 0x2e687A5628ff16c8f9624A914C1f727000089C3A <br>
|
||||
Solana: Z5YwNPkLheSHuaSJjyHhg3L8UxjpJPt5WU6vu4hFsNR
|
||||
Solana: Z5YwNPkLheSHuaSJjyHhg3L8UxjpJPt5WU6vu4hFsNR <br>
|
||||
Monero: 47tjD1z63wu3FEnDCvWnFaRAZbpDKc3Ys1WCbgzvB2Gg8XbqU8bARpcCC37mWzuWBAeZPu2UGY4TAcYGhb6fptoTR8X9vjc
|
||||
|
||||
|
||||
## A free recording software for different camsites. Currently supported: BongaCams, Cam4, CamSoda, Chaturbate, FC2Live, LiveJasmin, MyFreeCams, Streamate
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<parent>
|
||||
<groupId>ctbrec</groupId>
|
||||
<artifactId>master</artifactId>
|
||||
<version>5.3.3</version>
|
||||
<version>5.3.4</version>
|
||||
<relativePath>../master</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -268,7 +268,8 @@ public class CamrecApplication extends Application {
|
|||
tabPane.getTabs().add(new RecentlyWatchedTab(recorder, sites));
|
||||
}
|
||||
tabPane.getTabs().add(new SettingsTab(sites, recorder));
|
||||
tabPane.getTabs().add(new NewsTab(config));
|
||||
//tabPane.getTabs().add(new NewsTab(config));
|
||||
tabPane.getTabs().add(new NewsTab(config, getHostServices()));
|
||||
tabPane.getTabs().add(new DonateTabFx());
|
||||
tabPane.getTabs().add(new HelpTab());
|
||||
tabPane.getTabs().add(new LoggingTab());
|
||||
|
|
|
@ -6,17 +6,22 @@ import ctbrec.GlobalThreadPool;
|
|||
import ctbrec.Version;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.io.json.ObjectMapperFactory;
|
||||
import ctbrec.ui.CamrecApplication;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import ctbrec.ui.tabs.TabSelectionListener;
|
||||
import javafx.application.HostServices;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.layout.VBox;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -27,16 +32,17 @@ import static ctbrec.io.HttpConstants.USER_AGENT;
|
|||
|
||||
@Slf4j
|
||||
public class NewsTab extends Tab implements TabSelectionListener {
|
||||
private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0";
|
||||
private static final String URL = "https://mastodon.cloud/api/v1/accounts/480960/statuses?limit=20&exclude_replies=true";
|
||||
private static final String URL = "https://git.ctbrec.com/api/v1/repos/j62/ctbrec/releases";
|
||||
private final Config config;
|
||||
private final HostServices hostServices;
|
||||
private final VBox layout = new VBox();
|
||||
|
||||
private final ObjectMapper mapper = ObjectMapperFactory.getMapper();
|
||||
private final OkHttpClient httpClient = new OkHttpClient();
|
||||
|
||||
public NewsTab(Config config) {
|
||||
public NewsTab(Config config, HostServices hostServices) {
|
||||
this.config = config;
|
||||
setText("News");
|
||||
this.hostServices = hostServices;
|
||||
setText("Releases");
|
||||
layout.setMaxWidth(800);
|
||||
layout.setAlignment(Pos.CENTER);
|
||||
setContent(new ScrollPane(layout));
|
||||
|
@ -44,24 +50,21 @@ public class NewsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
@Override
|
||||
public void selected() {
|
||||
GlobalThreadPool.submit(this::loadToots);
|
||||
GlobalThreadPool.submit(this::loadReleases);
|
||||
}
|
||||
|
||||
private void loadToots() {
|
||||
private void loadReleases() {
|
||||
try {
|
||||
var request = new Request.Builder()
|
||||
.url(URL)
|
||||
.header("Authorization", "Bearer " + ACCESS_TOKEN)
|
||||
.header(USER_AGENT, "ctbrec " + Version.getVersion())
|
||||
.build();
|
||||
try (var response = CamrecApplication.httpClient.execute(request)) {
|
||||
try (Response response = httpClient.newCall(request).execute()) {
|
||||
if (response.isSuccessful()) {
|
||||
var body = Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string();
|
||||
log.debug(body);
|
||||
if (body.startsWith("[")) {
|
||||
onSuccess(body);
|
||||
} else if (body.startsWith("{")) {
|
||||
onError(body);
|
||||
} else {
|
||||
throw new IOException("Unexpected response: " + body);
|
||||
}
|
||||
|
@ -70,30 +73,53 @@ public class NewsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.info("Error while loading news", e);
|
||||
Dialogs.showError(getTabPane().getScene(), "News", "Couldn't load news from mastodon", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void onError(String body) throws IOException {
|
||||
var json = new JSONObject(body);
|
||||
if (json.has("error")) {
|
||||
throw new IOException("Request not successful: " + json.getString("error"));
|
||||
} else {
|
||||
throw new IOException("Unexpected response: " + body);
|
||||
log.info("Error while loading releases", e);
|
||||
Dialogs.showError(getTabPane().getScene(), "Releases", "Couldn't load release information", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSuccess(String body) throws IOException {
|
||||
Status[] statusArray = mapper.readValue(body, Status[].class);
|
||||
JSONArray releases = new JSONArray(body);
|
||||
Platform.runLater(() -> {
|
||||
layout.getChildren().clear();
|
||||
for (Status status : statusArray) {
|
||||
if (status.getInReplyToId() == null && !Objects.equals("direct", status.getVisibility())) {
|
||||
var stp = new StatusPane(status, config.getDateTimeFormatter());
|
||||
layout.getChildren().add(stp);
|
||||
VBox.setMargin(stp, new Insets(10));
|
||||
for (int i = 0; i < releases.length(); i++) {
|
||||
JSONObject release = releases.getJSONObject(i);
|
||||
String tagName = release.optString("tag_name", "Unknown Version");
|
||||
String releaseName = release.optString("name", "No Name");
|
||||
String description = release.optString("body", "No description available.");
|
||||
JSONArray assets = release.optJSONArray("assets");
|
||||
|
||||
var releasePane = new VBox();
|
||||
releasePane.setPadding(new Insets(10));
|
||||
releasePane.setSpacing(5);
|
||||
|
||||
Label versionLabel = new Label("Version: " + tagName);
|
||||
versionLabel.setStyle("-fx-font-weight: bold;");
|
||||
|
||||
Label nameLabel = new Label("Release: " + releaseName);
|
||||
Label descLabel = new Label(description);
|
||||
|
||||
releasePane.getChildren().addAll(versionLabel, nameLabel, descLabel);
|
||||
|
||||
if (assets != null) {
|
||||
Label assetsLabel = new Label("Assets:");
|
||||
releasePane.getChildren().add(assetsLabel);
|
||||
for (int j = 0; j < assets.length(); j++) {
|
||||
JSONObject asset = assets.getJSONObject(j);
|
||||
String assetName = asset.optString("name", "Unknown File");
|
||||
String downloadUrl = asset.optString("browser_download_url", "#");
|
||||
int size = asset.optInt("size", 0);
|
||||
int downloads = asset.optInt("download_count", 0);
|
||||
|
||||
Hyperlink assetLink = new Hyperlink(assetName + " (" + size / 1024 / 1024 + " MB, " + downloads + " downloads)");
|
||||
assetLink.setOnAction(event -> hostServices.showDocument(downloadUrl));
|
||||
|
||||
releasePane.getChildren().add(assetLink);
|
||||
}
|
||||
}
|
||||
|
||||
layout.getChildren().add(releasePane);
|
||||
VBox.setMargin(releasePane, new Insets(10));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import ctbrec.Settings.ProxyType;
|
|||
import ctbrec.docs.DocServer;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.SiteUI;
|
||||
import ctbrec.ui.SiteUiFactory;
|
||||
|
@ -16,6 +17,8 @@ import ctbrec.ui.controls.range.DiscreteRange;
|
|||
import ctbrec.ui.settings.api.*;
|
||||
import ctbrec.ui.sites.ConfigUI;
|
||||
import ctbrec.ui.tabs.TabSelectionListener;
|
||||
import ctbrec.ui.tabs.ThumbOverviewTab;
|
||||
import ctbrec.ui.sites.chaturbate.ChaturbateTabProvider;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.animation.Transition;
|
||||
|
@ -30,13 +33,16 @@ import javafx.scene.control.Button;
|
|||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TextInputDialog;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
import javafx.scene.Parent;
|
||||
import lombok.Getter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -70,6 +76,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
private SimpleBooleanProperty determineResolution;
|
||||
private SimpleBooleanProperty chooseStreamQuality;
|
||||
private SimpleBooleanProperty confirmationDialogs;
|
||||
private SimpleBooleanProperty naCamsOnly;
|
||||
private SimpleBooleanProperty livePreviews;
|
||||
private SimpleBooleanProperty monitorClipboard;
|
||||
private SimpleListProperty<String> startTab;
|
||||
|
@ -152,7 +159,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
private void initializeProperties() {
|
||||
flaresolverrApiUrl = new SimpleStringProperty(null, "flaresolverr.apiUrl", settings.flaresolverr.apiUrl);
|
||||
flaresolverrTimeoutInMillis = new SimpleIntegerProperty(null, "flaresolverr.timeoutInMillis", settings.flaresolverr.timeoutInMillis);
|
||||
flaresolverrUseForDomains = new SimpleJoinedStringListProperty(null, "flaresolverr.useForDomains", "\n",
|
||||
flaresolverrUseForDomains = new SimpleJoinedStringListProperty(null, "flaresolverr.useForDomains", "\n",
|
||||
FXCollections.observableList(settings.flaresolverr.useForDomains));
|
||||
httpUserAgent = new SimpleStringProperty(null, "httpUserAgent", settings.httpUserAgent);
|
||||
httpUserAgentMobile = new SimpleStringProperty(null, "httpUserAgentMobile", settings.httpUserAgentMobile);
|
||||
|
@ -207,6 +214,14 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
onlineCheckSkipsPausedModels = new SimpleBooleanProperty(null, "onlineCheckSkipsPausedModels", settings.onlineCheckSkipsPausedModels);
|
||||
fastScrollSpeed = new SimpleBooleanProperty(null, "fastScrollSpeed", settings.fastScrollSpeed);
|
||||
confirmationDialogs = new SimpleBooleanProperty(null, "confirmationForDangerousActions", settings.confirmationForDangerousActions);
|
||||
naCamsOnly = new SimpleBooleanProperty(null, "filterNAcamsOnly", settings.filterNAcamsOnly);
|
||||
naCamsOnly.addListener((obs, oldValue, newValue) -> {
|
||||
settings.filterNAcamsOnly = newValue;
|
||||
Config.getInstance().getSettings().filterNAcamsOnly = newValue; // Ensure the config is updated
|
||||
saveConfig();
|
||||
refreshChaturbateTabs(); // Refresh tabs when the setting changes
|
||||
});
|
||||
|
||||
useHlsdl = new SimpleBooleanProperty(null, "useHlsdl", settings.useHlsdl);
|
||||
hlsdlExecutable = new SimpleFileProperty(null, "hlsdlExecutable", settings.hlsdlExecutable);
|
||||
recentlyWatched = new SimpleBooleanProperty(null, "recentlyWatched", settings.recentlyWatched);
|
||||
|
@ -230,6 +245,48 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
httpClientMaxRequestsPerHost = new SimpleIntegerProperty(null, "httpClientMaxRequestsPerHost", settings.httpClientMaxRequestsPerHost);
|
||||
}
|
||||
|
||||
private void refreshChaturbateTabs() {
|
||||
System.out.println("Refreshing Chaturbate Tabs..."); // Debugging output
|
||||
|
||||
// Find the Chaturbate tab
|
||||
Tab chaturbateTab = null;
|
||||
for (Tab tab : getTabPane().getTabs()) {
|
||||
if (tab.getText().equalsIgnoreCase("Chaturbate")) {
|
||||
chaturbateTab = tab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chaturbateTab == null) {
|
||||
System.out.println("Chaturbate tab not found! Cannot refresh.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (chaturbateTab instanceof ThumbOverviewTab overviewTab) {
|
||||
overviewTab.getUpdateService().reset(); // Reset update service for new URLs
|
||||
}
|
||||
|
||||
// Get the tab container inside the Chaturbate tab
|
||||
if (chaturbateTab.getContent() instanceof Parent parent) {
|
||||
var chaturbateTabsContainer = parent.lookup(".tab-pane");
|
||||
if (chaturbateTabsContainer instanceof TabPane chaturbateTabPane) {
|
||||
// Remove all existing Chaturbate sub-tabs
|
||||
chaturbateTabPane.getTabs().clear();
|
||||
|
||||
// Get updated Chaturbate tabs and add them inside the Chaturbate section
|
||||
var newTabs = SiteUiFactory.getUi(new Chaturbate()).getTabProvider().getTabs(getTabPane().getScene());
|
||||
chaturbateTabPane.getTabs().addAll(newTabs);
|
||||
|
||||
System.out.println("Chaturbate tabs refreshed!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Could not find the correct TabPane inside Chaturbate tab!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void createGui() {
|
||||
var postProcessingStepPanel = new PostProcessingStepPanel(config);
|
||||
var variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables");
|
||||
|
@ -257,6 +314,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Setting.of("Start minimized", startMinimized, "Start the app minimized to the tray, automatically activates \"Minimize to tray\""),
|
||||
Setting.of("Add models from clipboard", monitorClipboard, "Monitor clipboard for model URLs and automatically add them to the recorder").needsRestart(),
|
||||
Setting.of("Show confirmation dialogs", confirmationDialogs, "Show confirmation dialogs for irreversible actions"),
|
||||
Setting.of("Show only North America Cams", naCamsOnly, "Show only North America Cams").needsRestart(),
|
||||
Setting.of("Recording tab per site", recordedModelsPerSite, "Add a Recording tab for each site").needsRestart(),
|
||||
Setting.of("Check for new versions at startup", checkForUpdates, "Search for updates every startup"),
|
||||
Setting.of("Start Tab", startTab)),
|
||||
|
@ -272,7 +330,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Setting.of("Browser", browserOverride),
|
||||
Setting.of("Start parameters", browserParams),
|
||||
Setting.of("Force use (ignore default browser)", forceBrowserOverride, "Default behaviour will fallback to OS default if the above browser fails")),
|
||||
|
||||
|
||||
Group.of("Flaresolverr",
|
||||
Setting.of("API URL", flaresolverrApiUrl),
|
||||
Setting.of("Request timeout", flaresolverrTimeoutInMillis),
|
||||
|
@ -343,11 +401,11 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Category.of("Advanced / Devtools",
|
||||
Group.of("Networking",
|
||||
Setting.of("Playlist request timeout (ms)", playlistRequestTimeout, "Timeout in ms for playlist requests"),
|
||||
Setting.of("Max requests", httpClientMaxRequests,
|
||||
Setting.of("Max requests", httpClientMaxRequests,
|
||||
"The maximum number of requests to execute concurrently. Above this requests queue in memory,\n" + //
|
||||
"waiting for the running calls to complete.\n\n" + //
|
||||
"If more than [maxRequests] requests are in flight when this is invoked, those requests will remain in flight."),
|
||||
Setting.of("Max requests per host", httpClientMaxRequestsPerHost,
|
||||
Setting.of("Max requests per host", httpClientMaxRequestsPerHost,
|
||||
"The maximum number of requests for each host to execute concurrently. This limits requests by\n" + //
|
||||
"the URL's host name. Note that concurrent requests to a single IP address may still exceed this\n" + //
|
||||
"limit: multiple hostnames may share an IP address or be routed through the same HTTP proxy.\n\n" + //
|
||||
|
@ -363,7 +421,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Setting.of("hlsdl executable", hlsdlExecutable, "Path to the hlsdl executable"),
|
||||
Setting.of("Log hlsdl output", loghlsdlOutput, "Log hlsdl output to files in the system's temp directory")),
|
||||
Group.of("Miscelaneous",
|
||||
Setting.of("Config file saving delay (ms)", configSavingDelayMs,
|
||||
Setting.of("Config file saving delay (ms)", configSavingDelayMs,
|
||||
"Wait specified number of milliseconds before actually writing config to disk"))));
|
||||
Region preferencesView = prefs.getView();
|
||||
prefs.onRestartRequired(this::showRestartRequired);
|
||||
|
@ -667,7 +725,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
private static final String DATE_FORMATTER_TOOLTIP = """
|
||||
Leave empty for system default
|
||||
|
||||
|
||||
Symbol Meaning Presentation Examples
|
||||
------ ------- ------------ -------
|
||||
G era text AD; Anno Domini; A
|
||||
|
@ -676,7 +734,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
D day-of-year number 189
|
||||
M/L month-of-year number/text 7; 07; Jul; July; J
|
||||
d day-of-month number 10
|
||||
|
||||
|
||||
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
|
||||
Y week-based-year year 1996; 96
|
||||
w week-of-week-based-year number 27
|
||||
|
@ -684,12 +742,12 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
E day-of-week text Tue; Tuesday; T
|
||||
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
|
||||
F week-of-month number 3
|
||||
|
||||
|
||||
a am-pm-of-day text PM
|
||||
h clock-hour-of-am-pm (1-12) number 12
|
||||
K hour-of-am-pm (0-11) number 0
|
||||
k clock-hour-of-am-pm (1-24) number 0
|
||||
|
||||
|
||||
H hour-of-day (0-23) number 0
|
||||
m minute-of-hour number 30
|
||||
s second-of-minute number 55
|
||||
|
@ -697,16 +755,16 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
A milli-of-day number 1234
|
||||
n nano-of-second number 987654321
|
||||
N nano-of-day number 1234000000
|
||||
|
||||
|
||||
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
|
||||
z time-zone name zone-name Pacific Standard Time; PST
|
||||
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
|
||||
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
|
||||
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
|
||||
Z zone-offset offset-Z +0000; -0800; -08:00;
|
||||
|
||||
|
||||
p pad next pad modifier 1
|
||||
|
||||
|
||||
' escape for text delimiter
|
||||
'' single quote literal '
|
||||
[ optional section start
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ctbrec.ui.sites.chaturbate;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.ui.sites.AbstractTabProvider;
|
||||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
|
@ -14,32 +15,47 @@ public class ChaturbateTabProvider extends AbstractTabProvider {
|
|||
|
||||
private final String apiUrl;
|
||||
private final ChaturbateFollowedTab followedTab;
|
||||
private final boolean regionNAEnabled; // Store the setting
|
||||
|
||||
public ChaturbateTabProvider(Chaturbate chaturbate) {
|
||||
super(chaturbate);
|
||||
apiUrl = site.getBaseUrl() + "/api/ts";
|
||||
this.followedTab = new ChaturbateFollowedTab("Followed", apiUrl + "/roomlist/room-list/?enable_recommendations=false&follow=true", chaturbate);
|
||||
regionNAEnabled = Config.getInstance().isFilterNAcamsOnlyEnabled();
|
||||
this.followedTab = new ChaturbateFollowedTab("Followed", buildUrl("/roomlist/room-list/?enable_recommendations=false&follow=true"), chaturbate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Tab> getSiteTabs(Scene scene) {
|
||||
List<Tab> tabs = new ArrayList<>();
|
||||
tabs.add(createTab("Featured", apiUrl + "/roomlist/room-list/?enable_recommendations=false"));
|
||||
tabs.add(createTab("Female", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=f"));
|
||||
tabs.add(createTab("New Female", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=f&new_cams=true"));
|
||||
tabs.add(createTab("Male", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=m"));
|
||||
tabs.add(createTab("New Male", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=m&new_cams=true"));
|
||||
tabs.add(createTab("Couples", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=c"));
|
||||
tabs.add(createTab("Trans", apiUrl + "/roomlist/room-list/?enable_recommendations=false&genders=t"));
|
||||
tabs.add(createTab("Private", apiUrl + "/roomlist/room-list/?enable_recommendations=false&private=true"));
|
||||
tabs.add(createTab("Hidden", apiUrl + "/roomlist/room-list/?enable_recommendations=false&hidden=true"));
|
||||
tabs.add(createTab("Gaming", apiUrl + "/roomlist/room-list/?enable_recommendations=false&gaming=true"));
|
||||
tabs.add(createTab("Featured", buildUrl("/roomlist/room-list/?enable_recommendations=false")));
|
||||
tabs.add(createTab("Female", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=f")));
|
||||
tabs.add(createTab("New Female", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=f&new_cams=true")));
|
||||
tabs.add(createTab("Milf", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=milf")));
|
||||
tabs.add(createTab("Teen", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=teen")));
|
||||
tabs.add(createTab("Creampie", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=creampie")));
|
||||
tabs.add(createTab("BBW", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=bbw")));
|
||||
tabs.add(createTab("Chubby", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=chubby")));
|
||||
tabs.add(createTab("Pregnant", buildUrl("/roomlist/room-list/?enable_recommendations=false&hashtags=pregnant")));
|
||||
tabs.add(createTab("Male", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=m")));
|
||||
tabs.add(createTab("New Male", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=m&new_cams=true")));
|
||||
tabs.add(createTab("Couples", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=c")));
|
||||
tabs.add(createTab("Trans", buildUrl("/roomlist/room-list/?enable_recommendations=false&genders=t")));
|
||||
tabs.add(createTab("N.American Cams", buildUrl("/roomlist/room-list/?enable_recommendations=false®ions=NA")));
|
||||
tabs.add(createTab("6TPM private", buildUrl("/roomlist/room-list/?enable_recommendations=false&private_prices=6")));
|
||||
tabs.add(createTab("Private", buildUrl("/roomlist/room-list/?enable_recommendations=false&private=true")));
|
||||
tabs.add(createTab("Hidden", buildUrl("/roomlist/room-list/?enable_recommendations=false&hidden=true")));
|
||||
tabs.add(createTab("Gaming", buildUrl("/roomlist/room-list/?enable_recommendations=false&gaming=true")));
|
||||
|
||||
followedTab.setScene(scene);
|
||||
followedTab.setRecorder(recorder);
|
||||
followedTab.setImageAspectRatio(9.0 / 16.0);
|
||||
tabs.add(followedTab);
|
||||
|
||||
//tabs.add(createApiTab("Top Rated", buildUrl("/discover/carousels/top-rated/")));
|
||||
//tabs.add(createApiTab("Trending", buildUrl("/discover/carousels/trending/")));
|
||||
tabs.add(createApiTab("Top Rated", apiUrl + "/discover/carousels/top-rated/"));
|
||||
tabs.add(createApiTab("Trending", apiUrl + "/discover/carousels/trending/"));
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
|
@ -64,4 +80,29 @@ public class ChaturbateTabProvider extends AbstractTabProvider {
|
|||
var updateService = new ChaturbateApiUpdateService(apiUrl, (Chaturbate) site);
|
||||
return createTab(title, updateService);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildUrl(String endpoint) {
|
||||
boolean filterNA = Config.getInstance().getSettings().filterNAcamsOnly; // Always check latest setting
|
||||
|
||||
// Do NOT modify "N.American Cams" - it should always have ®ions=NA
|
||||
if (endpoint.contains("®ions=NA")) {
|
||||
return apiUrl + endpoint; // Keep it unchanged
|
||||
}
|
||||
|
||||
// Ensure Top Rated & Trending use ? instead of &
|
||||
if (filterNA && endpoint.contains("discover/carousels")) {
|
||||
endpoint += "?regions=NA"; // Use ? instead of &
|
||||
}
|
||||
// For all other tabs (except N.American Cams), append ®ions=NA if enabled
|
||||
else if (filterNA) {
|
||||
endpoint += "®ions=NA";
|
||||
}
|
||||
|
||||
String url = apiUrl + endpoint;
|
||||
System.out.println("Building URL: " + url); // Debugging output
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -24,9 +24,9 @@ public class DonateTabFx extends Tab {
|
|||
|
||||
var headerVbox = new VBox(10);
|
||||
headerVbox.setAlignment(Pos.CENTER);
|
||||
var beer = new Label("Buy me some beer?!");
|
||||
var beer = new Label("Buy me a drink?!");
|
||||
beer.setFont(new Font(36));
|
||||
var desc = new Label("If you like this software and want to buy me some beer or pizza, here are some possibilities!");
|
||||
var desc = new Label("If you like this software and want to buy me some MtDew or Energy Drinks(boost ctbrec dev productivity! :), Beer or Pizza, here are some possibilities!");
|
||||
desc.setFont(new Font(24));
|
||||
headerVbox.getChildren().addAll(beer, desc);
|
||||
var header = new HBox();
|
||||
|
|
|
@ -773,6 +773,9 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
|||
popoverTreeList.setRecorder(recorder);
|
||||
}
|
||||
|
||||
public PaginatedScheduledService getUpdateService() {
|
||||
return updateService;
|
||||
}
|
||||
@Override
|
||||
public void selected() {
|
||||
grid.getChildren().removeAll(noResultsFound, errorLabel);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 4.9 KiB |
|
@ -8,7 +8,7 @@
|
|||
<parent>
|
||||
<groupId>ctbrec</groupId>
|
||||
<artifactId>master</artifactId>
|
||||
<version>5.3.3</version>
|
||||
<version>5.3.4</version>
|
||||
<relativePath>../master</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -162,6 +162,9 @@ public class Config {
|
|||
String json = new String(fileContent, UTF_8).trim();
|
||||
json = migrateJson(json);
|
||||
settings = Objects.requireNonNull(mapper.readValue(json, Settings.class));
|
||||
JSONObject jsonObject = new JSONObject(json);
|
||||
settings.filterNAcamsOnly = jsonObject.optBoolean("filterNAcamsOnly", false);
|
||||
|
||||
settings.httpTimeout = Math.max(settings.httpTimeout, 10_000);
|
||||
if (settings.recordingsDir.endsWith("/")) {
|
||||
settings.recordingsDir = settings.recordingsDir.substring(0, settings.recordingsDir.length() - 1);
|
||||
|
@ -221,11 +224,11 @@ public class Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void migrateTo5_3_2(JSONObject json) {
|
||||
if (json.has("chaturbateUseFlaresolverr") && json.has("flaresolverr")) {
|
||||
var fsr = json.getJSONObject("flaresolverr");
|
||||
|
||||
|
||||
if (!fsr.has("useForDomains") && json.getBoolean("chaturbateUseFlaresolverr")) {
|
||||
fsr.put("useForDomains", new JSONArray().put("chaturbate.com"));
|
||||
}
|
||||
|
@ -257,11 +260,13 @@ public class Config {
|
|||
if (savingDisabled) {
|
||||
return;
|
||||
}
|
||||
String json = mapper.writeValueAsString(settings);
|
||||
JSONObject jsonObject = new JSONObject(mapper.writeValueAsString(settings));
|
||||
jsonObject.put("filterNAcamsOnly", settings.filterNAcamsOnly);
|
||||
String jsonString = jsonObject.toString();
|
||||
File configFile = new File(configDir, filename);
|
||||
log.debug("Saving config to {}", configFile.getAbsolutePath());
|
||||
Files.createDirectories(configDir.toPath());
|
||||
Files.writeString(configFile.toPath(), json, CREATE, WRITE, TRUNCATE_EXISTING);
|
||||
Files.writeString(configFile.toPath(), jsonString, CREATE, WRITE, TRUNCATE_EXISTING);
|
||||
}
|
||||
|
||||
public static boolean isServerMode() {
|
||||
|
@ -358,4 +363,8 @@ public class Config {
|
|||
List<String> ignored = Config.getInstance().getSettings().ignoredModels;
|
||||
return ignored.contains(model.getUrl());
|
||||
}
|
||||
|
||||
public boolean isFilterNAcamsOnlyEnabled() {
|
||||
return settings.filterNAcamsOnly;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ public class Settings {
|
|||
public String mfcPassword = "";
|
||||
public String mfcUsername = "";
|
||||
public boolean minimizeToTray = false;
|
||||
public boolean filterNAcamsOnly = false;
|
||||
@Deprecated
|
||||
public int minimumLengthInSeconds = 0;
|
||||
public long minimumSpaceLeftInBytes = 0;
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-expand-lg bg-secondary fixed-top text-uppercase" id="mainNav">
|
||||
<div class="container">
|
||||
<a class="navbar-brand js-scroll-trigger" href="#page-top"><img src="https://raw.githubusercontent.com/0xboobface/ctbrec/master/client/src/main/resources/icon64.png" alt="Logo"/>CTB Recorder</a>
|
||||
<a class="navbar-brand js-scroll-trigger" href="#page-top"><img src="https://git.ctbrec.com/j62/ctbrec/raw/branch/main/client/src/main/resources/icon64.png" alt="Logo"/>CTB Recorder</a>
|
||||
<button class="navbar-toggler navbar-toggler-right text-uppercase bg-primary text-white rounded" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
Menu
|
||||
<i class="fa fa-bars"></i>
|
||||
|
@ -79,7 +79,7 @@
|
|||
-->
|
||||
<h1 class="text-uppercase mb-0">CTB Recorder</h1>
|
||||
<hr class="star-light">
|
||||
<h2 class="font-weight-light mb-0">A free recording software for different camsites.<br/>Currently supported: BongaCams, Cam4, CamSoda, Chaturbate, FC2Live, LiveJasmin, MyFreeCams, Streamate</h2>
|
||||
<h2 class="font-weight-light mb-0">A free recording software for different camsites.<br/>Currently supported: Amateur.tv, BongaCams, Cam4, CamSoda, Chaturbate, CherryTV, Dreamcam, FC2Live, Flirt4free, LiveJasmin, MV Live, MyFreeCams, SecretFriends, Showup.tv, Streamate, Stripchat, Streamray, WinkTV, XLoveCam</h2>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
@ -118,19 +118,19 @@
|
|||
</script>
|
||||
<div class="row text-center">
|
||||
<div class="col">
|
||||
<a id="download_windows" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://github.com/0xboobface/ctbrec/releases/download/1.18.0/ctbrec-1.18.0-win64-jre.zip');">
|
||||
<a id="download_windows" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://git.ctbrec.com/j62/ctbrec/releases/download/5.3.3/ctbrec-5.3.3-win64-jre.zip');">
|
||||
<i class="fa fa-windows mr-2"></i>
|
||||
Download for Windows!
|
||||
</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<a id="download_macos" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://github.com/0xboobface/ctbrec/releases/download/1.18.0/ctbrec-1.18.0-macos-jre.zip');">
|
||||
<a id="download_macos" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://git.ctbrec.com/j62/ctbrec/releases/download/5.3.3/ctbrec-5.3.3-macos-jre.zip');">
|
||||
<i class="fa fa-apple mr-2"></i>
|
||||
Download for macOS!
|
||||
</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<a id="download_linux" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://github.com/0xboobface/ctbrec/releases/download/1.18.0/ctbrec-1.18.0-linux-jre.zip');">
|
||||
<a id="download_linux" class="btn btn-xl btn-outline-dark" href="#donate" onclick="downloadFile('https://git.ctbrec.com/j62/ctbrec/releases/download/5.3.3/ctbrec-5.3.3-linux-jre.zip');">
|
||||
<i class="fa fa-linux mr-2"></i>
|
||||
Download for Linux!
|
||||
</a>
|
||||
|
@ -147,7 +147,7 @@
|
|||
<div class="col-lg-10 mx-auto text-center">
|
||||
<p id="download-counter" class="lead text-center" style="display:none"></p>
|
||||
<p class="lead">
|
||||
CTB Recorder is free and open source. I'm a student and wrote this software in my spare time.
|
||||
CTB Recorder is free and open source. (Originally created by 0xboobface). I'm a student and am helping with current development, hosting this site, git(source code repo) and more on servers I am providing for free in my spare time.
|
||||
If you like the software or want to suggest a new feature, please consider buying me a coffee or two. Thanks!
|
||||
</p>
|
||||
</div>
|
||||
|
@ -155,29 +155,21 @@
|
|||
<div class="row text-center">
|
||||
<div class="col">
|
||||
<p class="lead">
|
||||
<a href="https://www.buymeacoffee.com/0xboobface" target="_blank">
|
||||
<a href="https://buymeacoffee.com/j62ctbrec" target="_blank">
|
||||
<img src="img/buymeacoffee-round.png" alt="Buy a coffee" style="height: 160px; margin: 20px"/>
|
||||
</a><br/>
|
||||
<input type="button" value="Buy a coffee"
|
||||
onclick="window.open('https://www.buymeacoffee.com/0xboobface','_blank')">
|
||||
onclick="window.open('https://buymeacoffee.com/j62ctbrec','_blank')">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<p class="lead">
|
||||
<a href="https://www.paypal.me/0xb00bface" target="_blank">
|
||||
<img src="img/paypal-round.png" alt="PayPal" style="height: 160px; margin: 20px"/>
|
||||
</a><br/>
|
||||
<input type="button" value="PayPal"
|
||||
onclick="window.open('https://www.paypal.me/0xb00bface','_blank')">
|
||||
</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="lead">
|
||||
<a href="https://www.patreon.com/0xb00bface" target="_blank">
|
||||
<a href="https://www.patreon.com/j62ctbrec" target="_blank">
|
||||
<img src="img/patreon-round.png" alt="Patreon" style="height: 160px; margin: 20px"/>
|
||||
</a><br/>
|
||||
<input type="button" value="Patreon"
|
||||
onclick="window.open('https://www.patreon.com/0xb00bface','_blank')">
|
||||
onclick="window.open('https://www.patreon.com/j62ctbrec','_blank')">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -397,7 +389,7 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<p class="lead">
|
||||
CTB Recorder is free and open source. The source code is available on <a href="https://github.com/0xboobface/ctbrec">Github</a>.
|
||||
CTB Recorder is free and open source. The source code is available on <a href="https://git.ctbrec.com/j62/ctbrec">CTBRec Gitea</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<groupId>ctbrec</groupId>
|
||||
<artifactId>master</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>5.3.3</version>
|
||||
<version>5.3.4</version>
|
||||
|
||||
<modules>
|
||||
<module>../common</module>
|
||||
|
@ -23,6 +23,8 @@
|
|||
<jackson.version>2.15.1</jackson.version>
|
||||
<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<buildNumber>SNAPSHOT</buildNumber> <!-- Default value if none is provided -->
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
@ -44,6 +46,27 @@
|
|||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>create</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<doCheck>true</doCheck>
|
||||
<doUpdate>false</doUpdate>
|
||||
<providerImplementations>
|
||||
<svn>javasvn</svn>
|
||||
<git>jgit</git>
|
||||
</providerImplementations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
<parent>
|
||||
<groupId>ctbrec</groupId>
|
||||
<artifactId>master</artifactId>
|
||||
<version>5.3.3</version>
|
||||
<version>5.3.4</version>
|
||||
<relativePath>../master</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
Loading…
Reference in New Issue