Fix Cam4 browser tabs

This commit is contained in:
0xb00bface 2023-02-10 15:29:01 +01:00
parent adf129a0c0
commit f39b9ef13f
6 changed files with 91 additions and 96 deletions

View File

@ -1,15 +1,18 @@
package ctbrec.ui;
import java.io.IOException;
import ctbrec.Model;
import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider;
import java.io.IOException;
public interface SiteUI {
public TabProvider getTabProvider();
public ConfigUI getConfigUI();
public boolean login() throws IOException;
public boolean play(Model model);
TabProvider getTabProvider();
ConfigUI getConfigUI();
boolean login() throws IOException;
boolean play(Model model);
}

View File

@ -14,11 +14,15 @@ import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
private Label status;
private final Label status;
public Cam4FollowedTab(Cam4 cam4) {
super("Followed", new Cam4FollowedUpdateService(cam4), cam4);
status = new Label("Logging in...");
if (cam4.credentialsAvailable()) {
status = new Label("Logging in...");
} else {
status = new Label("Credentials are missing in the settings");
}
grid.getChildren().add(status);
}
@ -36,11 +40,11 @@ public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
offline.setToggleGroup(group);
pagination.getChildren().add(online);
pagination.getChildren().add(offline);
HBox.setMargin(online, new Insets(5,5,5,40));
HBox.setMargin(offline, new Insets(5,5,5,5));
HBox.setMargin(online, new Insets(5, 5, 5, 40));
HBox.setMargin(offline, new Insets(5, 5, 5, 5));
online.setSelected(true);
group.selectedToggleProperty().addListener(e -> {
((Cam4FollowedUpdateService)updateService).setShowOnline(online.isSelected());
((Cam4FollowedUpdateService) updateService).setShowOnline(online.isSelected());
queue.clear();
updateService.restart();
});

View File

