Hello tout le monde,
Je viens de débuter un petit projet sur le protocole de Dofus Touch histoire de passer le temps et j'ai passer mon aprem sur la partie connexion.
J'ai donc décidé de vous partager la classe que j'ai utiliser pour mes tests, c'est du Java pour l'implémentation des websocket j'utilise https://github.com/TakahikoKawasaki/nv-websocket-client.
Je vous met en garde le code qui suit est sale, il est seulement la pour vous aider à comprendre les étapes de connexion sur Dofus Touch, il ne gère pas les erreurs, pas thread safe, pas de pattern .....
import domain.AccountEntity;
import domain.ServerEntity;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import util.network.HttpService;
import util.network.WebsocketPrimus;
import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class LoginService {
private final Logger logger = Logger.getLogger(LoginService.class);
private final String sticker;
private final AccountEntity account;
private final ArrayBlockingQueue<JSONObject> messageQueue = new ArrayBlockingQueue<>(2500);
private JSONObject response;
private final HashMap<String, String> headers = new HashMap<>();
private final HttpService http = new HttpService();
public LoginService(String sticker, AccountEntity account) {
this.sticker = sticker;
this.account = account;
}
public Boolean getHaapiInfo() {
try {
logger.debug("########### Retrieve apikey and account data from haapi ###########");
response = http.sendPost("https://haapi.ankama.com/json/Ankama/v2/Api/CreateApiKey", account.getConnectionSyntax());
account.setApiKey(response.getString("key"));
account.setAccount_id(response.getInt("account_id"));
account.setIp(response.getString("ip"));
account.setCountry(response.getJSONObject("data").getString("country"));
account.setCurrency(response.getJSONObject("data").getString("currency"));
account.setRefresh_token(response.getString("refresh_token"));
account.setExpiration_date(response.getString("expiration_date"));
logger.debug("########### Retrieve token from haapi ###########");
headers.put("apikey", account.getApiKey());
response = http.sendGet("https://haapi.ankama.com/json/Ankama/v2/Account/CreateToken?game=18", headers);
account.setToken(response.getString("token"));
return true;
} catch (IllegalStateException e) {
logger.error(e.getMessage());
}
return false;
}
public Boolean websocketConnection() {
try {
logger.debug("########### Websocket Connection ###########");
WebsocketPrimus websocket = new WebsocketPrimus(sticker, messageQueue);
websocket.create("wss://proxyconnection.touch.dofus.com/primus/?STICKER=" + sticker + "&transport=websocket");
websocket.send("2probe");
response = messageQueue.poll(10, TimeUnit.SECONDS);
account.setSid(response.getString("sid"));
websocket.send("{\"call\":\"connecting\",\"data\":{\"language\":\"fr\",\"server\":\"login\",\"client\":\"android\",\"appVersion\":\"1.12.3\",\"buildVersion\":\"1.29.6\"}}");
while (true) {
response = messageQueue.poll(10, TimeUnit.SECONDS);
switch (response.getString("_messageType")) {
case "ProtocolRequired":
logger.debug("requiredVersion: " + response.getInt("requiredVersion") + " currentVersion: " + response.getInt("currentVersion"));
if (response.getInt("requiredVersion") > response.getInt("currentVersion")) {
throw new IllegalStateException("Error requiredVersion > currentVersion update is required");
}
break;
case "HelloConnectMessage":
account.setSalt(response.getString("salt"));
account.setKey(response.get("key").toString());
websocket.send("{\"call\":\"login\",\"data\":{\"username\":\"" + account.getUsername() + "\",\"token\":\"" + account.getToken() + "\",\"salt\":\"" + account.getSalt() + "\",\"key\":" + account.getKey() + "}}");
break;
case "LoginQueueStatusMessage":
logger.info("Position in queue " + response.getInt("position") + "/" + response.getInt("total"));
break;
case "IdentificationSuccessMessage":
account.setLogin(response.getString("login"));
account.setNickname(response.getString("nickname"));
account.setCommunityId(response.getInt("communityId"));
account.setWasAlreadyConnected(response.getBoolean("wasAlreadyConnected"));
break;
case "ServersListMessage":
response.getJSONArray("servers").forEach(item -> {
JSONObject server = (JSONObject) item;
account.getServers().add(new ServerEntity(server.getString("_type"), server.getInt("id"), server.getInt("status"), server.getInt("completion"),
server.getBoolean("isSelectable"), server.getInt("charactersCount"), server.getLong("date"), server.getString("_name"), server.getInt("_gameTypeId")));
});
websocket.send("{\"call\":\"sendMessage\",\"data\":{\"type\":\"ServerSelectionMessage\",\"data\":{\"serverId\":" + account.getServers().get(0).getId() + "}}}");
break;
case "SelectedServerDataMessage":
websocket.send("{\"call\":\"disconnecting\",\"data\":\"SWITCHING_TO_GAME\"}");
return true;
case "IdentificationFailedMessage":
logger.error("Identification Failed reason = " + response.getInt("reason"));
return false;
}
}
} catch (InterruptedException e) {
return false;
}
}
}
Si vous avez des suggestions d'amélioration, des conseils sur les patterns à suivre n'hésiter surtout pas à les partager, encore une fois ce code sert que de base je vous déconseille de l'utiliser tel quel.
Si vous avez besoin de clarification n'hésiter pas à poser vos question sur le forum adapté, à me joindre par mp ou sur Discord.
J'espere que ça vas aider.
-----------------
EDIT: j'ai plus trop le temps de bosser dessus malheureusement, je vous partage le code complet ou je me suis arrêté.