package games.strategy.engine.pbem;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.framework.system.HttpProxy;
import games.strategy.net.OpenFileUtility;
import games.strategy.triplea.help.HelpSupport;
import games.strategy.util.Util;
public class TripleAForumPoster extends AbstractForumPoster {
private static final long serialVersionUID = -3380344469767981030L;
public static final String tripleAForumURL = "https://forums.triplea-game.org";
private NameValuePair username;
private NameValuePair password;
@Override
public boolean postTurnSummary(String summary, String title) {
username = new BasicNameValuePair("username", getUsername());
password = new BasicNameValuePair("password", getPassword());
try (CloseableHttpClient client = HttpClients.custom().disableCookieManagement().build()) {
int userID = getUserId(client);
String token = getToken(client, userID);
try {
post(client, token, "### " + title + "\n" + summary);
m_turnSummaryRef = "Sucessfully posted!";
return true;
} finally {
deleteToken(client, userID, token);
}
} catch (Exception e) {
ClientLogger.logQuietly(e);
m_turnSummaryRef = e.getMessage();
}
return false;
}
private void post(CloseableHttpClient client, String token, String text) throws Exception {
HttpPost post = new HttpPost(tripleAForumURL + "/api/v1/topics/" + getTopicId());
addTokenHeader(post, token);
if (m_includeSaveGame && m_saveGameFile != null) {
text += uploadSavegame(client, token);
}
post.setEntity(new UrlEncodedFormEntity(
Arrays.asList(new BasicNameValuePair("content", text)),
StandardCharsets.UTF_8));
HttpProxy.addProxy(post);
client.execute(post);
}
private String uploadSavegame(CloseableHttpClient client, String token) throws Exception {
HttpPost fileUpload = new HttpPost(tripleAForumURL + "/api/v1/util/upload");
fileUpload.setEntity(MultipartEntityBuilder.create()
.addBinaryBody("files[]", m_saveGameFile, ContentType.APPLICATION_OCTET_STREAM, m_saveGameFileName)
.build());
HttpProxy.addProxy(fileUpload);
addTokenHeader(fileUpload, token);
try (CloseableHttpResponse response = client.execute(fileUpload)) {
int status = response.getStatusLine().getStatusCode();
if (status == HttpURLConnection.HTTP_OK) {
String json = Util.getStringFromInputStream(response.getEntity().getContent());
return "\n[Savegame](" + new JSONArray(json).getJSONObject(0).getString("url") + ")";
}
throw new Exception("Failed to upload savegame, server returned Error Code " + status);
}
}
private void deleteToken(CloseableHttpClient client, int userID, String token)
throws ClientProtocolException, IOException {
HttpDelete httpDelete = new HttpDelete(tripleAForumURL + "/api/v1/users/" + userID + "/tokens/" + token);
addTokenHeader(httpDelete, token);
client.execute(httpDelete);
}
private int getUserId(CloseableHttpClient client) throws JSONException, Exception {
JSONObject jsonObject = login(client, Arrays.asList(username, password));
checkUser(client, jsonObject);
return jsonObject.getInt("uid");
}
private void checkUser(CloseableHttpClient client, JSONObject jsonObject) throws JSONException, Exception {
if (jsonObject.has("message")) {
throw new Exception(jsonObject.getString("message"));
}
if (jsonObject.getInt("banned") != 0) {
throw new Exception("Your account is banned from the forum");
}
if (jsonObject.getInt("email:confirmed") != 1) {
throw new Exception("Your email isn't confirmed yet!");
}
}
private JSONObject login(CloseableHttpClient client, List<NameValuePair> entity)
throws ClientProtocolException, IOException {
HttpPost post = new HttpPost(tripleAForumURL + "/api/ns/login");
post.setEntity(new UrlEncodedFormEntity(entity, StandardCharsets.UTF_8));
HttpProxy.addProxy(post);
try (CloseableHttpResponse response = client.execute(post)) {
String rawJSON = Util.getStringFromInputStream(response.getEntity().getContent());
return new JSONObject(rawJSON);
}
}
private String getToken(CloseableHttpClient client, int userId) throws Exception {
HttpPost post = new HttpPost(tripleAForumURL + "/api/v1/users/" + userId + "/tokens");
post.setEntity(new UrlEncodedFormEntity(Arrays.asList(password), StandardCharsets.UTF_8));
HttpProxy.addProxy(post);
try (CloseableHttpResponse response = client.execute(post)) {
String rawJSON = Util.getStringFromInputStream(response.getEntity().getContent());
JSONObject jsonObject = new JSONObject(rawJSON);
if (jsonObject.has("code")) {
String code = jsonObject.getString("code");
if (code.equalsIgnoreCase("ok")) {
return jsonObject.getJSONObject("payload").getString("token");
}
throw new Exception("Failed to retrieve Token. Code: " + code + " Message: " + jsonObject.getString("message"));
}
throw new Exception("Failed to retrieve Token, server did not return correct JSON: " + rawJSON);
}
}
@Override
public boolean supportsSaveGame() {
return true;
}
@Override
public String getDisplayName() {
return "forums.triplea-game.org";
}
@Override
public void viewPosted() {
OpenFileUtility.openURL(tripleAForumURL + "/topic/" + m_topicId);
}
@Override
public String getTestMessage() {
return "Testing... This may take a while";
}
@Override
public IForumPoster doClone() {
final TripleAForumPoster clone = new TripleAForumPoster();
clone.setTopicId(getTopicId());
clone.setIncludeSaveGame(getIncludeSaveGame());
clone.setAlsoPostAfterCombatMove(getAlsoPostAfterCombatMove());
clone.setPassword(getPassword());
clone.setUsername(getUsername());
return clone;
}
@Override
public String getHelpText() {
return HelpSupport.loadHelp("tripleaForum.html");
}
private void addTokenHeader(HttpRequestBase request, String token) {
request.addHeader("Authorization", "Bearer " + token);
}
}