@ -1,15 +1,5 @@
package ctbrec.ui.sites.cam4;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Model;
import ctbrec.io.HttpException;
import ctbrec.sites.cam4.Cam4;
@ -18,12 +8,22 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task;
import okhttp3.Request;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Cam4FollowedUpdateService extends PaginatedScheduledService {
private static final Logger LOG = LoggerFactory.getLogger(Cam4FollowedUpdateService.class);
private Cam4 site;
private final Cam4 site;
private boolean showOnline = true;
public Cam4FollowedUpdateService(Cam4 site) {
@ -39,7 +39,7 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
@Override
protected Task<List<Model>> createTask() {
return new Task<List<Model>>() {
return new Task<>() {
@Override
public List<Model> call() throws IOException {
return loadModelList();
@ -48,6 +48,10 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
}
private List<Model> loadModelList() throws IOException {
if (!site.credentialsAvailable()) {
return Collections.emptyList();
}
// login first
SiteUiFactory.getUi(site).login();
String url = site.getBaseUrl() + "/directoryCams?directoryJson=true&online=" + showOnline + "&url=true&friends=true&favorites=true&resultsPerPage=90";

View File

@ -21,12 +21,13 @@ public class Cam4TabProvider extends AbstractTabProvider {
protected List<Tab> getSiteTabs(Scene scene) {
List<Tab> tabs = new ArrayList<>();
tabs.add(createTab("Female", site.getBaseUrl() + "/directoryResults?online=true&gender=female&orderBy=MOST_VIEWERS"));
tabs.add(createTab("Male", site.getBaseUrl() + "/directoryResults?online=true&gender=male&orderBy=MOST_VIEWERS"));
tabs.add(createTab("Trans", site.getBaseUrl() + "/directoryResults?online=true&gender=shemale&orderBy=MOST_VIEWERS"));
tabs.add(createTab("Couples", site.getBaseUrl() + "/directoryResults?online=true&broadcastType=male_group&broadcastType=female_group&broadcastType=male_female_group&orderBy=MOST_VIEWERS"));
tabs.add(createTab("HD", site.getBaseUrl() + "/directoryResults?online=true&hd=true&orderBy=MOST_VIEWERS"));
tabs.add(createTab("New", site.getBaseUrl() + "/directoryResults?online=true&gender=female&orderBy=MOST_VIEWERS&newPerformer=true"));
tabs.add(createTab("Female", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&gender=female"));
tabs.add(createTab("Male", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&gender=male"));
tabs.add(createTab("Trans", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&gender=shemale"));
tabs.add(createTab("Couples", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&broadcastType=male_group&broadcastType=female_group&broadcastType=male_female_group"));
tabs.add(createTab("HD", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=VIDEO_QUALITY&gender=female&broadcastType=female_group&broadcastType=solo&broadcastType=male_female_group&hd=true"));
tabs.add(createTab("Mobile", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&gender=female&broadcastType=female_group&broadcastType=solo&broadcastType=male_female_group&source=mobile"));
tabs.add(createTab("New", site.getBaseUrl() + "/directoryCams?directoryJson=true&online=true&url=true&orderBy=MOST_VIEWERS&gender=female&broadcastType=female_group&broadcastType=solo&broadcastType=male_female_group&newPerformer=true"));
followed = new Cam4FollowedTab((Cam4) site);
followed.setRecorder(recorder);

View File

@ -1,7 +1,19 @@
package ctbrec.ui.sites.cam4;
import static ctbrec.Model.State.*;
import static ctbrec.io.HttpConstants.*;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.io.HttpException;
import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.cam4.Cam4Model;
import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task;
import okhttp3.Request;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
@ -11,29 +23,16 @@ import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.json.JSONObject;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpException;
import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.cam4.Cam4Model;
import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task;
import okhttp3.Request;
import static ctbrec.Model.State.ONLINE;
import static ctbrec.io.HttpConstants.ACCEPT_LANGUAGE;
import static ctbrec.io.HttpConstants.USER_AGENT;
public class Cam4UpdateService extends PaginatedScheduledService {
private static final Logger LOG = LoggerFactory.getLogger(Cam4UpdateService.class);
private String url;
private Cam4 site;
private boolean loginRequired;
private final Cam4 site;
private final boolean loginRequired;
public Cam4UpdateService(String url, boolean loginRequired, Cam4 site) {
this.site = site;
@ -51,7 +50,7 @@ public class Cam4UpdateService extends PaginatedScheduledService {
@Override
protected Task<List<Model>> createTask() {
return new Task<List<Model>>() {
return new Task<>() {
@Override
public List<Model> call() throws IOException {
if (loginRequired && StringUtil.isBlank(Config.getInstance().getSettings().cam4Username)) {
@ -82,38 +81,20 @@ public class Cam4UpdateService extends PaginatedScheduledService {
private List<Model> parseModels(String body) {
var json = new JSONObject(body);
var html = json.getString("html");
var profilesBoxes = HtmlParser.getTags(html, "div[class~=profileDataBox]");
List<Model> models = new ArrayList<>(profilesBoxes.size());
for (Element profileBox : profilesBoxes) {
String boxHtml = profileBox.html();
Element profileLink = HtmlParser.getTag(boxHtml, "a.profile-preview");
String path = profileLink.attr("href");
var slug = path.substring(1);
Cam4Model model = site.createModel(slug);
String playlistUrl = profileLink.attr("data-hls-preview-url");
model.setDisplayName(HtmlParser.getText(boxHtml, "div.profileBoxTitle a").trim());
model.setPlaylistUrl(playlistUrl);
model.setPreview("https://snapshots.xcdnpro.com/thumbnails/" + model.getName() + "?s=" + System.currentTimeMillis());
model.setDescription(parseDesription(boxHtml));
JSONArray users = json.getJSONArray("users");
List<Model> models = new ArrayList<>(users.length());
for (int i = 0; i < users.length(); i++) {
JSONObject user = users.getJSONObject(i);
Cam4Model model = site.createModel(user.getString("username"));
model.setPlaylistUrl(user.getString("hlsPreviewUrl"));
model.setPreview(user.getString("snapshotImageLink"));
model.setDescription(user.getString("statusMessage"));
model.setOnlineState(ONLINE);
if (boxHtml.contains("In private show")) {
model.setOnlineState(PRIVATE);
}
models.add(model);
}
return models;
}
private String parseDesription(String boxHtml) {
try {
return HtmlParser.getText(boxHtml, "div[class~=statusMsg2]");
} catch(Exception e) {
LOG.trace("Couldn't parse description for room");
}
return "";
}
public void setUrl(String url) {
this.url = url;
}

View File

@ -1,18 +1,5 @@
package ctbrec.sites.cam4;
import static ctbrec.io.HttpClient.*;
import static ctbrec.io.HttpConstants.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONObject;
import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.io.HttpClient;
@ -20,6 +7,19 @@ import ctbrec.io.HttpException;
import ctbrec.sites.AbstractSite;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static ctbrec.io.HttpClient.bodyToJsonArray;
import static ctbrec.io.HttpConstants.USER_AGENT;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Cam4 extends AbstractSite {
@ -58,7 +58,7 @@ public class Cam4 extends AbstractSite {
if (!credentialsAvailable()) {
throw new IOException("Not logged in");
}
return ((Cam4HttpClient)getHttpClient()).getTokenBalance();
return ((Cam4HttpClient) getHttpClient()).getTokenBalance();
}
@Override
@ -114,13 +114,15 @@ public class Cam4 extends AbstractSite {
@Override
public List<Model> search(String q) throws IOException, InterruptedException {
List<Model> result = new ArrayList<>();
search(q, false, result);
search(q, true, result);
if (credentialsAvailable()) {
search(q, false, result);
search(q, true, result);
}
return result;
}
private void search(String q, boolean offline, List<Model> models) throws IOException {
String url = BASE_URI + "/usernameSearch?username=" + URLEncoder.encode(q, "utf-8");
String url = BASE_URI + "/usernameSearch?username=" + URLEncoder.encode(q, UTF_8);
if (offline) {
url += "&offline=true";
}
@ -135,7 +137,7 @@ public class Cam4 extends AbstractSite {
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
Model model = createModel(result.getString("username"));
String thumb = null;
String thumb;
if (result.has("thumbnailId")) {
thumb = "https://snapshots.xcdnpro.com/thumbnails/" + model.getName() + "?s=" + result.getString("thumbnailId");
} else {
@ -165,8 +167,8 @@ public class Cam4 extends AbstractSite {
@Override
public Model createModelFromUrl(String url) {
Matcher m = Pattern.compile("https?://(?:www\\.)?cam4(?:.*?).com/([^/]*?)/?").matcher(url);
if(m.matches()) {
Matcher m = Pattern.compile("https?://(?:www\\.)?cam4.*?.com/([^/]*?)/?").matcher(url);
if (m.matches()) {
String modelName = m.group(1);
return createModel(modelName);
} else {