diff --git a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedTab.java b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedTab.java new file mode 100644 index 00000000..86d53bc7 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedTab.java @@ -0,0 +1,41 @@ +package ctbrec.ui.sites.fc2live; + +import ctbrec.sites.fc2live.Fc2Live; +import ctbrec.ui.FollowedTab; +import ctbrec.ui.ThumbOverviewTab; +import javafx.geometry.Insets; +import javafx.scene.control.RadioButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.HBox; + +public class Fc2FollowedTab extends ThumbOverviewTab implements FollowedTab { + + public Fc2FollowedTab(Fc2Live fc2live) { + super("Followed", new Fc2FollowedUpdateService(fc2live), fc2live); + } + + @Override + protected void createGui() { + super.createGui(); + //addOnlineOfflineSelector(); + } + + @SuppressWarnings("unused") + private void addOnlineOfflineSelector() { + ToggleGroup group = new ToggleGroup(); + RadioButton online = new RadioButton("online"); + online.setToggleGroup(group); + RadioButton offline = new RadioButton("offline"); + 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)); + online.setSelected(true); + group.selectedToggleProperty().addListener((e) -> { + ((Fc2FollowedUpdateService)updateService).setShowOnline(online.isSelected()); + queue.clear(); + updateService.restart(); + }); + } +} diff --git a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedUpdateService.java b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedUpdateService.java new file mode 100644 index 00000000..5db22826 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2FollowedUpdateService.java @@ -0,0 +1,83 @@ +package ctbrec.ui.sites.fc2live; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import ctbrec.Model; +import ctbrec.io.HttpException; +import ctbrec.sites.fc2live.Fc2Live; +import ctbrec.sites.fc2live.Fc2Model; +import ctbrec.ui.PaginatedScheduledService; +import javafx.concurrent.Task; +import okhttp3.FormBody; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class Fc2FollowedUpdateService extends PaginatedScheduledService { + + private Fc2Live fc2live; + + public Fc2FollowedUpdateService(Fc2Live fc2live) { + this.fc2live = fc2live; + } + + @Override + protected Task> createTask() { + return new Task>() { + @Override + public List call() throws IOException { + if(!fc2live.login()) { + throw new IOException("Login didn't work"); + } + + RequestBody body = new FormBody.Builder() + .add("mode", "list") + .add("page", Integer.toString(page - 1)) + .build(); + Request req = new Request.Builder() + .url(fc2live.getBaseUrl() + "/api/favoriteManager.php") + .header("Referer", fc2live.getBaseUrl()) + .header("Content-Type", "application/x-www-form-urlencoded") + .post(body) + .build(); + try(Response resp = fc2live.getHttpClient().execute(req)) { + if(resp.isSuccessful()) { + List models = new ArrayList<>(); + String content = resp.body().string(); + JSONObject json = new JSONObject(content); + if(json.optInt("status") == 1) { + JSONArray data = json.getJSONArray("data"); + for (int i = 0; i < data.length(); i++) { + JSONObject m = data.getJSONObject(i); + Fc2Model model = (Fc2Model) fc2live.createModel(m.getString("name")); + model.setId(m.getString("id")); + model.setUrl(Fc2Live.BASE_URL + '/' + model.getId()); + String previewUrl = m.optString("icon"); + if(previewUrl == null || previewUrl.trim().isEmpty()) { + previewUrl = "https://live-storage.fc2.com/thumb/" + model.getId() + "/thumb.jpg"; + } + model.setPreview(previewUrl); + model.setDescription(""); + models.add(model); + } + return models; + } else { + throw new IOException("Request was not successful: " + content); + } + } else { + throw new HttpException(resp.code(), resp.message()); + } + } + } + }; + } + + public void setShowOnline(boolean online) { + //this.online = online; + } +} diff --git a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2TabProvider.java b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2TabProvider.java index d6e448c9..a5a0b32f 100644 --- a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2TabProvider.java +++ b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2TabProvider.java @@ -12,6 +12,7 @@ import javafx.scene.control.Tab; public class Fc2TabProvider extends TabProvider { private Fc2Live fc2live; + private Fc2FollowedTab followed; public Fc2TabProvider(Fc2Live fc2live) { this.fc2live = fc2live; @@ -21,6 +22,11 @@ public class Fc2TabProvider extends TabProvider { public List getTabs(Scene scene) { List tabs = new ArrayList<>(); tabs.add(createTab("Online", Fc2Live.BASE_URL + "/adult/contents/allchannellist.php")); + + followed = new Fc2FollowedTab(fc2live); + followed.setRecorder(fc2live.getRecorder()); + tabs.add(followed); + return tabs; } @@ -33,6 +39,6 @@ public class Fc2TabProvider extends TabProvider { @Override public Tab getFollowedTab() { - return null; + return followed; } } diff --git a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2UpdateService.java b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2UpdateService.java index 46c8cba7..d69b3a1d 100644 --- a/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2UpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/fc2live/Fc2UpdateService.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import ctbrec.Config; import ctbrec.Model; +import ctbrec.io.HttpException; import ctbrec.sites.fc2live.Fc2Live; import ctbrec.sites.fc2live.Fc2Model; import ctbrec.ui.PaginatedScheduledService; @@ -76,8 +77,7 @@ public class Fc2UpdateService extends PaginatedScheduledService { .limit(modelsPerPage) .collect(Collectors.toList()); } else { - resp.close(); - throw new IOException("HTTP status " + resp.code() + " " + resp.message()); + throw new HttpException(resp.code(), resp.message()); } } } diff --git a/common/src/main/java/ctbrec/Settings.java b/common/src/main/java/ctbrec/Settings.java index 33956234..fcf52571 100644 --- a/common/src/main/java/ctbrec/Settings.java +++ b/common/src/main/java/ctbrec/Settings.java @@ -63,6 +63,8 @@ public class Settings { public String camsodaPassword = ""; public String cam4Username = ""; public String cam4Password = ""; + public String fc2liveUsername = ""; + public String fc2livePassword = ""; public String livejasminUsername = ""; public String livejasminPassword = ""; public String livejasminBaseUrl = "https://www.livejasmin.com"; diff --git a/common/src/main/java/ctbrec/sites/fc2live/Fc2HttpClient.java b/common/src/main/java/ctbrec/sites/fc2live/Fc2HttpClient.java index 5f5ab795..8a70a70b 100644 --- a/common/src/main/java/ctbrec/sites/fc2live/Fc2HttpClient.java +++ b/common/src/main/java/ctbrec/sites/fc2live/Fc2HttpClient.java @@ -2,11 +2,17 @@ package ctbrec.sites.fc2live; import java.io.IOException; +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.FormBody; import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; import okhttp3.WebSocket; import okhttp3.WebSocketListener; @@ -20,81 +26,63 @@ public class Fc2HttpClient extends HttpClient { @Override public boolean login() throws IOException { - // if(loggedIn) { - // return true; - // } - // - // if(checkLogin()) { - // loggedIn = true; - // LOG.debug("Logged in with cookies"); - // return true; - // } - // - // String username = Config.getInstance().getSettings().mfcUsername; - // String password = Config.getInstance().getSettings().mfcPassword; - // RequestBody body = new FormBody.Builder() - // .add("username", username) - // .add("password", password) - // .add("tz", "2") - // .add("ss", "1920x1080") - // .add("submit_login", "97") - // .build(); - // Request req = new Request.Builder() - // .url(Fc2Live.BASE_URL + "/php/login.php") - // .header("Referer", Fc2Live.BASE_URL) - // .header("Content-Type", "application/x-www-form-urlencoded") - // .post(body) - // .build(); - // Response resp = execute(req); - // if(resp.isSuccessful()) { - // String page = resp.body().string(); - // if(page.contains("Your username or password are incorrect")) { - // return false; - // } else { - // loggedIn = true; - // return true; - // } - // } else { - // resp.close(); - // LOG.error("Login failed {} {}", resp.code(), resp.message()); - // return false; - // } - return false; + if(loggedIn) { + return true; + } + + if(checkLogin()) { + loggedIn = true; + LOG.debug("Logged in with cookies"); + return true; + } + + String username = Config.getInstance().getSettings().fc2liveUsername; + String password = Config.getInstance().getSettings().fc2livePassword; + RequestBody body = new FormBody.Builder() + .add("email", username) + .add("pass", password) + .add("image.x", "0") + .add("image.y", "0") + .add("done", "") + .build(); + Request req = new Request.Builder() + .url("https://secure.id.fc2.com/index.php?mode=login&switch_language=en") + .header("Referer", "https://fc2.com/en/login.php") + .header("Content-Type", "application/x-www-form-urlencoded") + .post(body) + .build(); + try(Response resp = execute(req)) { + if(resp.isSuccessful()) { + String page = resp.body().string(); + if(page.contains("Invalid e-mail address or password")) { + return false; + } else { + loggedIn = true; + return true; + } + } else { + resp.close(); + LOG.error("Login failed {} {}", resp.code(), resp.message()); + return false; + } + } } private boolean checkLogin() throws IOException { - // Request req = new Request.Builder().url(Fc2Live.BASE_URL + "/php/account.php?request=status").build(); - // try(Response response = execute(req)) { - // if(response.isSuccessful()) { - // String content = response.body().string(); - // try { - // Elements tags = HtmlParser.getTags(content, "div.content > p > b"); - // tags.get(2).text(); - // return true; - // } catch(Exception e) { - // LOG.debug("Token tag not found. Login failed"); - // return false; - // } - // } else { - // throw new HttpException(response.code(), response.message()); - // } - // } - return false; + Request req = new Request.Builder().url(Fc2Live.BASE_URL + "/api/favoriteManager.php").build(); + try (Response response = execute(req)) { + if (response.isSuccessful()) { + String content = response.body().string(); + JSONObject json = new JSONObject(content); + return json.optInt("status") == 1; + } else { + throw new HttpException(response.code(), response.message()); + } + } } + @Override public WebSocket newWebSocket(Request req, WebSocketListener webSocketListener) { return client.newWebSocket(req, webSocketListener); } - - // public Cookie getCookie(String name) { - // CookieJar jar = client.cookieJar(); - // HttpUrl url = HttpUrl.parse(MyFreeCams.BASE_URI); - // List cookies = jar.loadForRequest(url); - // for (Cookie cookie : cookies) { - // if(Objects.equals(cookie.name(), name)) { - // return cookie; - // } - // } - // throw new NoSuchElementException("No cookie with name " + name); - // } } diff --git a/common/src/main/java/ctbrec/sites/fc2live/Fc2Live.java b/common/src/main/java/ctbrec/sites/fc2live/Fc2Live.java index a795b00e..91c3e51a 100644 --- a/common/src/main/java/ctbrec/sites/fc2live/Fc2Live.java +++ b/common/src/main/java/ctbrec/sites/fc2live/Fc2Live.java @@ -2,6 +2,7 @@ package ctbrec.sites.fc2live; import java.io.IOException; +import ctbrec.Config; import ctbrec.Model; import ctbrec.io.HttpClient; import ctbrec.sites.AbstractSite; @@ -46,7 +47,7 @@ public class Fc2Live extends AbstractSite { @Override public boolean login() throws IOException { - return false; + return credentialsAvailable() && getHttpClient().login(); } @Override @@ -75,7 +76,7 @@ public class Fc2Live extends AbstractSite { @Override public boolean supportsFollow() { - return false; + return true; } @Override @@ -85,7 +86,7 @@ public class Fc2Live extends AbstractSite { @Override public boolean credentialsAvailable() { - return false; + return !Config.getInstance().getSettings().fc2liveUsername.isEmpty(); } } diff --git a/common/src/main/java/ctbrec/sites/fc2live/Fc2Model.java b/common/src/main/java/ctbrec/sites/fc2live/Fc2Model.java index ef924c89..f4130d97 100644 --- a/common/src/main/java/ctbrec/sites/fc2live/Fc2Model.java +++ b/common/src/main/java/ctbrec/sites/fc2live/Fc2Model.java @@ -76,15 +76,19 @@ public class Fc2Model extends AbstractModel { .header("User-Agent", Config.getInstance().getSettings().httpUserAgent) .header("X-Requested-With", "XMLHttpRequest") .build(); - LOG.debug("Fetching page {}", url); try(Response resp = getSite().getHttpClient().execute(req)) { if(resp.isSuccessful()) { String msg = resp.body().string(); JSONObject json = new JSONObject(msg); + // LOG.debug(json.toString(2)); JSONObject data = json.getJSONObject("data"); JSONObject channelData = data.getJSONObject("channel_data"); online = channelData.optInt("is_publish") == 1; onlineState = online ? State.ONLINE : State.OFFLINE; + if(channelData.optInt("fee") == 1) { + onlineState = State.PRIVATE; + online = false; + } version = channelData.optString("version"); } else { resp.close(); @@ -182,12 +186,15 @@ public class Fc2Model extends AbstractModel { if(resp.isSuccessful()) { String msg = resp.body().string(); JSONObject json = new JSONObject(msg); - String wssurl = json.getString("url"); - String token = json.getString("control_token"); - callback.accept(token, wssurl); + if(json.has("url")) { + String wssurl = json.getString("url"); + String token = json.getString("control_token"); + callback.accept(token, wssurl); + } else { + throw new IOException("Couldn't determine websocket url"); + } } else { - resp.close(); - throw new IOException("HTTP status " + resp.code() + " " + resp.message()); + throw new HttpException(resp.code(), resp.message()); } } } @@ -207,12 +214,40 @@ public class Fc2Model extends AbstractModel { @Override public boolean follow() throws IOException { - return false; + return followUnfollow("add"); } @Override public boolean unfollow() throws IOException { - return false; + return followUnfollow("remove"); + } + + private boolean followUnfollow(String mode) throws IOException { + if(!getSite().getHttpClient().login()) { + throw new IOException("Login didn't work"); + } + + RequestBody body = new FormBody.Builder() + .add("id", getId()) + .add("mode", mode) + .build(); + Request req = new Request.Builder() + .url(getSite().getBaseUrl() + "/api/favoriteManager.php") + .header("Referer", getUrl()) + .header("Content-Type", "application/x-www-form-urlencoded") + .post(body) + .build(); + try(Response resp = getSite().getHttpClient().execute(req)) { + if(resp.isSuccessful()) { + String content = resp.body().string(); + JSONObject json = new JSONObject(content); + return json.optInt("status") == 1; + } else { + resp.close(); + LOG.error("Login failed {} {}", resp.code(), resp.message()); + return false; + } + } } public void setId(String id) {