Archived
0

implement connect to Elite Dangerous Companion

This commit is contained in:
Mo
2015-07-19 00:35:38 +03:00
committed by iMoHax
parent 5109fe89d5
commit 37e147055f
14 changed files with 53269 additions and 1 deletions

View File

@@ -0,0 +1,261 @@
package ru.trader.edce;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Arrays;
import java.util.Date;
import java.util.function.Consumer;
/* Connect to Elite Dangerous Companion
* Thanks Andargor(https://github.com/Andargor) for source on Python
*/
public class EDSession {
private final static Logger LOG = LoggerFactory.getLogger(EDSession.class);
private final static String COMPANION_DOMAIN = "companion.orerve.net";
private final static String LOGIN_URL = "https://" + COMPANION_DOMAIN + "/user/login";
private final static String CONFIRM_URL = "https://" + COMPANION_DOMAIN + "/user/confirm";
private final static String PROFILE_URL = "https://" + COMPANION_DOMAIN + "/profile";
private final static String USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D257";
private final static String COOKIE_FILE = "edce.tmp";
private final String login;
private final String password;
private CookieStore cookieStore;
private CloseableHttpClient httpClient;
private ED_SESSION_STATUS lastStatus;
public EDSession(String login, String password) throws IOException, ClassNotFoundException {
this.login = login;
this.password = password;
this.lastStatus = ED_SESSION_STATUS.LOGIN_REQUIRED;
initClient();
}
private void initClient() throws IOException, ClassNotFoundException {
cookieStore = readCookieStore();
checkCookie();
httpClient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.setUserAgent(USER_AGENT)
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
}
public void login(){
LOG.info("Login to {}, email {}", COMPANION_DOMAIN, login);
HttpUriRequest loginRequest = RequestBuilder.post(LOGIN_URL)
.addParameter("email", login)
.addParameter("password", password)
.build();
EDResponseHandler handler = new EDResponseHandler(content -> {
if (content.contains("verification code")){
LOG.info("Verification code required");
lastStatus = ED_SESSION_STATUS.VERIFICATION_REQUIRED;
} else {
if (content.contains("Password")){
LOG.info("Wrong password or email");
lastStatus = ED_SESSION_STATUS.LOGIN_FAILED;
} else {
lastStatus = ED_SESSION_STATUS.OK;
}
}
});
try {
if (!httpClient.execute(loginRequest, handler)){
lastStatus = ED_SESSION_STATUS.ERROR;
}
} catch (IOException e) {
LOG.error("Error on connect to {}", LOGIN_URL);
LOG.error("", e);
lastStatus = ED_SESSION_STATUS.ERROR;
}
}
public void submitVerifyCode(String code){
LOG.info("Submit verify code to {}", COMPANION_DOMAIN);
HttpUriRequest submitRequest = RequestBuilder.post(CONFIRM_URL)
.addParameter("code", code)
.build();
EDResponseHandler handler = new EDResponseHandler(content -> {
if (content.contains("verification code")){
LOG.info("Wrong verify code");
lastStatus = ED_SESSION_STATUS.VERIFICATION_REQUIRED;
} else {
lastStatus = ED_SESSION_STATUS.OK;
}
});
try {
if (!httpClient.execute(submitRequest, handler)){
lastStatus = ED_SESSION_STATUS.ERROR;
}
} catch (IOException e) {
LOG.error("Error on connect to {}", CONFIRM_URL);
LOG.error("", e);
lastStatus = ED_SESSION_STATUS.ERROR;
}
}
public void readProfile(Consumer<String> contentConsumer){
LOG.info("Submit profile request to {}", COMPANION_DOMAIN);
HttpUriRequest submitRequest = RequestBuilder.get(PROFILE_URL).build();
EDResponseHandler handler = new EDResponseHandler(content -> {
if (lastStatus != ED_SESSION_STATUS.OK){
if (content.contains("verification code")){
LOG.info("Verification code required");
lastStatus = ED_SESSION_STATUS.VERIFICATION_REQUIRED;
} else if (content.contains("Password")) {
LOG.info("Login required");
lastStatus = ED_SESSION_STATUS.LOGIN_REQUIRED;
} else {
contentConsumer.accept(content);
lastStatus = ED_SESSION_STATUS.OK;
}
} else {
contentConsumer.accept(content);
}
});
try {
if (!httpClient.execute(submitRequest, handler)){
lastStatus = ED_SESSION_STATUS.ERROR;
}
} catch (IOException e) {
LOG.error("Error on connect to {}", CONFIRM_URL);
LOG.error("", e);
lastStatus = ED_SESSION_STATUS.ERROR;
}
}
public ED_SESSION_STATUS getLastStatus() {
return lastStatus;
}
public void close() throws IOException {
writeCookieStore(cookieStore);
httpClient.close();
}
private void checkCookie(){
boolean appFound = false, mtkFound = false, midFound = false;
for (Cookie cookie : cookieStore.getCookies()) {
if (COMPANION_DOMAIN.equals(cookie.getDomain())) {
if ("CompanionApp".equals(cookie.getName())) {
appFound = true;
} else if ("mid".equals(cookie.getName())){
midFound = true;
} else if ("mtk".equals(cookie.getName())){
mtkFound = true;
}
if (appFound && mtkFound && midFound){
LOG.debug("Old cookie found, login not required");
lastStatus = ED_SESSION_STATUS.OK;
break;
}
}
}
}
public void clearCookies(){
cookieStore.clear();
}
public void clearExpiredCookies(){
cookieStore.clearExpired(new Date());
}
private static CookieStore readCookieStore() {
LOG.debug("Read cookie store from {}", COOKIE_FILE);
File file = new File(COOKIE_FILE);
BasicCookieStore cookieStore = null;
if (file.exists()) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
cookieStore = (BasicCookieStore) ois.readObject();
cookieStore.clearExpired(new Date());
} catch (ClassNotFoundException | IOException e) {
LOG.warn("Error on read cookie from {}", COOKIE_FILE);
LOG.warn("", e);
}
}
if (cookieStore == null) {
LOG.debug("Not found cookie store, create new");
cookieStore = new BasicCookieStore();
}
return cookieStore;
}
private static void writeCookieStore(CookieStore cookieStore) {
LOG.debug("Write cookie store to {}", COOKIE_FILE);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(COOKIE_FILE))){
oos.writeObject(cookieStore);
oos.flush();
} catch (IOException e) {
LOG.warn("Error on write cookie to {}", COOKIE_FILE);
LOG.warn("", e);
}
}
private class EDResponseHandler implements ResponseHandler<Boolean> {
private final Consumer<String> contentReader;
public EDResponseHandler() {
this(null);
}
public EDResponseHandler(Consumer<String> contentReader) {
this.contentReader = contentReader;
}
private void readContent(HttpEntity entity) throws IOException {
if (contentReader != null) {
String content = EntityUtils.toString(entity);
LOG.debug("Content: {}", content);
contentReader.accept(content);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Content: {}", EntityUtils.toString(entity));
} else {
EntityUtils.consume(entity);
}
}
}
@Override
public Boolean handleResponse(HttpResponse response) throws IOException {
if (LOG.isDebugEnabled()) {
LOG.debug("Response: {}", response.getStatusLine());
LOG.debug("Headers: {}", Arrays.toString(response.getAllHeaders()));
}
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300){
HttpEntity entity = response.getEntity();
if (entity != null){
if ("application/json".equals(entity.getContentType().getValue())){
lastStatus = ED_SESSION_STATUS.OK;
}
readContent(entity);
}
return true;
} else {
LOG.warn("Don't connect, status: {}", response.getStatusLine());
if (LOG.isDebugEnabled()) {
LOG.debug("Content: {}", EntityUtils.toString(response.getEntity()));
}
return false;
}
}
}
}

