diff --git a/client/src/main/java/ctbrec/ui/SiteUI.java b/client/src/main/java/ctbrec/ui/SiteUI.java index 60289650..d7b75957 100644 --- a/client/src/main/java/ctbrec/ui/SiteUI.java +++ b/client/src/main/java/ctbrec/ui/SiteUI.java @@ -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); } diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedTab.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedTab.java index de6d895c..3a739a1a 100644 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedTab.java +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedTab.java @@ -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(); }); diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedUpdateService.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedUpdateService.java index a81df6cb..53ec2131 100644 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedUpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4FollowedUpdateService.java @@ -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> createTask() { - return new Task>() { + return new Task<>() { @Override public List call() throws IOException { return loadModelList(); @@ -48,6 +48,10 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService { } private List 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"; diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4TabProvider.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4TabProvider.java index 640cbb07..11119733 100644 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4TabProvider.java +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4TabProvider.java @@ -21,12 +21,13 @@ public class Cam4TabProvider extends AbstractTabProvider { protected List getSiteTabs(Scene scene) { List 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); diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4UpdateService.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4UpdateService.java index 8d5c13f7..c45836de 100644 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4UpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4UpdateService.java @@ -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> createTask() { - return new Task>() { + return new Task<>() { @Override public List call() throws IOException { if (loginRequired && StringUtil.isBlank(Config.getInstance().getSettings().cam4Username)) { @@ -82,38 +81,20 @@ public class Cam4UpdateService extends PaginatedScheduledService { private List parseModels(String body) { var json = new JSONObject(body); - var html = json.getString("html"); - var profilesBoxes = HtmlParser.getTags(html, "div[class~=profileDataBox]"); - List 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 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; } diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4.java b/common/src/main/java/ctbrec/sites/cam4/Cam4.java index 910a4baf..5c589ff2 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4.java @@ -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 search(String q) throws IOException, InterruptedException { List 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 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 {