Implement follow/unfollow for Flirt4Free
This commit is contained in:
parent
8f5c7ac9c4
commit
204eb99b29
|
@ -495,7 +495,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
|||
LOG.error("An error occured while sending tip", ex);
|
||||
showError("Couldn't send tip", "An error occured while sending tip:", ex);
|
||||
} catch (Exception ex) {
|
||||
showError("Couldn't send tip", "You entered an invalid amount of tokens", null);
|
||||
showError("Couldn't send tip", "You entered an invalid amount of tokens", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package ctbrec.ui.sites.flirt4free;
|
||||
|
||||
import ctbrec.sites.flirt4free.Flirt4Free;
|
||||
import ctbrec.ui.FollowedTab;
|
||||
import ctbrec.ui.ThumbOverviewTab;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
|
||||
public class Flirt4FreeFavoritesTab extends ThumbOverviewTab implements FollowedTab {
|
||||
|
||||
public Flirt4FreeFavoritesTab(Flirt4Free flirt4free) {
|
||||
super("Favorites", new Flirt4FreeFavoritesUpdateService(flirt4free), flirt4free);
|
||||
}
|
||||
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package ctbrec.ui.sites.flirt4free;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.io.HtmlParser;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.sites.flirt4free.Flirt4Free;
|
||||
import ctbrec.sites.flirt4free.Flirt4FreeModel;
|
||||
import ctbrec.ui.PaginatedScheduledService;
|
||||
import ctbrec.ui.SiteUiFactory;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService {
|
||||
private Flirt4Free flirt4free;
|
||||
|
||||
public Flirt4FreeFavoritesUpdateService(Flirt4Free flirt4free) {
|
||||
this.flirt4free = flirt4free;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<List<Model>> createTask() {
|
||||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
List<Model> models = new ArrayList<>();
|
||||
String url = flirt4free.getBaseUrl() + "/my-account/secure/favorites.php?a=models&sort=online&pg=" + page;
|
||||
SiteUiFactory.getUi(flirt4free).login();
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Referer", flirt4free.getBaseUrl())
|
||||
.header("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try(Response response = flirt4free.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
Elements modelContainers = HtmlParser.getTags(body, "div.model-container");
|
||||
for (Element modelContainer : modelContainers) {
|
||||
String modelHtml = modelContainer.html();
|
||||
Element bioLink = HtmlParser.getTag(modelHtml, "a.common-link");
|
||||
bioLink.setBaseUri(flirt4free.getBaseUrl());
|
||||
Flirt4FreeModel model = (Flirt4FreeModel) flirt4free.createModelFromUrl(bioLink.absUrl("href"));
|
||||
Element img = HtmlParser.getTag(modelHtml, "a > img[alt]");
|
||||
model.setDisplayName(img.attr("alt"));
|
||||
model.setPreview(img.attr("src"));
|
||||
model.setDescription("");
|
||||
model.setOnline(modelHtml.contains("I'm Online"));
|
||||
try {
|
||||
model.setOnlineState(model.isOnline() ? Model.State.ONLINE : Model.State.OFFLINE);
|
||||
} catch (ExecutionException | InterruptedException e) {}
|
||||
models.add(model);
|
||||
}
|
||||
return models;
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -13,9 +13,12 @@ import javafx.util.Duration;
|
|||
public class Flirt4FreeTabProvider extends TabProvider {
|
||||
|
||||
private Flirt4Free flirt4Free;
|
||||
private ThumbOverviewTab followedTab;
|
||||
|
||||
public Flirt4FreeTabProvider(Flirt4Free flirt4Free) {
|
||||
this.flirt4Free = flirt4Free;
|
||||
followedTab = new Flirt4FreeFavoritesTab(flirt4Free);
|
||||
followedTab.setRecorder(flirt4Free.getRecorder());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,12 +27,13 @@ public class Flirt4FreeTabProvider extends TabProvider {
|
|||
tabs.add(createTab("Girls", flirt4Free.getBaseUrl() + "/live/girls/"));
|
||||
tabs.add(createTab("Boys", flirt4Free.getBaseUrl() + "/live/guys/"));
|
||||
tabs.add(createTab("Trans", flirt4Free.getBaseUrl() + "/live/trans/"));
|
||||
tabs.add(followedTab);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tab getFollowedTab() {
|
||||
return null;
|
||||
return followedTab;
|
||||
}
|
||||
|
||||
private ThumbOverviewTab createTab(String title, String url) {
|
||||
|
|
|
@ -9,8 +9,6 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
|
@ -23,7 +21,6 @@ import okhttp3.Response;
|
|||
|
||||
public class Flirt4Free extends AbstractSite {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(Flirt4Free.class);
|
||||
public static final String BASE_URI = "https://www.flirt4free.com";
|
||||
private HttpClient httpClient;
|
||||
|
||||
|
@ -106,12 +103,12 @@ public class Flirt4Free extends AbstractSite {
|
|||
|
||||
@Override
|
||||
public boolean supportsTips() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFollow() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -47,6 +49,9 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
int[] resolution = new int[2];
|
||||
private Object monitor = new Object();
|
||||
private boolean online = false;
|
||||
private boolean isInteractiveShow = false;
|
||||
private String userIdt = "";
|
||||
private String userIp = "0.0.0.0";
|
||||
|
||||
@Override
|
||||
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
|
||||
|
@ -63,6 +68,7 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
try(Response response = getSite().getHttpClient().execute(request)) {
|
||||
if(response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(response.body().string());
|
||||
//LOG.debug("check model status: {}", json.toString(2));
|
||||
online = Objects.equals(json.optString("status"), "online");
|
||||
id = json.getString("model_id");
|
||||
if(online) {
|
||||
|
@ -96,6 +102,7 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
if(response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(response.body().string());
|
||||
if(json.optString("status").equals("success")) {
|
||||
//LOG.debug("chat-room-interface {}", json.toString(2));
|
||||
JSONObject config = json.getJSONObject("config");
|
||||
JSONObject performer = config.getJSONObject("performer");
|
||||
setName(performer.optString("name_seo", "n/a"));
|
||||
|
@ -105,6 +112,8 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
chatHost = room.getString("host");
|
||||
chatPort = room.getString("port_to_be");
|
||||
chatToken = json.getString("token_enc");
|
||||
JSONObject user = config.getJSONObject("user");
|
||||
userIp = user.getString("ip");
|
||||
} else {
|
||||
LOG.trace("Loading model info failed. Assuming model {} is offline", getName());
|
||||
online = false;
|
||||
|
@ -193,10 +202,20 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
public void onMessage(WebSocket webSocket, String text) {
|
||||
LOG.trace("Chat wbesocket for {}: {}", getName(), text);
|
||||
JSONObject json = new JSONObject(text);
|
||||
//LOG.debug("WS {}", text);
|
||||
if (json.optString("command").equals("8011")) {
|
||||
JSONObject data = json.getJSONObject("data");
|
||||
streamHost = data.getString("stream_host");
|
||||
streamHost = data.getString("stream_host"); // TODO look, if the stream_host is equal to the one encoded in base64 in some of the ajax requests (parameters)
|
||||
online = true;
|
||||
isInteractiveShow = data.optString("devices").equals("1");
|
||||
if(data.optString("room_state").equals("P")) {
|
||||
onlineState = Model.State.PRIVATE;
|
||||
online = false;
|
||||
}
|
||||
if(data.optString("room_state").equals("0") && data.optString("login_group_id").equals("14")) {
|
||||
onlineState = Model.State.GROUP;
|
||||
online = false;
|
||||
}
|
||||
try {
|
||||
resolution[0] = Integer.parseInt(data.getString("stream_width"));
|
||||
resolution[1] = Integer.parseInt(data.getString("stream_height"));
|
||||
|
@ -239,6 +258,82 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
|
||||
@Override
|
||||
public void receiveTip(Double tokens) throws IOException {
|
||||
// if(tokens < 50 || tokens > 750000) {
|
||||
// throw new RuntimeException("Tip amount has to be between 50 and 750000");
|
||||
// }
|
||||
|
||||
// make sure we are logged in and all necessary model data is available
|
||||
getSite().login();
|
||||
try {
|
||||
loadStreamUrl();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Couldn't send tip", e);
|
||||
}
|
||||
|
||||
// send the tip
|
||||
int giftId = isInteractiveShow ? 775 : 171;
|
||||
int amount = tokens.intValue();
|
||||
LOG.debug("Sending tip of {} to {}", amount, getName());
|
||||
String url = "https://ws.vs3.com/rooms/send-tip.php?" +
|
||||
"gift_id=" + giftId +
|
||||
"&num_credits=" + amount +
|
||||
"&userId=" + getUserIdt() +
|
||||
"&username=" + Config.getInstance().getSettings().flirt4freeUsername +
|
||||
"&userIP=" + userIp +
|
||||
"&anonymous=N&response_type=json" +
|
||||
"&t=" + System.currentTimeMillis();
|
||||
LOG.debug("Trying to send tip: {}", url);
|
||||
Request req = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Referer", getUrl())
|
||||
.header("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
||||
.header("Referer", getUrl())
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.build();
|
||||
try (Response response = getSite().getHttpClient().execute(req)) {
|
||||
if(response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(response.body().string());
|
||||
if(json.optInt("success") != 1) {
|
||||
String msg = json.optString("message");
|
||||
if(json.has("error_message")) {
|
||||
msg = json.getString("error_message");
|
||||
}
|
||||
LOG.error("Sending tip failed: {}", msg);
|
||||
LOG.debug("Response: {}", json.toString(2));
|
||||
throw new IOException(msg);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getUserIdt() throws IOException {
|
||||
if(userIdt.isEmpty()) {
|
||||
Request req = new Request.Builder()
|
||||
.url(getUrl())
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Referer", getUrl())
|
||||
.header("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = getSite().getHttpClient().execute(req)) {
|
||||
if(response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
Matcher m = Pattern.compile("idt\\s*:\\s*'(.*?)',").matcher(body);
|
||||
if(m.find()) {
|
||||
userIdt = m.group(1);
|
||||
} else {
|
||||
throw new IOException("userIdt not found on HTML page");
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
return userIdt;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -262,12 +357,44 @@ public class Flirt4FreeModel extends AbstractModel {
|
|||
|
||||
@Override
|
||||
public boolean follow() throws IOException {
|
||||
return false;
|
||||
return changeFavoriteStatus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unfollow() throws IOException {
|
||||
return false;
|
||||
try {
|
||||
isOnline(true);
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
throw new IOException("Couldn't rectrieve model id", e);
|
||||
}
|
||||
return changeFavoriteStatus(false);
|
||||
}
|
||||
|
||||
private boolean changeFavoriteStatus(boolean add) throws IOException {
|
||||
getSite().login();
|
||||
loadModelInfo();
|
||||
String url = getSite().getBaseUrl() + "/external.php?a=" +
|
||||
(add ? "add_favorite" : "delete_favorite") +
|
||||
"&id=" + id +
|
||||
"&name=" + getDisplayName() +
|
||||
"&t=" + System.currentTimeMillis();
|
||||
LOG.debug("Sending follow/unfollow request: {}", url);
|
||||
Request req = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Referer", getUrl())
|
||||
.header("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = getSite().getHttpClient().execute(req)) {
|
||||
if(response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
LOG.debug("Follow/Unfollow response: {}", body);
|
||||
return Objects.equals(body, "1");
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
|
|
Loading…
Reference in New Issue