forked from j62/ctbrec
1
0
Fork 0

Fix Streamate

Streamate introduced a CSRF token, which has to be sent in the HTTP
header.
This commit is contained in:
0xboobface 2020-01-26 18:33:13 +01:00
parent d6574a63b9
commit 18669a9c43
3 changed files with 60 additions and 44 deletions

View File

@ -1,11 +1,8 @@
package ctbrec.ui.sites.streamate; package ctbrec.ui.sites.streamate;
import static ctbrec.io.HttpConstants.*;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathExpressionException;
@ -16,10 +13,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.sites.streamate.Streamate; import ctbrec.sites.streamate.Streamate;
import ctbrec.sites.streamate.StreamateHttpClient;
import ctbrec.sites.streamate.StreamateModel; import ctbrec.sites.streamate.StreamateModel;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
@ -32,11 +29,13 @@ public class StreamateUpdateService extends PaginatedScheduledService {
private static final int MODELS_PER_PAGE = 48; private static final int MODELS_PER_PAGE = 48;
private Streamate streamate; private Streamate streamate;
private StreamateHttpClient httpClient;
private String url; private String url;
public StreamateUpdateService(Streamate streamate, String url) { public StreamateUpdateService(Streamate streamate, String url) {
this.streamate = streamate; this.streamate = streamate;
this.url = url; this.url = url;
this.httpClient = (StreamateHttpClient) streamate.getHttpClient();
} }
@Override @Override
@ -47,14 +46,8 @@ public class StreamateUpdateService extends PaginatedScheduledService {
int from = (page - 1) * MODELS_PER_PAGE; int from = (page - 1) * MODELS_PER_PAGE;
String pageUrl = url + "&from=" + from + "&size=" + MODELS_PER_PAGE; String pageUrl = url + "&from=" + from + "&size=" + MODELS_PER_PAGE;
LOG.debug("Fetching page {}", pageUrl); LOG.debug("Fetching page {}", pageUrl);
Request request = new Request.Builder() Request request = httpClient.newRequestBuilder().url(pageUrl).build();
.url(pageUrl) try (Response response = httpClient.execute(request)) {
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
.addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.addHeader(REFERER, streamate.getBaseUrl())
.build();
try(Response response = streamate.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
List<Model> models = new ArrayList<>(); List<Model> models = new ArrayList<>();
String content = response.body().string(); String content = response.body().string();
@ -68,14 +61,14 @@ public class StreamateUpdateService extends PaginatedScheduledService {
model.setPreview(p.getString("thumbnail")); model.setPreview(p.getString("thumbnail"));
model.setOnline(p.optBoolean("online")); model.setOnline(p.optBoolean("online"));
// TODO figure out, what all the states mean // TODO figure out, what all the states mean
// liveState {} // liveState {}
// exclusiveShow false // exclusiveShow false
// goldShow true // goldShow true
// onBreak false // onBreak false
// partyChat true // partyChat true
// preGoldShow true // preGoldShow true
// privateChat false // privateChat false
// specialShow false // specialShow false
models.add(model); models.add(model);
} }
return models; return models;

View File

@ -1,13 +1,10 @@
package ctbrec.sites.streamate; package ctbrec.sites.streamate;
import static ctbrec.io.HttpConstants.*;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -145,12 +142,7 @@ public class Streamate extends AbstractSite {
@Override @Override
public List<Model> search(String q) throws IOException, InterruptedException { public List<Model> search(String q) throws IOException, InterruptedException {
String url = BASE_URL + "/api/search/autocomplete?exact=false&skin_search_kids=0&results_per_page=10&query=" + URLEncoder.encode(q, "utf-8"); String url = BASE_URL + "/api/search/autocomplete?exact=false&skin_search_kids=0&results_per_page=10&query=" + URLEncoder.encode(q, "utf-8");
Request req = new Request.Builder().url(url) Request req = httpClient.newRequestBuilder().url(url).build();
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
.addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.addHeader(REFERER, Streamate.BASE_URL)
.addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST).build();
try (Response response = getHttpClient().execute(req)) { try (Response response = getHttpClient().execute(req)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String body = response.body().string(); String body = response.body().string();

View File

@ -6,6 +6,8 @@ import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -13,6 +15,8 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpConstants;
import ctbrec.io.HttpException;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.MediaType; import okhttp3.MediaType;
@ -29,6 +33,7 @@ public class StreamateHttpClient extends HttpClient {
private Long userId; private Long userId;
private String saKey = ""; private String saKey = "";
private String userNickname = ""; private String userNickname = "";
private String xsrfToken = null;
public StreamateHttpClient() { public StreamateHttpClient() {
super("streamate"); super("streamate");
@ -48,6 +53,29 @@ public class StreamateHttpClient extends HttpClient {
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
// ignore // ignore
} }
loadXsrfToken();
}
private void loadXsrfToken() {
// do a first request to get cookies and stuff
Request req = new Request.Builder() //
.url(Streamate.BASE_URL) //
.header(HttpConstants.USER_AGENT, Config.getInstance().getSettings().httpUserAgent) //
.build();
try (Response resp = execute(req)) {
if (resp.code() == 200) {
LOG.info("Initial request was fine, Extracting XSRF token");
Matcher m = Pattern.compile("\"xsrfToken\":\"(.*?)\"").matcher(resp.body().string());
if (m.find()) {
xsrfToken = m.group(1);
}
} else {
throw new HttpException(resp.code(), resp.message());
}
} catch (IOException e) {
LOG.error("Initial request failed", e);
}
} }
@Override @Override
@ -74,13 +102,8 @@ public class StreamateHttpClient extends HttpClient {
loginRequest.put("referrerId", 0); loginRequest.put("referrerId", 0);
loginRequest.put("siteId", 1); loginRequest.put("siteId", 1);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), loginRequest.toString()); RequestBody body = RequestBody.create(MediaType.parse("application/json"), loginRequest.toString());
Request login = new Request.Builder() Request login = newRequestBuilder()
.url(Streamate.BASE_URL + "/api/member/login") .url(Streamate.BASE_URL + "/api/member/login")
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
.addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.addHeader(REFERER, Streamate.BASE_URL)
.addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.post(body) .post(body)
.build(); .build();
try (Response response = client.newCall(login).execute()) { try (Response response = client.newCall(login).execute()) {
@ -101,20 +124,24 @@ public class StreamateHttpClient extends HttpClient {
return loggedIn; return loggedIn;
} }
public Request.Builder newRequestBuilder() {
return new Request.Builder() // @formatter:off
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(REFERER, Streamate.BASE_URL)
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.header("X-XSRF-TOKEN", getXsrfToken()); // @formatter:on
}
/** /**
* Check, if the login worked by loading the favorites * Check, if the login worked by loading the favorites
*/ */
public boolean checkLoginSuccess() { public boolean checkLoginSuccess() {
String url = Streamate.BASE_URL + "/api/search/v1/favorites?host=streamate.com&domain=streamate.com"; String url = Streamate.BASE_URL + "/api/search/v1/favorites?host=streamate.com&domain=streamate.com";
url = url + "&page_number=1&results_per_page=48&sakey=" + saKey + "&userid=" + userId; url = url + "&page_number=1&results_per_page=48&sakey=" + saKey + "&userid=" + userId;
Request request = new Request.Builder() Request request = newRequestBuilder().url(url).build();
.url(url) try (Response response = execute(request)) {
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
.addHeader(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.addHeader(REFERER, Streamate.BASE_URL)
.build();
try(Response response = execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String content = response.body().string(); String content = response.body().string();
JSONObject json = new JSONObject(content); JSONObject json = new JSONObject(content);
@ -122,7 +149,7 @@ public class StreamateHttpClient extends HttpClient {
} else { } else {
return false; return false;
} }
} catch(Exception e) { } catch (Exception e) {
return false; return false;
} }
} }
@ -141,4 +168,8 @@ public class StreamateHttpClient extends HttpClient {
public String getUserNickname() { public String getUserNickname() {
return userNickname; return userNickname;
} }
public String getXsrfToken() {
return xsrfToken;
}
} }