diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java index 3eef73c3..d63ca427 100644 --- a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java +++ b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java @@ -1,16 +1,5 @@ package ctbrec.ui.sites.bonga; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.Objects; -import java.util.function.Consumer; - -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import ctbrec.Config; import ctbrec.sites.bonga.BongaCams; import ctbrec.ui.ExternalBrowser; @@ -18,21 +7,32 @@ import okhttp3.Cookie; import okhttp3.Cookie.Builder; import okhttp3.CookieJar; import okhttp3.HttpUrl; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.Objects; +import java.util.function.Consumer; public class BongaCamsElectronLoginDialog { private static final Logger LOG = LoggerFactory.getLogger(BongaCamsElectronLoginDialog.class); public static final String DOMAIN = "bongacams.com"; - public static final String URL = BongaCams.baseUrl + "/login"; + private final BongaCams site; private CookieJar cookieJar; private ExternalBrowser browser; - public BongaCamsElectronLoginDialog(CookieJar cookieJar) throws IOException { + public BongaCamsElectronLoginDialog(BongaCams site, CookieJar cookieJar) throws IOException { + this.site = site; this.cookieJar = cookieJar; browser = ExternalBrowser.getInstance(); try { var config = new JSONObject(); - config.put("url", URL); + config.put("url", site.getBaseUrl() + "/login"); config.put("w", 640); config.put("h", 480); var msg = new JSONObject(); @@ -46,14 +46,14 @@ public class BongaCamsElectronLoginDialog { } } - private Consumer msgHandler = line -> { - if(!line.startsWith("{")) { + private final Consumer msgHandler = line -> { + if (!line.startsWith("{")) { LOG.error("Didn't received a JSON object {}", line); } else { var json = new JSONObject(line); - if(json.has("url")) { + if (json.has("url")) { var url = json.getString("url"); - if(url.endsWith("/login")) { + if (url.endsWith("/login")) { try { Thread.sleep(500); String username = Config.getInstance().getSettings().bongaUsername; @@ -65,7 +65,7 @@ public class BongaCamsElectronLoginDialog { password = password.replace("'", "\\'"); browser.executeJavaScript("document.getElementById('log_in_password').value = '" + password + "';"); } - var simplify = new String[] { + var simplify = new String[]{ "$('div[class~=\"page_header\"]').css('display','none');", "$('div[class~=\"header_bar\"]').css('display','none')", "$('footer').css('display','none');", @@ -75,36 +75,36 @@ public class BongaCamsElectronLoginDialog { for (String js : simplify) { browser.executeJavaScript(js); } - } catch(InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); LOG.warn("Couldn't auto fill username and password for BongaCams", e); - } catch(Exception e) { + } catch (Exception e) { LOG.warn("Couldn't auto fill username and password for BongaCams", e); } } - if(json.has("cookies")) { + if (json.has("cookies")) { var cookiesFromBrowser = json.getJSONArray("cookies"); for (var i = 0; i < cookiesFromBrowser.length(); i++) { var cookie = cookiesFromBrowser.getJSONObject(i); - if(cookie.getString("domain").contains(DOMAIN)) { + if (cookie.getString("domain").contains(DOMAIN)) { Builder b = new Cookie.Builder() .path(cookie.getString("path")) .domain(DOMAIN) .name(cookie.getString("name")) .value(cookie.getString("value")) .expiresAt((long) cookie.optDouble("expirationDate")); - if(cookie.optBoolean("hostOnly")) { + if (cookie.optBoolean("hostOnly")) { b.hostOnlyDomain(DOMAIN); } - if(cookie.optBoolean("httpOnly")) { + if (cookie.optBoolean("httpOnly")) { b.httpOnly(); } - if(cookie.optBoolean("secure")) { + if (cookie.optBoolean("secure")) { b.secure(); } Cookie c = b.build(); - cookieJar.saveFromResponse(HttpUrl.parse(BongaCams.baseUrl), Collections.singletonList(c)); + cookieJar.saveFromResponse(HttpUrl.parse(BongaCamsElectronLoginDialog.this.site.getBaseUrl()), Collections.singletonList(c)); } } } diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java index ac9ef402..82c0fff9 100644 --- a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java +++ b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java @@ -1,16 +1,15 @@ package ctbrec.ui.sites.bonga; -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import ctbrec.sites.bonga.BongaCams; import ctbrec.sites.bonga.BongaCamsHttpClient; import ctbrec.ui.controls.Dialogs; import ctbrec.ui.sites.AbstractSiteUi; import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.tabs.TabProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; public class BongaCamsSiteUi extends AbstractSiteUi { @@ -47,7 +46,7 @@ public class BongaCamsSiteUi extends AbstractSiteUi { } else { // login with external browser window try { - new BongaCamsElectronLoginDialog(bongaCams.getHttpClient().getCookieJar()); + new BongaCamsElectronLoginDialog(bongaCams, bongaCams.getHttpClient().getCookieJar()); } catch (Exception e1) { LOG.error("Error logging in with external browser", e1); Dialogs.showError("Login error", "Couldn't login to " + bongaCams.getName(), e1); diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsTabProvider.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsTabProvider.java index 7589ed06..4b0ad23d 100644 --- a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsTabProvider.java +++ b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsTabProvider.java @@ -23,32 +23,32 @@ public class BongaCamsTabProvider extends AbstractTabProvider { List tabs = new ArrayList<>(); // female - String url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset="; + String url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset="; var updateService = new BongaCamsUpdateService((BongaCams) site, url); tabs.add(createTab("Female", updateService)); // male - url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=male&online_only=true&is_mobile=true&offset="; + url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=male&online_only=true&is_mobile=true&offset="; updateService = new BongaCamsUpdateService((BongaCams) site, url); tabs.add(createTab("Male", updateService)); // couples - url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=couples&online_only=true&is_mobile=true&offset="; + url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=couples&online_only=true&is_mobile=true&offset="; updateService = new BongaCamsUpdateService((BongaCams) site, url); tabs.add(createTab("Couples", updateService)); // trans - url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=transsexual&online_only=true&is_mobile=true&offset="; + url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=transsexual&online_only=true&is_mobile=true&offset="; updateService = new BongaCamsUpdateService((BongaCams) site, url); tabs.add(createTab("Transsexual", updateService)); // new - url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=new&online_only=true&is_mobile=true&offset="; + url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=new&online_only=true&is_mobile=true&offset="; updateService = new BongaCamsUpdateService((BongaCams) site, url); tabs.add(createTab("New", updateService)); // friends - url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=friends&online_only=true&offset="; + url = site.getBaseUrl() + "/tools/listing_v3.php?livetab=friends&online_only=true&offset="; updateService = new BongaCamsUpdateService((BongaCams) site, url, true); friendsTab = new BongaCamsFriendsTab("Friends", updateService, site); friendsTab.setRecorder(recorder); diff --git a/common/src/main/java/ctbrec/io/HttpConstants.java b/common/src/main/java/ctbrec/io/HttpConstants.java index 62ab903c..10c27868 100644 --- a/common/src/main/java/ctbrec/io/HttpConstants.java +++ b/common/src/main/java/ctbrec/io/HttpConstants.java @@ -6,6 +6,7 @@ public class HttpConstants { public static final String ACCEPT_ENCODING = "Accept-Encoding"; public static final String ACCEPT_ENCODING_GZIP = "gzip"; public static final String ACCEPT_LANGUAGE = "Accept-Language"; + public static final String ALL = "*"; public static final String AUTHORIZATION = "Authorization"; public static final String CACHE_CONTROL = "Cache-Control"; public static final String CONNECTION = "Connection"; diff --git a/common/src/main/java/ctbrec/sites/bonga/BongaCams.java b/common/src/main/java/ctbrec/sites/bonga/BongaCams.java index 01b1452c..69aa1d1e 100644 --- a/common/src/main/java/ctbrec/sites/bonga/BongaCams.java +++ b/common/src/main/java/ctbrec/sites/bonga/BongaCams.java @@ -1,21 +1,5 @@ package ctbrec.sites.bonga; -import static ctbrec.io.HttpConstants.*; - -import java.io.IOException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import ctbrec.Model; import ctbrec.io.HttpClient; import ctbrec.io.HttpException; @@ -24,12 +8,26 @@ import okhttp3.FormBody; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL; +import static ctbrec.io.HttpConstants.*; +import static java.nio.charset.StandardCharsets.UTF_8; public class BongaCams extends AbstractSite { private static final Logger LOG = LoggerFactory.getLogger(BongaCams.class); - public static String baseUrl = "https://bongacams.com"; + private String baseUrl = "https://bongacams.com"; private BongaCamsHttpClient httpClient; @@ -50,7 +48,7 @@ public class BongaCams extends AbstractSite { @Override public String getAffiliateLink() { - return "http://bongacams2.com/track?c=610249"; + return "https://bongacams10.com/track?c=610249"; } @Override @@ -65,8 +63,8 @@ public class BongaCams extends AbstractSite { @Override public Double getTokenBalance() throws IOException { - int userId = ((BongaCamsHttpClient)getHttpClient()).getUserId(); - String url = BongaCams.baseUrl + "/tools/amf.php"; + int userId = ((BongaCamsHttpClient) getHttpClient()).getUserId(); + String url = getBaseUrl() + "/tools/amf.php"; RequestBody body = new FormBody.Builder() .add("method", "ping") .add("args[]", Integer.toString(userId)) @@ -76,14 +74,14 @@ public class BongaCams extends AbstractSite { .addHeader(USER_AGENT, getConfig().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl) + .addHeader(REFERER, getBaseUrl()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .post(body) .build(); - try(Response response = getHttpClient().execute(request)) { - if(response.isSuccessful()) { - JSONObject json = new JSONObject(response.body().string()); - if(json.optString("status").equals("online")) { + try (Response response = getHttpClient().execute(request)) { + if (response.isSuccessful()) { + JSONObject json = new JSONObject(Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string()); + if (json.optString("status").equals("online")) { JSONObject userData = json.getJSONObject("userData"); return (double) userData.getInt("balance"); } else { @@ -108,7 +106,7 @@ public class BongaCams extends AbstractSite { @Override public HttpClient getHttpClient() { if (httpClient == null) { - httpClient = new BongaCamsHttpClient(getConfig()); + httpClient = new BongaCamsHttpClient(this, getConfig()); } return httpClient; } @@ -142,39 +140,25 @@ public class BongaCams extends AbstractSite { @Override public List search(String q) throws IOException, InterruptedException { - String url = baseUrl + "/tools/listing_v3.php?offset=0&model_search[display_name][text]=" + URLEncoder.encode(q, "utf-8"); + String url = baseUrl + "/tools/listing_v3.php?offset=0&model_search[display_name][text]=" + URLEncoder.encode(q, UTF_8); Request req = new Request.Builder() .url(url) .addHeader(USER_AGENT, getConfig().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl) + .addHeader(REFERER, getBaseUrl()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .build(); - try(Response response = getHttpClient().execute(req)) { - if(response.isSuccessful()) { - String body = response.body().string(); + try (Response response = getHttpClient().execute(req)) { + if (response.isSuccessful()) { + String body = Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); JSONObject json = new JSONObject(body); - if(json.optString("status").equals("success")) { + if (json.optString("status").equals("success")) { List models = new ArrayList<>(); - JSONArray results = json.getJSONArray("models"); - for (int i = 0; i < results.length(); i++) { - JSONObject result = results.getJSONObject(i); - if(result.has("username")) { - Model model = createModel(result.getString("username")); - String thumb = result.getString("thumb_image").replace("{ext}", "jpg"); - if(thumb != null) { - model.setPreview("https:" + thumb); - } - if(result.has("display_name")) { - model.setDisplayName(result.getString("display_name")); - } - models.add(model); - } - } + parseModelList(models, json); return models; } else { - LOG.warn("Search result: " + json.toString(2)); + LOG.warn("Search result: {}", json.toString(2)); return Collections.emptyList(); } } else { @@ -183,6 +167,24 @@ public class BongaCams extends AbstractSite { } } + private void parseModelList(List models, JSONObject json) { + JSONArray results = json.getJSONArray("models"); + for (int i = 0; i < results.length(); i++) { + JSONObject result = results.getJSONObject(i); + if (result.has("username")) { + Model model = createModel(result.getString("username")); + String thumb = result.getString("thumb_image").replace("{ext}", "jpg"); + if (thumb != null) { + model.setPreview("https:" + thumb); + } + if (result.has("display_name")) { + model.setDisplayName(result.getString("display_name")); + } + models.add(model); + } + } + } + @Override public boolean isSiteForModel(Model m) { return m instanceof BongaCamsModel; @@ -197,7 +199,7 @@ public class BongaCams extends AbstractSite { @Override public Model createModelFromUrl(String url) { Matcher m = Pattern.compile("https?://.*?bongacams.com(?:/profile)?/([^/]*?)/?").matcher(url); - if(m.matches()) { + if (m.matches()) { String modelName = m.group(1); return createModel(modelName); } else { diff --git a/common/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java b/common/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java index cae7a7d1..6e2c240c 100644 --- a/common/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java +++ b/common/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java @@ -1,36 +1,34 @@ package ctbrec.sites.bonga; -import static ctbrec.io.HttpConstants.*; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - +import ctbrec.Config; +import ctbrec.io.HttpClient; +import ctbrec.io.HttpException; +import okhttp3.*; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ctbrec.Config; -import ctbrec.io.HttpClient; -import ctbrec.io.HttpException; -import okhttp3.Cookie; -import okhttp3.FormBody; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL; +import static ctbrec.io.HttpConstants.*; public class BongaCamsHttpClient extends HttpClient { private static final Logger LOG = LoggerFactory.getLogger(BongaCamsHttpClient.class); private static final String SORT_COOKIE = "ls01"; + private final BongaCams site; private int userId = 0; - public BongaCamsHttpClient(Config config) { + public BongaCamsHttpClient(BongaCams site, Config config) { super("bongacams", config); + this.site = site; addSortByPopularCookie(); } @@ -48,24 +46,19 @@ public class BongaCamsHttpClient extends HttpClient { Map> cookies = cookieJar.getCookies(); for (Entry> entry : cookies.entrySet()) { List cookieList = entry.getValue(); - for (Iterator iterator = cookieList.iterator(); iterator.hasNext();) { - Cookie cookie = iterator.next(); - if(cookie.name().equals(SORT_COOKIE)) { - iterator.remove(); - } - } + cookieList.removeIf(cookie -> cookie.name().equals(SORT_COOKIE)); entry.getValue().add(sortByCookie); } } @Override public synchronized boolean login() throws IOException { - if(loggedIn) { + if (loggedIn) { return true; } boolean cookiesWorked = checkLoginSuccess(); - if(cookiesWorked) { + if (cookiesWorked) { loggedIn = true; LOG.debug("Logged in with cookies"); return true; @@ -76,33 +69,32 @@ public class BongaCamsHttpClient extends HttpClient { /** * Check, if the login worked by requesting roomdata and looking - * @throws IOException + * + * @throws IOException if the roomdata couldn't be loaded */ public boolean checkLoginSuccess() throws IOException { String modelName = getAnyModelName(); // we request the roomData of a random model, because it contains // user data, if the user is logged in, which we can use to verify, that the login worked - String url = BongaCams.baseUrl + "/tools/amf.php"; + String url = site.getBaseUrl() + "/tools/amf.php"; RequestBody body = new FormBody.Builder() .add("method", "getRoomData") .add("args[]", modelName) .add("args[]", "false") - //.add("method", "ping") // TODO alternative request, but - //.add("args[]", ) // where to get the userId .build(); Request request = new Request.Builder() .url(url) .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl) + .addHeader(REFERER, site.getBaseUrl()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .post(body) .build(); - try(Response response = execute(request)) { - if(response.isSuccessful()) { - JSONObject json = new JSONObject(response.body().string()); - if(json.optString("status").equals("success")) { + try (Response response = execute(request)) { + if (response.isSuccessful()) { + JSONObject json = new JSONObject(Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string()); + if (json.optString("status").equals("success")) { JSONObject userData = json.getJSONObject("userData"); userId = userData.optInt("userId"); return userId > 0; @@ -120,23 +112,23 @@ public class BongaCamsHttpClient extends HttpClient { */ private String getAnyModelName() throws IOException { Request request = new Request.Builder() - .url(BongaCams.baseUrl + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset=0") + .url(site.getBaseUrl() + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset=0") .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl) + .addHeader(REFERER, site.getBaseUrl()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .build(); - try(Response response = execute(request)) { + try (Response response = execute(request)) { if (response.isSuccessful()) { - String content = response.body().string(); + String content = Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); JSONObject json = new JSONObject(content); - if(json.optString("status").equals("success")) { + if (json.optString("status").equals("success")) { JSONArray jsonModels = json.getJSONArray("models"); JSONObject m = jsonModels.getJSONObject(0); String name = m.getString("username"); return name; - } else { + } else { throw new IOException("Request was not successful: " + content); } } else { @@ -145,45 +137,8 @@ public class BongaCamsHttpClient extends HttpClient { } } - // @Override - // public boolean login() throws IOException { - // String url = BongaCams.BASE_URL + "/login"; - // String dateTime = new SimpleDateFormat("d.MM.yyyy', 'HH:mm:ss").format(new Date()); - // RequestBody body = new FormBody.Builder() - // .add("security_log_additional_info","{\"language\":\"en\",\"cookieEnabled\":true,\"javaEnabled\":false,\"flashVersion\":\"31.0.0\",\"dateTime\":\""+dateTime+"\",\"ips\":[\"192.168.0.1\"]}") - // .add("log_in[username]", Config.getInstance().getSettings().bongaUsername) - // .add("log_in[password]", Config.getInstance().getSettings().bongaPassword) - // .add("log_in[remember]", "1") - // .add("log_in[bfpt]", "") - // .add("header_form", "1") - // .build(); - // Request request = new Request.Builder() - // .url(url) - // .post(body) - // .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) - // .addHeader(ACCEPT,"application/json") - // .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - // .addHeader(REFERER, BongaCams.BASE_URL) - // .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) - // .build(); - // try(Response response = execute(request)) { - // if(response.isSuccessful()) { - // JSONObject json = new JSONObject(response.body().string()); - // if(json.optString("status").equals("success")) { - // return true; - // } else { - // LOG.debug("Login response: {}", json.toString(2)); - // Platform.runLater(() -> new BongaCamsLoginDialog()); - // throw new IOException("Login not successful"); - // } - // } else { - // throw new HttpException(response.code(), response.message()); - // } - // } - // } - public int getUserId() throws IOException { - if(userId == 0) { + if (userId == 0) { login(); } return userId; diff --git a/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java b/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java index 206c8c37..08569cb6 100644 --- a/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java +++ b/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java @@ -1,44 +1,34 @@ package ctbrec.sites.bonga; -import static ctbrec.Model.State.*; -import static ctbrec.io.HttpConstants.*; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.ExecutionException; - -import org.json.JSONObject; -import org.jsoup.nodes.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.iheartradio.m3u8.Encoding; -import com.iheartradio.m3u8.Format; -import com.iheartradio.m3u8.ParseException; -import com.iheartradio.m3u8.ParsingMode; -import com.iheartradio.m3u8.PlaylistException; -import com.iheartradio.m3u8.PlaylistParser; +import com.iheartradio.m3u8.*; import com.iheartradio.m3u8.data.MasterPlaylist; import com.iheartradio.m3u8.data.Playlist; import com.iheartradio.m3u8.data.PlaylistData; import com.iheartradio.m3u8.data.StreamInfo; - import ctbrec.AbstractModel; import ctbrec.Config; import ctbrec.io.HtmlParser; -import ctbrec.io.HtmlParserException; import ctbrec.io.HttpException; import ctbrec.recorder.download.StreamSource; import okhttp3.FormBody; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import org.json.JSONObject; +import org.jsoup.nodes.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL; +import static ctbrec.Model.State.*; +import static ctbrec.io.HttpConstants.*; public class BongaCamsModel extends AbstractModel { @@ -47,61 +37,87 @@ public class BongaCamsModel extends AbstractModel { private static final String SUCCESS = "success"; private static final String STATUS = "status"; - private int userId; + private static final Pattern ONLINE_BADGE_REGEX = Pattern.compile("class=\"badge_online\s*\""); + private boolean online = false; - private transient List streamSources = new ArrayList<>(); + private final transient List streamSources = new ArrayList<>(); private int[] resolution; @Override public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException { if (ignoreCache) { - String url = "https://en.bongacams.com/" + URLEncoder.encode(getName(), StandardCharsets.UTF_8.name()); - Request req = new Request.Builder().url(url) - .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) - .header(ACCEPT, "*") - .header(ACCEPT_LANGUAGE, "en") - .header(REFERER, getSite().getBaseUrl()) - .build(); - try (Response resp = site.getHttpClient().execute(req)) { - String body = resp.body().string(); - String chatType = parseChatType(body); - onlineState = mapState(chatType); - if (onlineState == ONLINE) { - if (isStreamAvailable()) { - online = true; - } else { - online = false; - onlineState = AWAY; - } - } else { - online = false; - } + boolean modelIsConnected = basicOnlineCheck(); + if (!modelIsConnected) { + onlineState = OFFLINE; + online = false; + return false; } + + return completeOnlineCheck(); } return online; } - private String parseChatType(String body) { - String chatType = ""; - if (body.contains("chatType")) { - try { - chatType = HtmlParser.getText(body, ".chatType"); - } catch (HtmlParserException e) { - LOG.warn("Online check didn't work", e); - } + private boolean completeOnlineCheck() throws IOException { + JSONObject roomData = getRoomData(); + if (!roomData.has("performerData")) { + onlineState = UNKNOWN; + return false; } - return chatType; + JSONObject performerData = roomData.getJSONObject("performerData"); + setDisplayName(performerData.optString("displayName")); + String chatType = performerData.optString("showType"); + boolean isAway = performerData.optBoolean("isAway"); + + onlineState = mapState(chatType); + if (onlineState == ONLINE) { + if (isStreamAvailable()) { + if (isAway) { + onlineState = AWAY; + online = false; + } else { + online = true; + } + } else { + online = false; + onlineState = AWAY; + } + } else { + online = false; + } + return online; } - private State mapState(String chatType) { - if (chatType.matches(".*? is in a public chat")) { - return ONLINE; - } else if (chatType.matches(".*? is in a group chat")) { - return GROUP; - } else if (chatType.matches(".*? is in a private chat")) { - return PRIVATE; - } else { - return OFFLINE; + private boolean basicOnlineCheck() { + try { + String url = site.getBaseUrl() + "/profile/" + getName().toLowerCase(); + Request req = new Request.Builder().url(url).build(); + try (Response resp = site.getHttpClient().execute(req)) { + if (resp.isSuccessful()) { + String body = Objects.requireNonNull(resp.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); + Matcher m = ONLINE_BADGE_REGEX.matcher(body); + return m.find(); + } else { + return false; + } + } + } catch (Exception e) { + LOG.warn("Couldn't check if model is connected: {}", e.getLocalizedMessage()); + return false; + } + } + + public State mapState(String roomState) { + switch (roomState) { + case "private", "fullprivate": + return PRIVATE; + case "group": + return GROUP; + case "public": + return ONLINE; + default: + LOG.debug(roomState); + return OFFLINE; } } @@ -111,20 +127,20 @@ public class BongaCamsModel extends AbstractModel { Request req = new Request.Builder().url(url).build(); try (Response resp = site.getHttpClient().execute(req)) { if (resp.isSuccessful()) { - String body = resp.body().string(); + String body = Objects.requireNonNull(resp.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); return body.contains("#EXT-X-STREAM-INF"); } else { return false; } } - } catch(Exception e) { + } catch (Exception e) { LOG.warn("Couldn't check if stream is available: {}", e.getLocalizedMessage()); return false; } } private JSONObject getRoomData() throws IOException { - String url = BongaCams.baseUrl + "/tools/amf.php"; + String url = getSite().getBaseUrl() + "/tools/amf.php"; RequestBody body = new FormBody.Builder() .add("method", "getRoomData") .add(ARGS, getName()) @@ -135,13 +151,13 @@ public class BongaCamsModel extends AbstractModel { .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl) + .addHeader(REFERER, getSite().getBaseUrl()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .post(body) .build(); - try(Response response = site.getHttpClient().execute(request)) { - if(response.isSuccessful()) { - JSONObject json = new JSONObject(response.body().string()); + try (Response response = site.getHttpClient().execute(request)) { + if (response.isSuccessful()) { + JSONObject json = new JSONObject(Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string()); return json; } else { throw new IOException(response.code() + " " + response.message()); @@ -155,9 +171,7 @@ public class BongaCamsModel extends AbstractModel { @Override public State getOnlineState(boolean failFast) throws IOException, ExecutionException { - if (failFast) { - return onlineState; - } else { + if (!failFast) { try { isOnline(true); } catch (InterruptedException e) { @@ -166,8 +180,8 @@ public class BongaCamsModel extends AbstractModel { } catch (IOException | ExecutionException e) { onlineState = OFFLINE; } - return onlineState; } + return onlineState; } @Override @@ -179,28 +193,13 @@ public class BongaCamsModel extends AbstractModel { public List getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException { String streamUrl = getStreamUrl(); Request req = new Request.Builder().url(streamUrl).build(); - try(Response response = site.getHttpClient().execute(req)) { - if(response.isSuccessful()) { - InputStream inputStream = response.body().byteStream(); + try (Response response = site.getHttpClient().execute(req)) { + if (response.isSuccessful()) { + InputStream inputStream = Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).byteStream(); PlaylistParser parser = new PlaylistParser(inputStream, Format.EXT_M3U, Encoding.UTF_8, ParsingMode.LENIENT); Playlist playlist = parser.parse(); MasterPlaylist master = playlist.getMasterPlaylist(); - streamSources.clear(); - for (PlaylistData playlistData : master.getPlaylists()) { - StreamSource streamsource = new StreamSource(); - streamsource.mediaPlaylistUrl = streamUrl.replace("playlist.m3u8", playlistData.getUri()); - if (playlistData.hasStreamInfo()) { - StreamInfo info = playlistData.getStreamInfo(); - streamsource.bandwidth = info.getBandwidth(); - streamsource.width = info.hasResolution() ? info.getResolution().width : 0; - streamsource.height = info.hasResolution() ? info.getResolution().height : 0; - } else { - streamsource.bandwidth = 0; - streamsource.width = 0; - streamsource.height = 0; - } - streamSources.add(streamsource); - } + extractStreamSources(streamUrl, master); } else { throw new HttpException(response.code(), response.message()); } @@ -208,6 +207,25 @@ public class BongaCamsModel extends AbstractModel { return streamSources; } + private void extractStreamSources(String streamUrl, MasterPlaylist master) { + streamSources.clear(); + for (PlaylistData playlistData : master.getPlaylists()) { + StreamSource streamsource = new StreamSource(); + streamsource.mediaPlaylistUrl = streamUrl.replace("playlist.m3u8", playlistData.getUri()); + if (playlistData.hasStreamInfo()) { + StreamInfo info = playlistData.getStreamInfo(); + streamsource.bandwidth = info.getBandwidth(); + streamsource.width = info.hasResolution() ? info.getResolution().width : 0; + streamsource.height = info.hasResolution() ? info.getResolution().height : 0; + } else { + streamsource.bandwidth = 0; + streamsource.width = 0; + streamsource.height = 0; + } + streamSources.add(streamsource); + } + } + private String getStreamUrl() throws IOException { JSONObject roomData = getRoomData(); if (roomData.optString(STATUS).equals(SUCCESS)) { @@ -226,8 +244,8 @@ public class BongaCamsModel extends AbstractModel { @Override public void receiveTip(Double tokens) throws IOException { - String url = BongaCams.baseUrl + "/chat-ajax-amf-service?" + System.currentTimeMillis(); - userId = ((BongaCamsHttpClient)site.getHttpClient()).getUserId(); + String url = getSite().getBaseUrl() + "/chat-ajax-amf-service?" + System.currentTimeMillis(); + int userId = ((BongaCamsHttpClient) site.getHttpClient()).getUserId(); RequestBody body = new FormBody.Builder() .add("method", "tipModel") .add(ARGS, getName()) @@ -240,14 +258,14 @@ public class BongaCamsModel extends AbstractModel { .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .addHeader(REFERER, BongaCams.baseUrl + '/' + getName()) + .addHeader(REFERER, getSite().getBaseUrl() + '/' + getName()) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .post(body) .build(); - try(Response response = site.getHttpClient().execute(request)) { - if(response.isSuccessful()) { - JSONObject json = new JSONObject(response.body().string()); - if(!json.optString(STATUS).equals(SUCCESS)) { + try (Response response = site.getHttpClient().execute(request)) { + if (response.isSuccessful()) { + JSONObject json = new JSONObject(Objects.requireNonNull(response.body(), HTTP_RESPONSE_BODY_IS_NULL).string()); + if (!json.optString(STATUS).equals(SUCCESS)) { LOG.error("Sending tip failed {}", json.toString(2)); throw new IOException("Sending tip failed"); } @@ -259,18 +277,18 @@ public class BongaCamsModel extends AbstractModel { @Override public int[] getStreamResolution(boolean failFast) throws ExecutionException { - if(resolution == null) { - if(failFast) { + if (resolution == null) { + if (failFast) { return new int[2]; } try { - if(!isOnline()) { + if (!isOnline()) { return new int[2]; } List sources = getStreamSources(); Collections.sort(sources); - StreamSource best = sources.get(sources.size()-1); - resolution = new int[] {best.width, best.height}; + StreamSource best = sources.get(sources.size() - 1); + resolution = new int[]{best.width, best.height}; } catch (InterruptedException e) { Thread.currentThread().interrupt(); LOG.warn("Couldn't determine stream resolution for {} - {}", getName(), e.getMessage()); @@ -279,15 +297,13 @@ public class BongaCamsModel extends AbstractModel { LOG.warn("Couldn't determine stream resolution for {} - {}", getName(), e.getMessage()); resolution = new int[2]; } - return resolution; - } else { - return resolution; } + return resolution; } @Override public boolean follow() throws IOException { - if(!getSite().login()) { + if (!getSite().login()) { throw new IOException("Not logged in"); } @@ -306,11 +322,11 @@ public class BongaCamsModel extends AbstractModel { .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(X_REQUESTED_WITH, XML_HTTP_REQUEST) .build(); - try(Response resp = site.getHttpClient().execute(req)) { - if(resp.isSuccessful()) { - String msg = resp.body().string(); + try (Response resp = site.getHttpClient().execute(req)) { + if (resp.isSuccessful()) { + String msg = Objects.requireNonNull(resp.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); JSONObject json = new JSONObject(msg); - if(json.optBoolean(SUCCESS)) { + if (json.optBoolean(SUCCESS)) { LOG.debug("Follow/Unfollow -> {}", msg); return true; } else { @@ -328,12 +344,12 @@ public class BongaCamsModel extends AbstractModel { .url(getUrl()) .header(ACCEPT, "*/*") .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .header(REFERER, BongaCams.baseUrl) + .header(REFERER, getSite().getBaseUrl()) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .build(); - try(Response resp = site.getHttpClient().execute(req)) { - if(resp.isSuccessful()) { - String content = resp.body().string(); + try (Response resp = site.getHttpClient().execute(req)) { + if (resp.isSuccessful()) { + String content = Objects.requireNonNull(resp.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); Element html = HtmlParser.getTag(content, "html"); String csrfToken = html.attr("data-csrf_value"); LOG.debug("CSRF-Token {}", csrfToken); @@ -366,7 +382,7 @@ public class BongaCamsModel extends AbstractModel { .build(); try (Response resp = site.getHttpClient().execute(req)) { if (resp.isSuccessful()) { - String msg = resp.body().string(); + String msg = Objects.requireNonNull(resp.body(), HTTP_RESPONSE_BODY_IS_NULL).string(); JSONObject json = new JSONObject(msg); if (json.optBoolean(SUCCESS)) { LOG.debug("Follow/Unfollow -> {}", msg); @@ -381,32 +397,17 @@ public class BongaCamsModel extends AbstractModel { } } - public int getUserId() throws IOException { - if (userId == 0) { - JSONObject roomData = getRoomData(); - userId = roomData.getJSONObject("performerData").getInt("userId"); - } - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - public void mapOnlineState(String roomState) { switch (roomState) { - case "private": - case "fullprivate": - setOnlineState(PRIVATE); - break; - case "group": - case "public": - setOnlineState(ONLINE); - setOnline(true); - break; - default: - LOG.debug(roomState); - setOnlineState(OFFLINE); + case "private", "fullprivate" -> setOnlineState(PRIVATE); + case "group", "public" -> { + setOnlineState(ONLINE); + setOnline(true); + } + default -> { + LOG.debug(roomState); + setOnlineState(OFFLINE); + } } }