diff --git a/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvTabProvider.java b/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvTabProvider.java index 8bfdc6d7..da580a1e 100644 --- a/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvTabProvider.java +++ b/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvTabProvider.java @@ -2,7 +2,6 @@ package ctbrec.ui.sites.winktv; import ctbrec.sites.winktv.WinkTv; import ctbrec.sites.winktv.WinkTvModel; - import ctbrec.ui.sites.AbstractTabProvider; import ctbrec.ui.tabs.ThumbOverviewTab; import javafx.scene.Scene; @@ -10,7 +9,6 @@ import javafx.scene.control.Tab; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.function.Predicate; public class WinkTvTabProvider extends AbstractTabProvider { @@ -22,7 +20,9 @@ public class WinkTvTabProvider extends AbstractTabProvider { @Override protected List getSiteTabs(Scene scene) { List tabs = new ArrayList<>(); - tabs.add(createTab("Live", m -> !m.isAdult())); + tabs.add(createTab("Live", Predicate.not(WinkTvModel::isAdult))); + // adult streams are only available with korean age verification, you have to be logged in + //tabs.add(createTab("Adult", WinkTvModel::isAdult)); return tabs; } diff --git a/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvUpdateService.java b/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvUpdateService.java index 6efe43ea..99225f14 100644 --- a/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvUpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/winktv/WinkTvUpdateService.java @@ -1,43 +1,32 @@ package ctbrec.ui.sites.winktv; -import static ctbrec.io.HttpConstants.*; - import ctbrec.Config; import ctbrec.Model; import ctbrec.io.HttpException; import ctbrec.sites.winktv.WinkTv; import ctbrec.sites.winktv.WinkTvModel; -import ctbrec.ui.SiteUiFactory; import ctbrec.ui.tabs.PaginatedScheduledService; -import java.io.IOException; -import java.text.MessageFormat; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.stream.Collectors; import javafx.concurrent.Task; +import lombok.extern.slf4j.Slf4j; import okhttp3.FormBody; import okhttp3.Request; -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.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.function.Predicate; + +import static ctbrec.io.HttpConstants.*; + +@Slf4j public class WinkTvUpdateService extends PaginatedScheduledService { - private static final Logger LOG = LoggerFactory.getLogger(WinkTvUpdateService.class); private static final String API_URL = "https://api.winktv.co.kr/v1/live"; - private WinkTv site; - private String url; - private static List modelsList; - private static Instant lastListInfoRequest = Instant.EPOCH; + private final WinkTv site; protected int modelsPerPage = 48; protected Predicate filter; @@ -48,54 +37,46 @@ public class WinkTvUpdateService extends PaginatedScheduledService { @Override protected Task> createTask() { - return new Task>() { + return new Task<>() { @Override public List call() throws IOException { - return getModelList().stream() + return loadModelList() + .stream() .filter(filter) - .skip((page - 1) * (long) modelsPerPage) - .limit(modelsPerPage) - .collect(Collectors.toList()); // NOSONAR + .map(Model.class::cast) + .toList(); } }; } - private List getModelList() throws IOException { - if (Duration.between(lastListInfoRequest, Instant.now()).getSeconds() < 30) { - return Optional.ofNullable(modelsList).orElse(loadModelList()); - } - modelsList = loadModelList(); - return Optional.ofNullable(modelsList).orElse(Collections.emptyList()); - } - private List loadModelList() throws IOException { - LOG.debug("Fetching page {}", API_URL); - lastListInfoRequest = Instant.now(); + int offset = (page - 1) * modelsPerPage; + log.debug("Fetching page {} offset:{}, limit:{}", API_URL, offset, modelsPerPage); + + FormBody body = new FormBody.Builder() - .add("offset", "0") - .add("limit", "500") + .add("offset", String.valueOf(offset)) + .add("limit", String.valueOf(modelsPerPage)) .add("orderBy", "hot") + .add("onlyNewBj", "N") .build(); Request req = new Request.Builder() .url(API_URL) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) - .header(ACCEPT, MIMETYPE_APPLICATION_JSON) + .header(ACCEPT, "*/*") .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .header(X_REQUESTED_WITH, XML_HTTP_REQUEST) - .header(REFERER, site.getBaseUrl() + "/") - .header(ORIGIN, site.getBaseUrl()) .post(body) .build(); try (var response = site.getHttpClient().execute(req)) { if (response.isSuccessful()) { - List models = new ArrayList<>(); + List result = new ArrayList<>(); var content = response.body().string(); var json = new JSONObject(content); if (json.optBoolean("result")) { var modelNodes = json.getJSONArray("list"); - parseModels(modelNodes, models); + parseModels(modelNodes, result); } - return models; + return result; } else { throw new HttpException(response.code(), response.message()); } @@ -106,9 +87,9 @@ public class WinkTvUpdateService extends PaginatedScheduledService { for (var i = 0; i < jsonModels.length(); i++) { var m = jsonModels.getJSONObject(i); String name = m.optString("userId"); - WinkTvModel model = (WinkTvModel) site.createModel(name); + WinkTvModel model = site.createModel(name); model.setDisplayName(m.getString("userNick")); - boolean isAdult = m.optBoolean("isAdult"); + boolean isAdult = m.optBoolean("isAdult"); model.setAdult(isAdult); if (isAdult && m.has("ivsThumbnail")) { model.setPreview(m.optString("ivsThumbnail")); @@ -119,9 +100,9 @@ public class WinkTvUpdateService extends PaginatedScheduledService { if (isLive) models.add(model); } } - + public void setFilter(Predicate filter) { this.filter = filter; } - + } diff --git a/common/src/main/java/ctbrec/sites/winktv/WinkTvModel.java b/common/src/main/java/ctbrec/sites/winktv/WinkTvModel.java index 1f4c4620..1795e3aa 100644 --- a/common/src/main/java/ctbrec/sites/winktv/WinkTvModel.java +++ b/common/src/main/java/ctbrec/sites/winktv/WinkTvModel.java @@ -10,12 +10,13 @@ import ctbrec.io.HttpException; import ctbrec.recorder.download.RecordingProcess; import ctbrec.recorder.download.StreamSource; import ctbrec.recorder.download.hls.MergedFfmpegHlsDownload; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import okhttp3.FormBody; import okhttp3.Request; import okhttp3.Response; import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -25,19 +26,21 @@ import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Optional; import java.util.concurrent.ExecutionException; import static ctbrec.Model.State.*; import static ctbrec.io.HttpConstants.*; import static java.nio.charset.StandardCharsets.UTF_8; +@Slf4j public class WinkTvModel extends AbstractModel { - private static final Logger LOG = LoggerFactory.getLogger(WinkTvModel.class); private int[] resolution = new int[]{0, 0}; + + @Getter + @Setter private boolean adult = false; - private JSONObject modelInfo; + private transient JSONObject modelInfo; private transient Instant lastInfoRequest = Instant.EPOCH; @@ -98,7 +101,7 @@ public class WinkTvModel extends AbstractModel { src.bandwidth = playlist.getStreamInfo().getBandwidth(); src.height = playlist.getStreamInfo().getResolution().height; src.mediaPlaylistUrl = playlist.getUri(); - LOG.trace("Media playlist {}", src.mediaPlaylistUrl); + log.trace("Media playlist {}", src.mediaPlaylistUrl); sources.add(src); } } @@ -106,7 +109,7 @@ public class WinkTvModel extends AbstractModel { } private MasterPlaylist getMasterPlaylist(String url) throws IOException, ParseException, PlaylistException { - LOG.trace("Loading master playlist {}", url); + log.trace("Loading master playlist {}", url); Request req = new Request.Builder() .url(url) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) @@ -153,7 +156,7 @@ public class WinkTvModel extends AbstractModel { String hlsUrl = hls.optString("url"); return hlsUrl; } else { - LOG.debug("Error while get master playlist url for {}: {}", getName(), response.body().string()); + log.debug("Error while get master playlist url for {}: {}", getName(), response.body().string()); throw new HttpException(response.code(), response.message()); } } @@ -176,11 +179,10 @@ public class WinkTvModel extends AbstractModel { } private JSONObject getModelInfo() throws IOException { - if (Duration.between(lastInfoRequest, Instant.now()).getSeconds() < 5) { - return Optional.ofNullable(modelInfo).orElse(new JSONObject()); + if (modelInfo == null || Duration.between(lastInfoRequest, Instant.now()).getSeconds() < 5) { + lastInfoRequest = Instant.now(); + modelInfo = loadModelInfo(); } - lastInfoRequest = Instant.now(); - modelInfo = loadModelInfo(); return modelInfo; } @@ -210,19 +212,6 @@ public class WinkTvModel extends AbstractModel { } } - public String getPreviewURL() throws IOException { - JSONObject json = getModelInfo(); - if (json.has("media")) { - JSONObject media = json.getJSONObject("media"); - return media.optString("ivsThumbnail"); - } - if (json.has("bjInfo")) { - JSONObject info = json.getJSONObject("bjInfo"); - return info.optString("thumbUrl"); - } - return ""; - } - @Override public boolean follow() throws IOException { return false; @@ -233,14 +222,6 @@ public class WinkTvModel extends AbstractModel { return false; } - public boolean isAdult() { - return adult; - } - - public void setAdult(boolean a) { - this.adult = a; - } - @Override public void receiveTip(Double tokens) throws IOException { // not implemented