package ctbrec.ui.sites.streamray; import static ctbrec.io.HttpConstants.*; import ctbrec.Config; import ctbrec.Model; import ctbrec.StringUtil; import ctbrec.io.HttpException; import ctbrec.sites.streamray.*; import ctbrec.ui.SiteUiFactory; import ctbrec.ui.tabs.PaginatedScheduledService; import java.io.IOException; import java.net.URLEncoder; import java.text.MessageFormat; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; import javafx.concurrent.Task; import okhttp3.Request; import okhttp3.Response; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class StreamrayUpdateService extends PaginatedScheduledService { private static final Logger LOG = LoggerFactory.getLogger(StreamrayUpdateService.class); private static final String API_URL = "https://beta-api.cams.com/won/compressed/"; private Streamray site; private static List modelsList; private static Instant lastListInfoRequest = Instant.EPOCH; private static JSONArray mapping; protected int modelsPerPage = 48; protected Predicate filter; public StreamrayUpdateService(Streamray site, Predicate filter) { this.site = site; this.filter = filter; } @Override protected Task> createTask() { return new Task>() { @Override public List call() throws IOException { return getModelList().stream() .filter(filter) .skip((page - 1) * (long) modelsPerPage) .limit(modelsPerPage) .collect(Collectors.toList()); // NOSONAR } }; } 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(); StreamrayHttpClient client = (StreamrayHttpClient) site.getHttpClient(); Request req = new Request.Builder() .url(API_URL) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(ACCEPT, MIMETYPE_APPLICATION_JSON) .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) .header(REFERER, site.getBaseUrl() + "/") .header(ORIGIN, site.getBaseUrl()) .header(X_REQUESTED_WITH, XML_HTTP_REQUEST) .build(); try (Response response = client.execute(req)) { if (response.isSuccessful()) { List models = new ArrayList<>(); String content = response.body().string(); JSONObject json = new JSONObject(content); JSONArray modelNodes = json.getJSONArray("models"); mapping = json.getJSONArray("mapping"); parseModels(modelNodes, models); return models; } else { throw new HttpException(response.code(), response.message()); } } } private void parseModels(JSONArray jsonModels, List models) { int name_idx = mapping_index("stream_name"); int date_idx = mapping_index("create_date"); int gen_idx = mapping_index("gender"); for (var i = 0; i < jsonModels.length(); i++) { var m = jsonModels.getJSONArray(i); String name = m.optString(name_idx); String gender = m.optString(gen_idx); String reg = m.optString(date_idx); StreamrayModel model = (StreamrayModel) site.createModel(name); try { LocalDate regDate = LocalDate.parse(reg, DateTimeFormatter.BASIC_ISO_DATE); model.setRegDate(regDate); } catch (DateTimeParseException e) { model.setRegDate(LocalDate.EPOCH); } String preview = getPreviewURL(name); model.setPreview(preview); model.setGender(gender); models.add(model); } } private String getPreviewURL(String name) { String lname = name.toLowerCase(); String url = MessageFormat.format("https://images4.streamray.com/images/streamray/won/jpg/{0}/{1}/{2}_640.jpg", lname.substring(0,1), lname.substring(lname.length()-1), lname); try { return MessageFormat.format("https://dynimages.securedataimages.com/unsigned/rs:fill:640::0/g:no/plain/{0}@jpg", URLEncoder.encode(url, "utf-8")); } catch (Exception ex) { return url; } } public void setFilter(Predicate filter) { this.filter = filter; } private int mapping_index(String s) { for (var i = 0; i < mapping.length(); i++) { if (Objects.equals(s, mapping.get(i))) return i; } return -1; } }