View File

@@ -0,0 +1,5 @@
package ru.trader.edce;
public enum ED_SESSION_STATUS {
OK, VERIFICATION_REQUIRED, LOGIN_FAILED, ERROR, LOGIN_REQUIRED
}

View File

@@ -0,0 +1,45 @@
package ru.trader.edce;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EDSessionDemo {
private final static Logger LOG = LoggerFactory.getLogger(EDSessionDemo.class);
private static String readLine(String format, Object... args) throws IOException {
if (System.console() != null) {
return System.console().readLine(format, args);
}
System.out.print(String.format(format, args));
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
return reader.readLine();
}
public static void main(String args[]) throws Exception {
LOG.info("Test ED Companion connect");
EDSession edSession = new EDSession("frontier@mail.ru","elite");
if (edSession.getLastStatus() == ED_SESSION_STATUS.OK){
LOG.info("Check get profile");
edSession.readProfile(s ->{});
}
if (edSession.getLastStatus() == ED_SESSION_STATUS.LOGIN_REQUIRED) {
edSession.login();
if (edSession.getLastStatus() == ED_SESSION_STATUS.VERIFICATION_REQUIRED) {
LOG.info("Check verification");
String code = readLine("Verify code:");
edSession.submitVerifyCode(code);
edSession.login();
}
if (edSession.getLastStatus() == ED_SESSION_STATUS.OK) {
LOG.info("Check get profile");
edSession.readProfile(s -> {});
}
}
edSession.close();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,4 +5,4 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n
log4j.logger.ru.trader.edce = DEBUG