From 00692f991e6ca8fd90f575701e3a2dac8a91ca9e Mon Sep 17 00:00:00 2001 From: 0xboobface <0xboobface@gmail.com> Date: Mon, 28 Jan 2019 13:00:54 +0100 Subject: [PATCH] Add UI part for MVLive At the moment only the thumbnail overview is working. More stuff to come... --- .../java/ctbrec/ui/CamrecApplication.java | 2 + .../main/java/ctbrec/ui/SiteUiFactory.java | 5 ++ .../ui/sites/manyvids/MVLiveSiteUi.java | 35 ++++++++ .../ui/sites/manyvids/MVLiveTabProvider.java | 40 +++++++++ .../sites/manyvids/MVLiveUpdateService.java | 84 +++++++++++++++++++ .../java/ctbrec/sites/manyvids/MVLive.java | 5 +- .../ctbrec/sites/manyvids/MVLiveModel.java | 21 ++--- 7 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveSiteUi.java create mode 100644 client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveTabProvider.java create mode 100644 client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveUpdateService.java diff --git a/client/src/main/java/ctbrec/ui/CamrecApplication.java b/client/src/main/java/ctbrec/ui/CamrecApplication.java index dd402d03..4143697c 100644 --- a/client/src/main/java/ctbrec/ui/CamrecApplication.java +++ b/client/src/main/java/ctbrec/ui/CamrecApplication.java @@ -47,6 +47,7 @@ import ctbrec.sites.chaturbate.Chaturbate; import ctbrec.sites.fc2live.Fc2Live; import ctbrec.sites.flirt4free.Flirt4Free; import ctbrec.sites.jasmin.LiveJasmin; +import ctbrec.sites.manyvids.MVLive; import ctbrec.sites.mfc.MyFreeCams; import ctbrec.sites.showup.Showup; import ctbrec.sites.streamate.Streamate; @@ -114,6 +115,7 @@ public class CamrecApplication extends Application { sites.add(new Fc2Live()); sites.add(new Flirt4Free()); sites.add(new LiveJasmin()); + sites.add(new MVLive()); sites.add(new MyFreeCams()); sites.add(new Showup()); sites.add(new Streamate()); diff --git a/client/src/main/java/ctbrec/ui/SiteUiFactory.java b/client/src/main/java/ctbrec/ui/SiteUiFactory.java index 5cc25734..169da4f3 100644 --- a/client/src/main/java/ctbrec/ui/SiteUiFactory.java +++ b/client/src/main/java/ctbrec/ui/SiteUiFactory.java @@ -71,6 +71,11 @@ public class SiteUiFactory { flirt4FreeSiteUi = new Flirt4FreeSiteUi((Flirt4Free) site); } return flirt4FreeSiteUi; + } else if (site instanceof MVLive) { + if (mvLiveSiteUi == null) { + mvLiveSiteUi = new MVLiveSiteUi((MVLive) site); + } + return mvLiveSiteUi; } else if (site instanceof MyFreeCams) { if (mfcSiteUi == null) { mfcSiteUi = new MyFreeCamsSiteUi((MyFreeCams) site); diff --git a/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveSiteUi.java b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveSiteUi.java new file mode 100644 index 00000000..aed59d69 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveSiteUi.java @@ -0,0 +1,35 @@ +package ctbrec.ui.sites.manyvids; + +import java.io.IOException; + +import ctbrec.sites.ConfigUI; +import ctbrec.sites.manyvids.MVLive; +import ctbrec.ui.TabProvider; +import ctbrec.ui.sites.AbstractSiteUi; + +public class MVLiveSiteUi extends AbstractSiteUi { + + private MVLiveTabProvider tabProvider; + private MVLive mvlive; + + public MVLiveSiteUi(MVLive mvlive) { + this.mvlive = mvlive; + tabProvider = new MVLiveTabProvider(mvlive); + } + + @Override + public TabProvider getTabProvider() { + return tabProvider; + } + + @Override + public ConfigUI getConfigUI() { + return null; + } + + @Override + public boolean login() throws IOException { + return false; + } + +} diff --git a/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveTabProvider.java b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveTabProvider.java new file mode 100644 index 00000000..905dad36 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveTabProvider.java @@ -0,0 +1,40 @@ +package ctbrec.ui.sites.manyvids; + +import java.util.ArrayList; +import java.util.List; + +import ctbrec.sites.manyvids.MVLive; +import ctbrec.ui.TabProvider; +import ctbrec.ui.ThumbOverviewTab; +import javafx.scene.Scene; +import javafx.scene.control.Tab; + +public class MVLiveTabProvider extends TabProvider { + + private MVLive mvlive; + + public MVLiveTabProvider(MVLive mvlive) { + this.mvlive = mvlive; + + } + + @Override + public List getTabs(Scene scene) { + List tabs = new ArrayList<>(); + tabs.add(createTab("Online", mvlive.getBaseUrl() + "/MVLive/")); + return tabs; + } + + private Tab createTab(String title, String url) { + MVLiveUpdateService updateService = new MVLiveUpdateService(url, mvlive); + ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, mvlive); + tab.setRecorder(mvlive.getRecorder()); + return tab; + } + + @Override + public Tab getFollowedTab() { + return null; + } + +} diff --git a/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveUpdateService.java b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveUpdateService.java new file mode 100644 index 00000000..ce27b24b --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/manyvids/MVLiveUpdateService.java @@ -0,0 +1,84 @@ +package ctbrec.ui.sites.manyvids; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ctbrec.Config; +import ctbrec.Model; +import ctbrec.io.HtmlParser; +import ctbrec.io.HttpException; +import ctbrec.sites.manyvids.MVLive; +import ctbrec.sites.manyvids.MVLiveModel; +import ctbrec.ui.PaginatedScheduledService; +import javafx.concurrent.Task; +import okhttp3.Request; +import okhttp3.Response; + +public class MVLiveUpdateService extends PaginatedScheduledService { + + private static final transient Logger LOG = LoggerFactory.getLogger(MVLiveUpdateService.class); + private String url; + private MVLive mvlive; + + public MVLiveUpdateService(String url, MVLive mvlive) { + this.url = url; + this.mvlive = mvlive; + } + + @Override + protected Task> createTask() { + return new Task>() { + @Override + public List call() throws IOException { + LOG.debug("Fetching page {}", url); + Request request = new Request.Builder() + .url(url) + .header("User-Agent", Config.getInstance().getSettings().httpUserAgent) + .header("Referer", MVLive.BASE_URL) + .build(); + try (Response response = mvlive.getHttpClient().execute(request)) { + if (response.isSuccessful()) { + List models = new ArrayList<>(); + String content = response.body().string(); + Elements cards = HtmlParser.getTags(content, "div.live-room"); + for (Element card : cards) { + try { + String cardHtml = card.html(); + Element link = HtmlParser.getTag(cardHtml, "h5 a"); + MVLiveModel model = (MVLiveModel) mvlive.createModel(link.text().trim()); + model.setUrl(mvlive.getBaseUrl() + link.attr("href")); + Element thumb = HtmlParser.getTag(cardHtml, "a img"); + model.setPreview(thumb.attr("src")); + Element status = HtmlParser.getTag(cardHtml, "div[class~=model-status]"); + String cssClass = status.attr("class"); + if(cssClass.contains("live")) { + model.setOnlineState(Model.State.ONLINE); + } else if(cssClass.contains("private")) { + model.setOnlineState(Model.State.PRIVATE); + } else { + model.setOnlineState(Model.State.UNKNOWN); + } + models.add(model); + } catch(RuntimeException e) { + if(e.getMessage().contains("No element selected by")) { + // ignore + } else { + throw e; + } + } + } + return models; + } else { + throw new HttpException(response.code(), response.message()); + } + } + } + }; + } +} diff --git a/common/src/main/java/ctbrec/sites/manyvids/MVLive.java b/common/src/main/java/ctbrec/sites/manyvids/MVLive.java index 5e65234c..90f1a278 100644 --- a/common/src/main/java/ctbrec/sites/manyvids/MVLive.java +++ b/common/src/main/java/ctbrec/sites/manyvids/MVLive.java @@ -10,7 +10,7 @@ public class MVLive extends AbstractSite { public static final String BASE_URL = "https://www.manyvids.com"; - private MVLiveHttpClient httpClient = new MVLiveHttpClient(); + private MVLiveHttpClient httpClient; @Override public String getName() { @@ -53,6 +53,9 @@ public class MVLive extends AbstractSite { @Override public HttpClient getHttpClient() { + if(httpClient == null) { + httpClient = new MVLiveHttpClient(); + } return httpClient; } diff --git a/common/src/main/java/ctbrec/sites/manyvids/MVLiveModel.java b/common/src/main/java/ctbrec/sites/manyvids/MVLiveModel.java index 04bcfce9..de2f98d0 100644 --- a/common/src/main/java/ctbrec/sites/manyvids/MVLiveModel.java +++ b/common/src/main/java/ctbrec/sites/manyvids/MVLiveModel.java @@ -4,54 +4,51 @@ import java.io.IOException; import java.util.List; import java.util.concurrent.ExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.iheartradio.m3u8.ParseException; import com.iheartradio.m3u8.PlaylistException; import ctbrec.AbstractModel; +import ctbrec.Model; import ctbrec.recorder.download.StreamSource; public class MVLiveModel extends AbstractModel { + private static final transient Logger LOG = LoggerFactory.getLogger(MVLiveModel.class); + @Override public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException { - // TODO Auto-generated method stub - return false; + return getOnlineState(true) == Model.State.ONLINE; } @Override public List getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException { - // TODO Auto-generated method stub + LOG.debug("Loading {}", getUrl()); return null; } @Override public void invalidateCacheEntries() { - // TODO Auto-generated method stub - } @Override public void receiveTip(Double tokens) throws IOException { - // TODO Auto-generated method stub - } @Override public int[] getStreamResolution(boolean failFast) throws ExecutionException { - // TODO Auto-generated method stub - return null; + return new int[2]; } @Override public boolean follow() throws IOException { - // TODO Auto-generated method stub return false; } @Override public boolean unfollow() throws IOException { - // TODO Auto-generated method stub return false; } - }