167 lines
6.8 KiB
Java
167 lines
6.8 KiB
Java
package ctbrec.ui.sites.camsoda;
|
|
|
|
import ctbrec.Model;
|
|
import ctbrec.StringUtil;
|
|
import ctbrec.io.HttpException;
|
|
import ctbrec.sites.camsoda.Camsoda;
|
|
import ctbrec.sites.camsoda.CamsodaModel;
|
|
import ctbrec.ui.SiteUiFactory;
|
|
import ctbrec.ui.tabs.PaginatedScheduledService;
|
|
import javafx.concurrent.Task;
|
|
import okhttp3.Request;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONObject;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.io.IOException;
|
|
import java.util.*;
|
|
import java.util.function.Predicate;
|
|
import java.util.stream.Collectors;
|
|
|
|
import static ctbrec.Model.State.OFFLINE;
|
|
import static ctbrec.Model.State.ONLINE;
|
|
|
|
public class CamsodaUpdateService extends PaginatedScheduledService {
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(CamsodaUpdateService.class);
|
|
|
|
private final String url;
|
|
private final boolean loginRequired;
|
|
private final Camsoda camsoda;
|
|
int modelsPerPage = 50;
|
|
|
|
private Predicate<CamsodaModel> filter;
|
|
|
|
public CamsodaUpdateService(String url, boolean loginRequired, Camsoda camsoda, Predicate<CamsodaModel> filter) {
|
|
this.url = url;
|
|
this.loginRequired = loginRequired;
|
|
this.camsoda = camsoda;
|
|
this.filter = filter;
|
|
}
|
|
|
|
@Override
|
|
protected Task<List<Model>> createTask() {
|
|
return new Task<>() {
|
|
@Override
|
|
public List<Model> call() throws IOException {
|
|
return loadOnlineModels().stream()
|
|
.sorted((m1, m2) -> (int) (m2.getSortOrder() - m1.getSortOrder()))
|
|
.filter(filter)
|
|
.skip((page - 1) * (long) modelsPerPage)
|
|
.limit(modelsPerPage)
|
|
.collect(Collectors.toList());
|
|
}
|
|
};
|
|
}
|
|
|
|
protected List<CamsodaModel> loadOnlineModels() throws IOException {
|
|
if (loginRequired && StringUtil.isBlank(ctbrec.Config.getInstance().getSettings().camsodaUsername)) {
|
|
return Collections.emptyList();
|
|
} else {
|
|
LOG.debug("Fetching page {}", url);
|
|
if (loginRequired) {
|
|
SiteUiFactory.getUi(camsoda).login();
|
|
}
|
|
var request = new Request.Builder().url(url).build();
|
|
try (var response = camsoda.getHttpClient().execute(request)) {
|
|
if (response.isSuccessful()) {
|
|
return parseModels(Objects.requireNonNull(response.body(), "HTTP response body is null").string());
|
|
} else {
|
|
throw new HttpException(response.code(), response.message());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<CamsodaModel> parseModels(String body) {
|
|
List<CamsodaModel> models = new ArrayList<>();
|
|
var json = new JSONObject(body);
|
|
var template = json.getJSONArray("template");
|
|
var results = json.getJSONArray("results");
|
|
for (var i = 0; i < results.length(); i++) {
|
|
var result = results.getJSONObject(i);
|
|
var templateObject = result.get("tpl");
|
|
try {
|
|
if (templateObject instanceof JSONObject) {
|
|
parseModelFromObject(result, templateObject, template, models);
|
|
} else if (templateObject instanceof JSONArray) {
|
|
parseModelFromArray(templateObject, template, models);
|
|
}
|
|
} catch (Exception e) {
|
|
LOG.warn("Couldn't parse one of the models: {}", result, e);
|
|
}
|
|
}
|
|
return models;
|
|
}
|
|
|
|
private void parseModelFromArray(Object templateObject, JSONArray template, List<CamsodaModel> models) {
|
|
var tpl = (JSONArray) templateObject;
|
|
var name = tpl.getString(getTemplateIndex(template, "username"));
|
|
CamsodaModel model = (CamsodaModel) camsoda.createModel(name);
|
|
model.setSortOrder(tpl.getFloat(getTemplateIndex(template, "sort_value")));
|
|
model.setDescription(tpl.getString(getTemplateIndex(template, "subject_html")));
|
|
var preview = tpl.getString(getTemplateIndex(template, "thumb"));
|
|
if (preview.startsWith("//")) {
|
|
preview = "https:" + preview;
|
|
}
|
|
model.setPreview(preview);
|
|
LOG.info("Preview: {}", preview);
|
|
model.setOnlineStateByStatus(tpl.getString(getTemplateIndex(template, "status")));
|
|
var displayName = tpl.getString(getTemplateIndex(template, "display_name"));
|
|
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
|
|
if (model.getDisplayName().isBlank()) {
|
|
model.setDisplayName(name);
|
|
}
|
|
models.add(model);
|
|
}
|
|
|
|
private void parseModelFromObject(JSONObject result, Object templateObject, JSONArray template, List<CamsodaModel> models) {
|
|
var tpl = (JSONObject) templateObject;
|
|
var name = tpl.getString(Integer.toString(getTemplateIndex(template, "username")));
|
|
CamsodaModel model = (CamsodaModel) camsoda.createModel(name);
|
|
model.setDescription(tpl.getString(Integer.toString(getTemplateIndex(template, "subject_html"))));
|
|
model.setSortOrder(tpl.getFloat(Integer.toString(getTemplateIndex(template, "sort_value"))));
|
|
model.setNew(result.optBoolean("new"));
|
|
model.setGender(tpl.getString(Integer.toString(getTemplateIndex(template, "gender"))));
|
|
var preview = tpl.getString(Integer.toString(getTemplateIndex(template, "thumb")));
|
|
if (preview.startsWith("//")) {
|
|
preview = "https:" + preview;
|
|
}
|
|
model.setPreview(preview);
|
|
var displayName = tpl.getString(Integer.toString(getTemplateIndex(template, "display_name")));
|
|
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
|
|
if (model.getDisplayName().isBlank()) {
|
|
model.setDisplayName(name);
|
|
}
|
|
model.setOnlineState(tpl.getString(Integer.toString(getTemplateIndex(template, "stream_name"))).isEmpty() ? OFFLINE : ONLINE);
|
|
parseStatus(template, tpl, model);
|
|
models.add(model);
|
|
}
|
|
|
|
private void parseStatus(JSONArray template, JSONObject tpl, CamsodaModel model) {
|
|
try {
|
|
var statusIndex = Integer.toString(getTemplateIndex(template, "status"));
|
|
if (tpl.has(statusIndex)) {
|
|
model.setOnlineStateByStatus(tpl.getString(statusIndex));
|
|
}
|
|
} catch (NoSuchElementException e) {
|
|
// that's ok
|
|
}
|
|
}
|
|
|
|
private int getTemplateIndex(JSONArray template, String string) {
|
|
for (var i = 0; i < template.length(); i++) {
|
|
var s = template.getString(i);
|
|
if (Objects.equals(s, string)) {
|
|
return i;
|
|
}
|
|
}
|
|
throw new NoSuchElementException(string + " not found in template: " + template);
|
|
}
|
|
|
|
public void setFilter(Predicate<CamsodaModel> filter) {
|
|
this.filter = filter;
|
|
}
|
|
}
|