package fr.xtof54.jsgo; import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.socketio.client.IO; import com.github.nkzawa.socketio.client.Socket; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.ClientContext; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; /** * Created by xtof2 on 04/06/15. */ public class OGSConnection { final static String ioserver = "http://ggs.online-go.com"; static String atoken = null, rtoken = null; static HttpContext httpctxt = new BasicHttpContext(); static HttpClient httpclient = null; static boolean sendMoveIsSuccess = true; static BasicCookieStore mycookiestore = new BasicCookieStore(); private static int playerid=-1; // to be run on a separate thread public static String getClientIDFromPrivateConfigfile() { String res = null; try { ClassLoader cl = ((Object) GoJsActivity.main).getClass().getClassLoader(); InputStream is = cl.getResourceAsStream("assets/privateconfig.txt"); BufferedReader b = new BufferedReader(new InputStreamReader(is)); for (; ; ) { String s = b.readLine(); if (s == null) break; if (s.startsWith("CLIENTID=")) { res = s.substring(9); break; } } is.close(); } catch (Exception e) { return null; } return res; } public static String getClientSecretFromPrivateConfigfile() { String res = null; try { ClassLoader cl = ((Object) GoJsActivity.main).getClass().getClassLoader(); InputStream is = cl.getResourceAsStream("assets/privateconfig.txt"); BufferedReader b = new BufferedReader(new InputStreamReader(is)); for (; ; ) { String s = b.readLine(); if (s == null) break; if (s.startsWith("CLIENTSECRET=")) { res = s.substring(13); break; } } is.close(); } catch (Exception e) { return null; } return res; } private static void initHttp() { if (httpclient == null) { HttpParams httpparms = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpparms, 6000); HttpConnectionParams.setSoTimeout(httpparms, 6000); httpclient = new DefaultHttpClient(httpparms); } } static void acceptChallenge(String challid) { initHttp(); try { final String cmd = "https://online-go.com/api/v1/me/challenges/" + challid + "/accept/"; HttpPost httppost = new HttpPost(cmd); String header = "Bearer " + atoken; httppost.addHeader("Authorization", header); HttpResponse response = httpclient.execute(httppost, httpctxt); BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); for (; ; ) { String s = fin.readLine(); if (s == null) break; System.out.println("ogsacceptchallenge " + s); } fin.close(); } catch (Exception e) { e.printStackTrace(); } } public static List<String> getNotifications0() { ArrayList<String> newgames2play = new ArrayList<String>(); if (atoken == null) return null; try { initHttp(); final String cmd = "https://online-go.com/api/v1/me/notifications"; HttpGet httpget = new HttpGet(cmd); String header = "Bearer " + atoken; System.out.println("ogs getnotifications header " + header); httpget.addHeader("Authorization", header); HttpResponse response = httpclient.execute(httpget, httpctxt); // retrieve the notifications BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); for (; ; ) { String s = fin.readLine(); System.out.println("ogsnotlog " + s); if (s == null) break; if (s.indexOf("Authentication credentials were not provided") >= 0) { GoJsActivity.main.showMessage("Auth. failed no credentials"); return null; } // TODO: do a real JSON parsing // look for new challenges for (int deb = 0; ; ) { int i = s.indexOf("\"type\": \"challenge\"", deb); if (i < 0) break; deb = i + 8; String challid = null, challenger = null; int i0 = i; { int j = s.lastIndexOf("challenge_id", i); if (j < 0) continue; i = s.indexOf(':', j); if (i < 0) continue; else i += 2; j = s.indexOf(',', i); if (j < 0) continue; challid = s.substring(i, j); } { int j = s.lastIndexOf("username", i0); if (j < 0) continue; i = s.indexOf(':', j); if (i < 0) continue; else i += 3; j = s.indexOf('"', i); if (j < 0) continue; challenger = s.substring(i, j); } System.out.println("ogs notifications found challengeid " + challid + " " + challenger); if (challenger != null && challid != null) { final String chid = challid; GUI.askUser("Challenge from " + challenger + ": accept ?", new GUI.FunctionOK() { @Override public void isOK() { acceptChallenge(chid); } }); } } // look for games where it's my move for (int deb = 0; ; ) { int i = s.indexOf("\"type\": \"yourMove\"", deb); if (i < 0) break; deb = i + 8; int j = s.lastIndexOf("game_id", i); if (j < 0) { GoJsActivity.main.showMessage("ERROR in JSON got from OGS"); return newgames2play; } i = s.indexOf(':', j); if (i < 0) { GoJsActivity.main.showMessage("ERROR in JSON got from OGS"); return newgames2play; } else i += 2; j = s.indexOf(',', i); if (j < 0) { GoJsActivity.main.showMessage("ERROR in JSON got from OGS"); return newgames2play; } String gameid = s.substring(i, j); newgames2play.add(gameid); System.out.println("ogs notifications found gameid "+gameid); { // also get at the same time the player_id int k=s.lastIndexOf("player_id",i); if (k>=0) { j=s.indexOf(':',k); if (j>=0) { i=s.indexOf(',',j); if (i>=0) { try { k = Integer.parseInt(s.substring(j + 1, i).trim()); playerid=k; } catch (Exception e) { System.out.println("ogs WARNING: error parsing playerid "+s); } } } } } } } fin.close(); } catch (Exception e) { e.printStackTrace(); } return newgames2play; } public static void loadGame(String gameid) { // now download the sgf of this game // TODO: try and download ONLY the last opponent move } public static boolean nextGame2play(Game g) { initHttp(); int i = -g.getGameID(); String gid = "" + i; if (downloadGame(gid)) { return true; } else { GoJsActivity.main.showMessage("Error downloading OGS game"); GoJsActivity.main.changeState(GoJsActivity.guistate.nogame); return false; } } public static boolean sendMove(int gameid, String move) { // faut-il mettre tout ca dans un thread ? initHttp(); sendMoveIsSuccess = true; try { final String cmd = "https://online-go.com/api/v1/games/" + gameid + "/move/"; HttpPost httppost = new HttpPost(cmd); String header = "Bearer " + atoken; httppost.addHeader("Authorization", header); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("move", move)); System.out.println("ogs sendmove " + move); UrlEncodedFormEntity entity; entity = new UrlEncodedFormEntity(formparams, "UTF-8"); httppost.setEntity(entity); HttpResponse response = httpclient.execute(httppost, httpctxt); // retrieve the response BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); for (; ; ) { String s = fin.readLine(); if (s == null) break; System.out.println("ogssendmovelog " + s); if (s.indexOf("error") >= 0) sendMoveIsSuccess = false; } fin.close(); } catch (Exception e) { e.printStackTrace(); sendMoveIsSuccess = false; } return sendMoveIsSuccess; } private static String downoadGameReview(String gameid) { try { /* dans api/v1/games/gameid, il y a dans: - moves = tous les coups joues - XXX: le temps restant - last_move: un move ID ?? ... */ final String cmd = "https://online-go.com/api/v1/games/" + gameid + "/reviews/"; HttpGet httpget = new HttpGet(cmd); String header = "Bearer " + atoken; httpget.addHeader("Authorization", header); HttpResponse response = httpclient.execute(httpget, httpctxt); BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); for (; ; ) { String s = fin.readLine(); System.out.println("ogsreviewlog " + s); if (s == null) break; if (s.indexOf("Authentication credentials were not provided") >= 0) { GoJsActivity.main.showMessage("Auth. failed no credentials"); return null; } s = s.trim(); if (s.length() > 0) { // TODO: add the review as sgf comments ? } } fin.close(); return null; } catch (Exception e) { e.printStackTrace(); return null; } } // return true iff download succeeded private static boolean downloadGame(String gid) { // downoadGameReview(gid); try { /* dans api/v1/games/gameid, il y a dans: - moves = tous les coups joues - XXX: le temps restant - last_move: un move ID ?? ... */ final String cmd = "https://online-go.com/api/v1/games/" + gid + "/sgf/"; HttpGet httpget = new HttpGet(cmd); String header = "Bearer " + atoken; httpget.addHeader("Authorization", header); HttpResponse response = httpclient.execute(httpget, httpctxt); // retrieve the game details BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); int gamid = Integer.parseInt(gid); // j'utilise un - pour differencier games de OGS de DGS Game g = new Game(null, -gamid); for (; ; ) { String s = fin.readLine(); // on n'a ici QUE des lignes SGF System.out.println("ogsgamelog " + s); if (s == null) break; if (s.indexOf("Authentication credentials were not provided") >= 0) { GoJsActivity.main.showMessage("Auth. failed no credentials"); return false; } // TODO: rendre Game moins dependant de DGS s = s.trim(); if (s.length() > 0) { // this method does not trigger a local save // but when we'll add the new single user move, this will save the sgf on disk g.addSgfData(s); } } fin.close(); // on a charge tout le SGF GoJsActivity.main.changeState(GoJsActivity.guistate.play); GoJsActivity.main.showMessage("OGS game: your turn !"); GoJsActivity.main.showGame(g); // get chat data connectChat(gamid); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public static void login() { GUI.showWaitingWin(); if (atoken == null) { System.out.println("ogs no access token, trying login..."); login0(); } if (atoken == null) { System.out.println("ogs no access after login. Stopping"); } else { List<String> games2play = getNotifications0(); { // add these games into the main games list List<Game> mainGameList = Game.getGames(); for (String newgame : games2play) { int newgid = Integer.parseInt(newgame); boolean isAlreadyHere = false; for (Game g : mainGameList) { if (g.getGameID() == -newgid) { isAlreadyHere = true; break; } } if (!isAlreadyHere) { Game newg = new Game(null, -newgid); mainGameList.add(newg); } } } // nextGame2play(); } GUI.hideWaitingWin(); } public static boolean login0() { System.out.println("ogs connectchat"); connectChat(123); System.out.println("login0"); String OGSCLIENTID = PrefUtils.getFromPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_CLIENTID, null); if (OGSCLIENTID == null) { OGSCLIENTID = getClientIDFromPrivateConfigfile(); System.out.println("ogs found client " + OGSCLIENTID); if (OGSCLIENTID == null) { GoJsActivity.main.showMessage("You cannot connect to OGS with the app coming from F-Droid ! Please rather install: http://talc1.loria.fr/users/cerisara/DragonGoApp.apk"); return false; } else PrefUtils.saveToPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_CLIENTID, OGSCLIENTID); } String OGSCLIENTSECRET = PrefUtils.getFromPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_CLIENTSECRET, null); if (OGSCLIENTSECRET == null) { OGSCLIENTSECRET = getClientSecretFromPrivateConfigfile(); System.out.println("ogs found secret " + OGSCLIENTID); if (OGSCLIENTID == null) { GoJsActivity.main.showMessage("You cannot connect to OGS with the app coming from F-Droid ! Please rather install: http://talc1.loria.fr/users/cerisara/DragonGoApp.apk"); return false; } else PrefUtils.saveToPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_CLIENTSECRET, OGSCLIENTSECRET); } final String pwd = PrefUtils.getFromPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_PASSWD, null); if (pwd == null) GoJsActivity.main.showMessage("You must first create an application-specific password on online-go.com," + "and enter this password in this app Settings menu"); else { final String user = PrefUtils.getFromPrefs(GoJsActivity.main.getApplicationContext(), PrefUtils.PREFS_LOGIN_OGS_USERNAME, null); if (user == null) GoJsActivity.main.showMessage("You must first enter your OGS credentials via the Settings menu"); else { System.out.println("all info is here:"); System.out.println("OGSuser " + user); System.out.println("OGSpwd " + pwd); System.out.println("login to OGS server"); httpctxt.setAttribute(ClientContext.COOKIE_STORE, mycookiestore); initHttp(); try { String cmd = "https://online-go.com/oauth2/access_token"; List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("client_id", OGSCLIENTID)); formparams.add(new BasicNameValuePair("client_secret", OGSCLIENTSECRET)); formparams.add(new BasicNameValuePair("grant_type", "password")); formparams.add(new BasicNameValuePair("username", user)); formparams.add(new BasicNameValuePair("password", pwd)); UrlEncodedFormEntity entity; entity = new UrlEncodedFormEntity(formparams, "UTF-8"); HttpPost httppost = new HttpPost(cmd); httppost.setEntity(entity); HttpResponse response = httpclient.execute(httppost, httpctxt); // retrieve the access token from the response BufferedReader fin = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8"))); for (; ; ) { String s = fin.readLine(); if (s == null) break; System.out.println("ogslog " + s); s = s.trim(); if (s.indexOf("error") >= 0) { GoJsActivity.main.showMessage("ERROR login OGS " + s); } else { // retrieve the token int i = s.indexOf("access_token"); if (i < 0) { GoJsActivity.main.showMessage("ERROR login OGS " + s); } else { int j = s.indexOf(':', i); i = s.indexOf('"', j) + 1; j = s.indexOf('"', i); atoken = s.substring(i, j); i = s.indexOf("refresh_token"); if (i >= 0) { j = s.indexOf(':', i); i = s.indexOf('"', j) + 1; j = s.indexOf('"', i); rtoken = s.substring(i, j); } else rtoken = null; return true; } } } fin.close(); } catch (Exception e) { e.printStackTrace(); } } } return false; } static void connectChat(final int gameid) { try { final Socket socket = IO.socket(ioserver); socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() { @Override public void call(Object... args) { System.out.println("PASS HERE"); try { JSONObject parms = new JSONObject(); parms.put("game_id", gameid); parms.put("player_id", 1); parms.put("chat", true); socket.emit("game/connect", parms); } catch (Exception e) { e.printStackTrace(); } } }).on("game/"+gameid+"/gamedata", new Emitter.Listener() { @Override public void call(Object... args) { JSONObject obj = (JSONObject) args[0]; System.out.println("PASS HEREZ " + obj); socket.disconnect(); } }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() { @Override public void call(Object... args) { System.out.println("PASS HEREGG"); } }); socket.connect(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) { System.out.println("dbug"); } }