├── Extension ├── Chrome │ ├── css │ ├── js │ └── manifest.json ├── Firefox │ ├── addon │ │ ├── data │ │ │ ├── css │ │ │ └── js │ │ ├── package.json │ │ └── lib │ │ │ └── main.js │ └── install.rdf ├── Safari │ ├── nationstates++.safariextension │ │ ├── css │ │ ├── js │ │ ├── Settings.plist │ │ ├── global.html │ │ └── Info.plist │ └── safari.plist ├── css │ ├── forum.css │ ├── two_column.css │ ├── nationstates++_dark.css │ ├── modern_flat_theme.css │ ├── nouislider.fox.css │ ├── bootstrap-fileupload.min.css │ └── nprogress.css ├── js │ ├── world.js │ ├── forum_post_id.js │ ├── nspp.js │ ├── issues.js │ ├── wa.js │ ├── bootstrap-dropdown.min.js │ ├── happenings.js │ ├── textFit.min.js │ ├── jquery.caret.js │ ├── help.js │ ├── irc.js │ ├── embassy_flags.js │ ├── bootstrap-fileupload.min.js │ ├── alerts.js │ ├── jquery.highlight.js │ ├── jquery.nouislider.min.js │ ├── Blob.js │ └── nprogress.js ├── unminified-js │ └── ga.js ├── html │ ├── banhammer.html │ ├── newspaper_administration.html │ └── newspaper_editor.html ├── nspp.js └── irc.json ├── Assembly ├── public │ ├── stylesheets │ │ └── main.css │ └── images │ │ └── favicon.png ├── project │ ├── build.properties │ ├── activator-sbt-idea-shim.sbt │ ├── activator-sbt-eclipse-shim.sbt │ └── plugins.sbt ├── .target │ └── .gitignore ├── lib │ ├── nsapi-1.0.0-SNAPSHOT.jar │ ├── cereal-1.0.0-SNAPSHOT.jar │ └── ns-dumps-1.0.0-SNAPSHOT.jar ├── README ├── .gitignore ├── app │ ├── net │ │ └── nationstatesplusplus │ │ │ └── assembly │ │ │ ├── amqp │ │ │ ├── AMQPQueue.java │ │ │ ├── EmptyAMQPQueue.java │ │ │ ├── NullAMQPConenctionFactory.java │ │ │ ├── AMQPMessage.java │ │ │ ├── AMQPThread.java │ │ │ └── AMQPConnectionFactory.java │ │ │ ├── nation │ │ │ ├── NationSettings.java │ │ │ ├── DefaultSettings.java │ │ │ └── MongoSettings.java │ │ │ ├── model │ │ │ ├── websocket │ │ │ │ ├── Request.java │ │ │ │ ├── PageType.java │ │ │ │ ├── WebsocketMessage.java │ │ │ │ ├── NationContext.java │ │ │ │ ├── DataRequest.java │ │ │ │ └── NationStatesWebSocket.java │ │ │ ├── page │ │ │ │ ├── DefaultPage.java │ │ │ │ ├── NationStatesPage.java │ │ │ │ ├── RecruitmentAdministrationPage.java │ │ │ │ ├── NationPage.java │ │ │ │ └── RegionPage.java │ │ │ ├── Region.java │ │ │ └── Nation.java │ │ │ ├── util │ │ │ ├── Sha.java │ │ │ └── EncodingUtil.java │ │ │ ├── logging │ │ │ ├── LoggerOutputStream.java │ │ │ └── LoggingFilter.java │ │ │ ├── RecruitmentTargetTask.java │ │ │ ├── Start.java │ │ │ ├── NationUpdateTask.java │ │ │ ├── UpdateOrderTask.java │ │ │ ├── FlagUpdateTask.java │ │ │ ├── RepeatingTaskThread.java │ │ │ └── auth │ │ │ └── Authentication.java │ └── controllers │ │ ├── NationStatesController.java │ │ ├── DatabaseController.java │ │ ├── FlagController.java │ │ ├── AutocompleteController.java │ │ ├── WebSocketController.java │ │ ├── IRCController.java │ │ ├── XenforoController.java │ │ ├── HappeningsController.java │ │ └── NSWikiController.java ├── build.sbt └── conf │ ├── application.conf │ └── application-logger.xml ├── license.txt ├── README.md └── .gitignore /Extension/Chrome/css: -------------------------------------------------------------------------------- 1 | ./../css -------------------------------------------------------------------------------- /Extension/Chrome/js: -------------------------------------------------------------------------------- 1 | ./../js -------------------------------------------------------------------------------- /Assembly/public/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Extension/Firefox/addon/data/css: -------------------------------------------------------------------------------- 1 | ./../../../css -------------------------------------------------------------------------------- /Extension/Firefox/addon/data/js: -------------------------------------------------------------------------------- 1 | ./../../../js -------------------------------------------------------------------------------- /Assembly/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.6 2 | -------------------------------------------------------------------------------- /Extension/Safari/nationstates++.safariextension/css: -------------------------------------------------------------------------------- 1 | ./../../css -------------------------------------------------------------------------------- /Extension/Safari/nationstates++.safariextension/js: -------------------------------------------------------------------------------- 1 | ./../../js -------------------------------------------------------------------------------- /Assembly/.target/.gitignore: -------------------------------------------------------------------------------- 1 | /controllers/ 2 | /models/ 3 | /net/ 4 | -------------------------------------------------------------------------------- /Extension/css/forum.css: -------------------------------------------------------------------------------- 1 | #logoutbox, #loginbannerbox { 2 | margin-top: 8px; 3 | } -------------------------------------------------------------------------------- /Assembly/project/activator-sbt-idea-shim.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.2") -------------------------------------------------------------------------------- /Assembly/project/activator-sbt-eclipse-shim.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.3.0") -------------------------------------------------------------------------------- /Assembly/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NationStates/NationStatesPlusPlus/HEAD/Assembly/public/images/favicon.png -------------------------------------------------------------------------------- /Assembly/lib/nsapi-1.0.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NationStates/NationStatesPlusPlus/HEAD/Assembly/lib/nsapi-1.0.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /Assembly/lib/cereal-1.0.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NationStates/NationStatesPlusPlus/HEAD/Assembly/lib/cereal-1.0.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /Assembly/lib/ns-dumps-1.0.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NationStates/NationStatesPlusPlus/HEAD/Assembly/lib/ns-dumps-1.0.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /Assembly/README: -------------------------------------------------------------------------------- 1 | This is your new Play 2.1 application 2 | ===================================== 3 | 4 | This file will be packaged with your application, when using `play dist`. 5 | -------------------------------------------------------------------------------- /Assembly/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | project/project 3 | project/target 4 | target 5 | tmp 6 | .history 7 | dist 8 | /.idea 9 | /*.iml 10 | /out 11 | /.idea_modules 12 | /.classpath 13 | /.project 14 | /RUNNING_PID 15 | /.settings 16 | /bin 17 | -------------------------------------------------------------------------------- /Extension/Safari/nationstates++.safariextension/Settings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Extension/Firefox/addon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nationstates", 3 | "fullName": "nationstates", 4 | "id": "afforess@gmail.com", 5 | "description": "Enhances the NationStates.net experience", 6 | "author": "Afforess, Eluvatar", 7 | "license": "MIT", 8 | "version": "2.5.1.2" 9 | } 10 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/amqp/AMQPQueue.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.amqp; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | 5 | public interface AMQPQueue { 6 | 7 | public void send(JsonNode node); 8 | 9 | public boolean isShutdown(); 10 | 11 | public void shutdown(); 12 | } 13 | -------------------------------------------------------------------------------- /Assembly/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | // Comment to get more information during initialization 2 | logLevel := Level.Warn 3 | 4 | // The Typesafe repository 5 | resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" 6 | 7 | // Use the Play sbt plugin for Play projects 8 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.2") 9 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/nation/NationSettings.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.nation; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | 5 | public interface NationSettings { 6 | 7 | public V getValue(String name, V defaultVal, Class type); 8 | 9 | public JsonNode querySettings(String query); 10 | 11 | public void updateSettings(JsonNode update); 12 | } 13 | -------------------------------------------------------------------------------- /Extension/js/world.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (getVisiblePage() == "world") { 3 | //Add change region/create region links 4 | var bulletChar = $('
').html(" • ").text(); 5 | $("
Move to a New Region" + bulletChar + "Create a New Region
").insertBefore($("fieldset.featuredregion")); 6 | } 7 | })(); -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/websocket/Request.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.websocket; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import com.fasterxml.jackson.databind.JsonNode; 7 | 8 | public interface Request { 9 | public JsonNode[] executeRequest(Connection conn, DataRequest request, NationContext context) throws SQLException; 10 | } 11 | -------------------------------------------------------------------------------- /Extension/unminified-js/ga.js: -------------------------------------------------------------------------------- 1 | var _gaq = _gaq || []; 2 | function update(delay){ 3 | setTimeout(function() { 4 | _gaq.push(['_setAccount', 'UA-41267101-1']); 5 | _gaq.push(['_trackPageview']); 6 | _gaq.push(['_setCustomVar', 1, 'Version', 'v2.3.0', 2]); 7 | 8 | if (delay == 1) { 9 | _gaq.push(['_trackEvent', 'NationStates', 'URL', window.location.href]); 10 | } 11 | update(60000); 12 | }, delay); 13 | } 14 | update(1); -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/amqp/EmptyAMQPQueue.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.amqp; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | 5 | public class EmptyAMQPQueue implements AMQPQueue { 6 | @Override 7 | public void send(JsonNode node) { 8 | 9 | } 10 | 11 | public boolean isShutdown() { 12 | return false; 13 | } 14 | 15 | @Override 16 | public void shutdown() { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/nation/DefaultSettings.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.nation; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | 5 | public class DefaultSettings implements NationSettings { 6 | @Override 7 | public V getValue(String name, V defaultVal, Class type) { 8 | return defaultVal; 9 | } 10 | 11 | @Override 12 | public JsonNode querySettings(String query) { 13 | return null; 14 | } 15 | 16 | @Override 17 | public void updateSettings(JsonNode update) { 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/page/DefaultPage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.page; 2 | 3 | import net.nationstatesplusplus.assembly.model.websocket.DataRequest; 4 | import net.nationstatesplusplus.assembly.model.websocket.PageType; 5 | import net.nationstatesplusplus.assembly.model.websocket.RequestType; 6 | 7 | public class DefaultPage extends NationStatesPage { 8 | public DefaultPage() { 9 | super(PageType.DEFAULT); 10 | } 11 | 12 | @Override 13 | public void onRequest(RequestType type, DataRequest request) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Extension/js/forum_post_id.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (window.location.href.indexOf("viewtopic.php") != -1) { 3 | $("div.post").each(function() { 4 | var marginLeft = 11 + (8 - $(this).attr("id").substring(1).length) * 4.4; 5 | $(this).find(".profile-icons").prepend("
  • " + $(this).attr("id").substring(1) + "
  • "); 6 | }); 7 | } 8 | 9 | $(".icon-logout").hide(); 10 | })(); -------------------------------------------------------------------------------- /Extension/css/two_column.css: -------------------------------------------------------------------------------- 1 | .colmask { 2 | position:relative; 3 | clear:both; 4 | float:left; 5 | width:100%; 6 | overflow:hidden; 7 | } 8 | .colleft { 9 | float:left; 10 | width:100%; 11 | position:relative; 12 | } 13 | .col1, .col2, .col3 { 14 | float:left; 15 | position:relative; 16 | padding:0 0 0 0; 17 | overflow:hidden; 18 | } 19 | .colleft { 20 | right:25%; 21 | } 22 | .col1 { 23 | width:calc(100% - 220px); 24 | left:25%; 25 | z-index: 2; 26 | } 27 | .col2 { 28 | width:200px; 29 | display:inline; 30 | margin-right:-25%; 31 | float:right; 32 | } -------------------------------------------------------------------------------- /Assembly/app/controllers/NationStatesController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import net.nationstatesplusplus.assembly.util.DatabaseAccess; 4 | 5 | import org.spout.cereal.config.yaml.YamlConfiguration; 6 | 7 | import com.limewoodMedia.nsapi.NationStates; 8 | 9 | public abstract class NationStatesController extends DatabaseController{ 10 | private final NationStates api; 11 | public NationStatesController(DatabaseAccess access, YamlConfiguration config, NationStates api) { 12 | super(access, config); 13 | this.api = api; 14 | } 15 | 16 | public final NationStates getAPI() { 17 | return api; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Extension/js/nspp.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (window.location.href.indexOf("nationstatesplusplus") != -1 && window.location.href.indexOf("api.html") != -1) { 3 | $.get("//www.nationstates.net/page=verify_login?nspp=1", function(data) { 4 | if ($(data).find(".STANDOUT:first").length > 0) { 5 | var nation = $(data).find(".STANDOUT:first").attr("href").substring(7); 6 | var authCode = $(data).find("#proof_of_login_checksum").html(); 7 | $(document.body).append(""); 8 | } else { 9 | $(document.body).append(""); 10 | } 11 | }); 12 | } 13 | })(); -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/util/Sha.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.util; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | public class Sha { 7 | public static String hash256(String data) { 8 | try {MessageDigest md = MessageDigest.getInstance("SHA-256"); 9 | md.update(data.getBytes()); 10 | return bytesToHex(md.digest()); 11 | } catch (NoSuchAlgorithmException e) { 12 | throw new RuntimeException(e); 13 | } 14 | } 15 | 16 | private static String bytesToHex(byte[] bytes) { 17 | StringBuffer result = new StringBuffer(); 18 | for (byte byt : bytes) result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1)); 19 | return result.toString(); 20 | } 21 | } -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/amqp/NullAMQPConenctionFactory.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.amqp; 2 | 3 | import java.io.IOException; 4 | 5 | import com.rabbitmq.client.Channel; 6 | import com.rabbitmq.client.Consumer; 7 | 8 | public class NullAMQPConenctionFactory extends AMQPConnectionFactory { 9 | 10 | public NullAMQPConenctionFactory() { 11 | super(null, 0, null, null, null); 12 | } 13 | 14 | @Override 15 | public AMQPQueue createQueue() throws IOException { 16 | return new EmptyAMQPQueue(); 17 | } 18 | 19 | @Override 20 | public void registerConsumer(Consumer consumer) throws IOException { 21 | 22 | } 23 | 24 | @Override 25 | public Channel createChannel() throws IOException { 26 | throw new UnsupportedOperationException(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Extension/Safari/safari.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Extension Updates 6 | 7 | 8 | CFBundleIdentifier 9 | com.afforess.nationstates 10 | Developer Identifier 11 | 3PTEBHH3QU 12 | CFBundleVersion 13 | 2.5.1.2 14 | CFBundleShortVersionString 15 | 2.5.1.2 16 | URL 17 | https://nationstatesplusplus.net/nationstates/nationstates++.safariextz 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Extension/js/issues.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (getVisiblePage() == "dilemmas") { 3 | (new UserSettings()).child("dismiss_all").on(function(data) { 4 | $("button[name='autodismiss_issues']").remove(); 5 | if (!data["dismiss_all"]) { 6 | $("").insertAfter($("button[name='dismiss_all']")); 7 | } else { 8 | $("").insertAfter($("button[name='dismiss_all']")); 9 | } 10 | }, false); 11 | $("body").on("click", "button[name='autodismiss_issues']", function(event) { 12 | event.preventDefault(); 13 | var enabled = $(this).html() == "Cancel Dismissing All Issues"; 14 | (new UserSettings()).child("dismiss_all").set(!enabled); 15 | $(this).attr("disabled", true); 16 | }); 17 | } 18 | })(); 19 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/amqp/AMQPMessage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.amqp; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import com.fasterxml.jackson.databind.JsonNode; 7 | 8 | @JsonInclude(JsonInclude.Include.NON_NULL) 9 | public class AMQPMessage { 10 | @JsonProperty("serverName") 11 | private final String serverName; 12 | @JsonProperty("message") 13 | private final JsonNode message; 14 | 15 | @JsonCreator 16 | public AMQPMessage(@JsonProperty("serverName") String serverName, @JsonProperty("message") JsonNode message) { 17 | this.serverName = serverName; 18 | this.message = message; 19 | } 20 | 21 | public String getServerName() { 22 | return serverName; 23 | } 24 | 25 | public JsonNode getMessage() { 26 | return message; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/page/NationStatesPage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.page; 2 | 3 | import net.nationstatesplusplus.assembly.model.websocket.DataRequest; 4 | import net.nationstatesplusplus.assembly.model.websocket.PageType; 5 | import net.nationstatesplusplus.assembly.model.websocket.RequestType; 6 | 7 | public abstract class NationStatesPage { 8 | private final PageType type; 9 | public NationStatesPage(PageType type) { 10 | this.type = type; 11 | } 12 | 13 | public final PageType getType() { 14 | return type; 15 | } 16 | 17 | public boolean isValidUpdate(RequestType type, DataRequest request) { 18 | for (RequestType t : this.type.getInitialRequests()) { 19 | if (t == type) 20 | return true; 21 | } 22 | return type == RequestType.KEEP_ALIVE || type == RequestType.GET_SETTING; 23 | } 24 | 25 | public abstract void onRequest(RequestType type, DataRequest request); 26 | } 27 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/page/RecruitmentAdministrationPage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.page; 2 | 3 | import net.nationstatesplusplus.assembly.model.websocket.DataRequest; 4 | import net.nationstatesplusplus.assembly.model.websocket.PageType; 5 | import net.nationstatesplusplus.assembly.model.websocket.RequestType; 6 | 7 | public class RecruitmentAdministrationPage extends NationStatesPage { 8 | private final String adminRegion; 9 | private final int adminRegionId; 10 | public RecruitmentAdministrationPage(String adminRegion, int adminRegionId) { 11 | super(PageType.RECRUITMENT_ADMINISTRATION); 12 | this.adminRegion = adminRegion; 13 | this.adminRegionId = adminRegionId; 14 | } 15 | 16 | @Override 17 | public void onRequest(RequestType type, DataRequest request) { 18 | } 19 | 20 | public String getAdminRegion() { 21 | return adminRegion; 22 | } 23 | 24 | public int getAdminRegionId() { 25 | return adminRegionId; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Assembly/app/controllers/DatabaseController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import net.nationstatesplusplus.assembly.util.DatabaseAccess; 7 | 8 | import org.spout.cereal.config.yaml.YamlConfiguration; 9 | 10 | import com.mchange.v2.c3p0.ComboPooledDataSource; 11 | 12 | import play.mvc.Controller; 13 | 14 | public abstract class DatabaseController extends Controller{ 15 | private final ComboPooledDataSource pool; 16 | private final DatabaseAccess access; 17 | private final YamlConfiguration config; 18 | public DatabaseController(DatabaseAccess access, YamlConfiguration config) { 19 | this.pool = access.getPool(); 20 | this.access = access; 21 | this.config = config; 22 | } 23 | 24 | public final Connection getConnection() throws SQLException { 25 | return pool.getConnection(); 26 | } 27 | 28 | public final DatabaseAccess getDatabase() { 29 | return access; 30 | } 31 | 32 | public YamlConfiguration getConfig() { 33 | return config; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/Region.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | @JsonInclude(JsonInclude.Include.NON_NULL) 7 | public class Region { 8 | @JsonProperty 9 | private String name; 10 | @JsonProperty 11 | private String title; 12 | @JsonProperty 13 | private String flag; 14 | 15 | public Region() { 16 | 17 | } 18 | 19 | public Region(String name, String title, String flag) { 20 | this.name = name; 21 | this.title = title; 22 | this.flag = flag; 23 | } 24 | 25 | public String getFlag() { 26 | return flag; 27 | } 28 | 29 | public void setFlag(String flag) { 30 | this.flag = flag; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public String getTitle() { 42 | return title; 43 | } 44 | 45 | public void setTitle(String title) { 46 | this.title = title; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Assembly/build.sbt: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import Keys._ 3 | import play.Play.autoImport._ 4 | import PlayKeys._ 5 | 6 | name := "Assembly" 7 | 8 | version := "1.0-SNAPSHOT" 9 | 10 | lazy val root = (project in file(".")).enablePlugins(PlayJava) 11 | 12 | scalaVersion := "2.11.1" 13 | 14 | libraryDependencies ++= Seq( 15 | javaJdbc, filters, 16 | "mysql" % "mysql-connector-java" % "5.1.31", 17 | "commons-io" % "commons-io" % "2.4", 18 | "commons-lang" % "commons-lang" % "2.6", 19 | "com.mchange" % "c3p0" % "0.9.2.1", 20 | "org.jsoup" % "jsoup" % "1.7.2", 21 | "commons-dbutils" % "commons-dbutils" % "1.5", 22 | "com.google.guava" % "guava" % "18.0", 23 | "org.apache.commons" % "commons-math3" % "3.2", 24 | "com.fasterxml.jackson.core" % "jackson-core" % "2.3.0", 25 | "com.fasterxml.jackson.core" % "jackson-annotations" % "2.3.0", 26 | "com.fasterxml.jackson.core" % "jackson-databind" % "2.3.0", 27 | "net.sourceforge" % "jwbf" % "2.0.0", 28 | "com.rabbitmq" % "amqp-client" % "3.3.1", 29 | "org.mongodb" % "mongo-java-driver" % "2.12.2", 30 | "net.schmizz" % "sshj" % "0.9.0" 31 | ) 32 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/page/NationPage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.page; 2 | 3 | import net.nationstatesplusplus.assembly.model.websocket.DataRequest; 4 | import net.nationstatesplusplus.assembly.model.websocket.PageType; 5 | import net.nationstatesplusplus.assembly.model.websocket.RequestType; 6 | 7 | public class NationPage extends NationStatesPage { 8 | private final String nation; 9 | private final int nationId; 10 | public NationPage(String nation, int nationId) { 11 | super(PageType.NATION); 12 | this.nation = nation; 13 | this.nationId = nationId; 14 | } 15 | 16 | public String getNation() { 17 | return nation; 18 | } 19 | 20 | public int getNationId() { 21 | return nationId; 22 | } 23 | 24 | @Override 25 | public boolean isValidUpdate(RequestType type, DataRequest request) { 26 | if (type == RequestType.NATION_HAPPENINGS) { 27 | return nationId == request.getValue("nation", null, Integer.class); 28 | } 29 | return super.isValidUpdate(type, request); 30 | } 31 | 32 | @Override 33 | public void onRequest(RequestType type, DataRequest request) { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Afforess 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/logging/LoggerOutputStream.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.logging; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | 6 | import org.slf4j.Logger; 7 | 8 | import ch.qos.logback.classic.Level; 9 | 10 | public class LoggerOutputStream extends ByteArrayOutputStream { 11 | private final String separator = System.getProperty("line.separator"); 12 | private final Level level; 13 | private final Logger log; 14 | 15 | public LoggerOutputStream(Level level, Logger log) { 16 | this.level = level; 17 | this.log = log; 18 | } 19 | 20 | @Override 21 | public synchronized void flush() throws IOException { 22 | super.flush(); 23 | String record = this.toString(); 24 | super.reset(); 25 | 26 | if (record.length() > 0 && !record.equals(separator) && level != Level.OFF) { 27 | if (level == Level.TRACE) 28 | log.trace(record); 29 | else if (level == Level.DEBUG) 30 | log.debug(record); 31 | else if (level == Level.INFO) 32 | log.info(record); 33 | else if (level == Level.WARN) 34 | log.warn(record); 35 | else if (level == Level.ERROR) 36 | log.error(record); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/logging/LoggingFilter.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.logging; 2 | 3 | import play.Logger; 4 | import ch.qos.logback.classic.spi.ILoggingEvent; 5 | import ch.qos.logback.classic.spi.IThrowableProxy; 6 | import ch.qos.logback.classic.spi.ThrowableProxy; 7 | import ch.qos.logback.core.filter.Filter; 8 | import ch.qos.logback.core.spi.FilterReply; 9 | 10 | public class LoggingFilter extends Filter { 11 | 12 | public LoggingFilter() { 13 | Logger.warn("Creating logging filter!"); 14 | } 15 | 16 | @Override 17 | public FilterReply decide(ILoggingEvent event) { 18 | final IThrowableProxy throwableProxy = event.getThrowableProxy(); 19 | if (throwableProxy == null) { 20 | return FilterReply.NEUTRAL; 21 | } 22 | 23 | if (!(throwableProxy instanceof ThrowableProxy)) { 24 | return FilterReply.NEUTRAL; 25 | } 26 | 27 | final ThrowableProxy throwableProxyImpl = (ThrowableProxy) throwableProxy; 28 | final Throwable throwable = throwableProxyImpl.getThrowable(); 29 | if (java.nio.channels.ClosedChannelException.class.isInstance(throwable)) { 30 | return FilterReply.DENY; 31 | } 32 | 33 | return FilterReply.NEUTRAL; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NationStates++ Project Layout 2 | ============= 3 | - Assembly [play! framework 2.2 project] 4 | - app [java codebase] 5 | - conf [play! framework settings & endpoints] 6 | - Extension [all extension/front-end code] 7 | - Chrome [chrome specific manifest & background.js] 8 | - Firefox [Firefox addon install manifest] 9 | - addon [Firefox SDK-generated root addon folder] 10 | - data [Firefox specific background.js] 11 | - lib [Firefox main.js (addon entrypoint)] 12 | - Safari [container for Safari content] 13 | - nationstates++.safariextension [auto-generated Safari extension folder] 14 | - css [Location of CSS for inclusion into extension] 15 | - js [Location of JS for inclusion into the extension] 16 | - highcarts-adapter.js [Injected JS to interface from extension to highcharts.js at nationstates.net] 17 | 18 | ============= 19 | Libraries included in .jar form, not in maven repos: 20 | - NS-API: https://github.com/Afforess/ns-api 21 | - Java Object model of the NationStates XML API 22 | - NS-DUMPS: https://github.com/Afforess/ns-dumps 23 | - Converts NationStates XML dumps into standardize database schema 24 | - Cereal(ization): https://github.com/Afforess/Cerealization 25 | - Library for easy YAML configuration handling 26 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/websocket/PageType.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.websocket; 2 | 3 | import static net.nationstatesplusplus.assembly.model.websocket.RequestType.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | public enum PageType { 11 | DEFAULT(GAMEPLAY_NEWS_SIDEBAR, ROLEPLAY_NEWS_SIDEBAR, REGIONAL_NEWS_SIDEBAR, PENDING_NEWS_SUBMISSIONS, CHECK_RECRUITMENT_OFFICERS), 12 | REGION(INITIAL_REGION_SETTINGS, REGION_TITLE, REGION_MAP, REGION_UPDATES, REGION_NEWSPAPER, REGION_EMBASSIES, REGION_POPULATION), 13 | NATION(LAST_NATION_ACTIVITY), 14 | WA, 15 | RECRUITMENT_ADMINISTRATION(RECRUITMENT_CAMPAIGNS, RECRUITMENT_OFFICERS, RECRUITMENT_EFFECTIVENESS), 16 | 17 | ; 18 | 19 | private final List initialRequests; 20 | PageType(RequestType... initial) { 21 | if (initial != null) initialRequests = Arrays.asList(initial); 22 | else initialRequests = Collections.emptyList(); 23 | } 24 | 25 | public List getInitialRequests() { 26 | if (this == DEFAULT) { 27 | return new ArrayList(initialRequests); 28 | } 29 | List initial = new ArrayList(initialRequests); 30 | initial.addAll(DEFAULT.initialRequests); 31 | return initial; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Extension/Firefox/install.rdf: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | afforess@gmail.com 7 | 2.4.3.8 8 | 2 9 | true 10 | false 11 | 12 | 13 | 14 | 15 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 16 | 17.0 17 | 40.* 18 | 19 | 20 | 21 | 22 | NationStates++ 23 | Improves the NationStates.net Regional Message Board experience 24 | Afforess 25 | https://nationstatesplusplus.net/nationstates/update.rdf 26 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUMDxmO/nqJBL9Pum8iNF1toKJfBcG1Sukfw5blQs9kAYfaWVAYZobd43E0yzDEoHk8S8D8P4WDOiNiK5yZPO3gq/HtO+3+nrGgOzfO6S3abAIuTQ1YCWE4XPWYdzW80P6v1kUwX/QMD+jiDkYSiALISv/N1cLjY8OdaalD5KUQwIDAQAB 27 | 28 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/websocket/WebsocketMessage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.websocket; 2 | 3 | import java.util.Set; 4 | 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | import com.fasterxml.jackson.databind.JsonNode; 9 | 10 | @JsonInclude(JsonInclude.Include.NON_NULL) 11 | public class WebsocketMessage { 12 | @JsonProperty("page") 13 | private final PageType page; 14 | @JsonProperty("type") 15 | private final RequestType type; 16 | @JsonProperty("request") 17 | private final DataRequest request; 18 | @JsonProperty("node") 19 | private final JsonNode node; 20 | @JsonProperty("nations") 21 | private final Set nations; 22 | 23 | @JsonCreator 24 | public WebsocketMessage(@JsonProperty("page") PageType page, @JsonProperty("type") RequestType type, @JsonProperty("request") DataRequest request, @JsonProperty("node") JsonNode node, @JsonProperty("nations") Set nations) { 25 | this.page = page; 26 | this.type = type; 27 | this.request = request; 28 | this.node = node; 29 | this.nations = nations; 30 | } 31 | 32 | public PageType getPage() { 33 | return page; 34 | } 35 | 36 | public RequestType getType() { 37 | return type; 38 | } 39 | 40 | public DataRequest getRequest() { 41 | return request; 42 | } 43 | 44 | public JsonNode getNode() { 45 | return node; 46 | } 47 | 48 | public Set getNations() { 49 | return nations; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/websocket/NationContext.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.websocket; 2 | 3 | import net.nationstatesplusplus.assembly.model.page.NationStatesPage; 4 | import net.nationstatesplusplus.assembly.nation.NationSettings; 5 | import net.nationstatesplusplus.assembly.util.DatabaseAccess; 6 | 7 | public class NationContext { 8 | private final String nation; 9 | private final int nationId; 10 | private final String userRegion; 11 | private final int userRegionId; 12 | private final NationSettings settings; 13 | private final NationStatesPage activePage; 14 | private final DatabaseAccess access; 15 | 16 | public NationContext(String nation, int nationId, String userRegion, int userRegionId, NationSettings settings, NationStatesPage page, DatabaseAccess access) { 17 | this.nation = nation; 18 | this.nationId = nationId; 19 | this.userRegion = userRegion; 20 | this.userRegionId = userRegionId; 21 | this.settings = settings; 22 | this.activePage = page; 23 | this.access = access; 24 | } 25 | 26 | public String getNation() { 27 | return nation; 28 | } 29 | 30 | public int getNationId() { 31 | return nationId; 32 | } 33 | 34 | public String getUserRegion() { 35 | return userRegion; 36 | } 37 | 38 | public int getUserRegionId() { 39 | return userRegionId; 40 | } 41 | 42 | public NationSettings getSettings() { 43 | return settings; 44 | } 45 | 46 | public NationStatesPage getActivePage() { 47 | return activePage; 48 | } 49 | 50 | public DatabaseAccess getAccess() { 51 | return access; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Assembly/app/net/nationstatesplusplus/assembly/model/page/RegionPage.java: -------------------------------------------------------------------------------- 1 | package net.nationstatesplusplus.assembly.model.page; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import net.nationstatesplusplus.assembly.model.websocket.DataRequest; 7 | import net.nationstatesplusplus.assembly.model.websocket.PageType; 8 | import net.nationstatesplusplus.assembly.model.websocket.RequestType; 9 | 10 | public class RegionPage extends NationStatesPage { 11 | private final Set rmbPosts = new HashSet(); 12 | private final String region; 13 | private final int regionId; 14 | public RegionPage(String region, int regionId) { 15 | super(PageType.REGION); 16 | this.region = region; 17 | this.regionId = regionId; 18 | } 19 | 20 | public String getRegion() { 21 | return region; 22 | } 23 | 24 | public int getRegionId() { 25 | return regionId; 26 | } 27 | 28 | @Override 29 | public boolean isValidUpdate(RequestType type, DataRequest request) { 30 | if (type == RequestType.RMB_RATINGS) { 31 | Integer rmbPost = request.getValue("rmb_post_id", null, Integer.class); 32 | if (rmbPost != null) { 33 | return rmbPosts.contains(rmbPost); 34 | } 35 | } else if (type == RequestType.RMB_MESSAGE || type == RequestType.REGION_HAPPENINGS) { 36 | return regionId == request.getValue("region", null, Integer.class); 37 | } 38 | return super.isValidUpdate(type, request); 39 | } 40 | 41 | @Override 42 | public void onRequest(RequestType type, DataRequest request) { 43 | if (type == RequestType.RMB_RATINGS) { 44 | rmbPosts.add(request.getValue("rmb_post_id", null, Integer.class)); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Extension/js/wa.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (getVisiblePage() == "ga" || getVisiblePage() == "sc") { 3 | if ($("h3:contains('Resolution At Vote')").length > 0) { 4 | var resolution = $("h2").text(); 5 | if (resolution) { 6 | showIndividualVotes(); 7 | } 8 | } 9 | } 10 | 11 | function showIndividualVotes() { 12 | $.get("https://nationstatesplusplus.net/api/wa/nation_votes/", function(data) { 13 | for (var i = 0; i < data.length; i += 1) { 14 | if (data[i].name == $("h2").text()) { 15 | var resolution = data[i]; 16 | var total = 0; 17 | if (resolution.nation_votes_for) total += resolution.nation_votes_for; 18 | if (resolution.nation_votes_against) total += resolution.nation_votes_against; 19 | 20 | if (resolution.nation_votes_for) { 21 | var percent = Math.floor((resolution.nation_votes_for / total) * 100); 22 | $("

    Individuals For: " + numberWithCommas(resolution.nation_votes_for) + " (" + percent + "%)

    ").insertAfter($("p:contains('Votes For')")) 23 | $("strong:contains('Votes For')").html("Delegates Votes For:"); 24 | } 25 | if (resolution.nation_votes_against) { 26 | var percent = Math.floor((resolution.nation_votes_against / total) * 100); 27 | $("

    Individuals Against: " + numberWithCommas(resolution.nation_votes_against) + " (" + percent + "%)

    ").insertAfter($("p:contains('Votes Against')")) 28 | $("strong:contains('Votes Against')").html("Delegates Votes Against:"); 29 | } 30 | } 31 | } 32 | }); 33 | } 34 | 35 | function numberWithCommas(x) { 36 | return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 37 | } 38 | })(); -------------------------------------------------------------------------------- /Extension/css/nationstates++_dark.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | text-shadow: 2px 2px 1px #5A5858; 3 | } 4 | 5 | h1, h1 a, h2, h3, h4, h5, h6 { 6 | color: #FFFFFF !important; 7 | } 8 | 9 | .ns-settings { 10 | background: #2A2A2A; 11 | border: 1px solid #383838; 12 | } 13 | 14 | .puppet-form { 15 | background: #2A2A2A; 16 | } 17 | 18 | #nationstates_settings h1 { 19 | color: #D0D0D0 !important; 20 | } 21 | 22 | #nationstates_settings { 23 | background: #000 !important; 24 | color: #D0D0D0 !important; 25 | } 26 | 27 | #nationstates_settings fieldset{ 28 | background: #2A2A2A !important; 29 | border: 1px solid #383838 !important; 30 | color: #D0D0D0 !important; 31 | } 32 | 33 | .dossier_element { 34 | border: 6px solid #191919 !important; 35 | background-color: #191919 !important; 36 | } 37 | 38 | .older { 39 | background: #191919; 40 | border: 1px #383838 solid; 41 | } 42 | 43 | #manage_newspaper { 44 | border: solid 2px white; 45 | background: black; 46 | } 47 | 48 | #inner-content fieldset, #target fieldset { 49 | background-color: black !important; 50 | } 51 | 52 | .updatetime { 53 | background: #2A2A2A; 54 | border: 1px solid #383838; 55 | color: #D0D0D0 !important; 56 | } 57 | 58 | #nspp_trophy { 59 | -webkit-filter: none !important; 60 | } 61 | 62 | #preview { 63 | color: black !important; 64 | } 65 | 66 | #alert_msg_box h1, #alert_msg_box h2, #alert_msg_box h3, #alert_msg_box h4, #alert_msg_box h5, #alert_msg_box h6{ 67 | color: black !important; 68 | text-shadow: 2px 2px 1px #FFFFFF; 69 | } 70 | 71 | #toggle_dossier_label { 72 | border: 2px solid white !important; 73 | } 74 | 75 | .banner-theme { 76 | background: #2A2A2A !important; 77 | border: 1px solid #383838 !important; 78 | } -------------------------------------------------------------------------------- /Extension/Safari/nationstates++.safariextension/global.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 29 | 30 | -------------------------------------------------------------------------------- /Extension/html/banhammer.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | 5 |
    6 | 7 |
    8 | 12 |
    13 |
    14 | 15 | 16 |
    17 | 18 |
    19 | 20 |

    Type part of the nation"s name (press enter to execute filter)

    21 |
    22 |
    23 | 24 | 25 |
    26 | 27 |
    28 | 32 | 36 |
    37 |
    38 | 39 | 40 |
    41 | 42 |
    43 | 47 |
    48 |
    49 | 50 |
    51 |
    52 | -------------------------------------------------------------------------------- /Extension/js/bootstrap-dropdown.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap.js by @fat & @mdo 3 | * plugins: bootstrap-dropdown.js 4 | * Copyright 2013 Twitter, Inc. 5 | * http://www.apache.org/licenses/LICENSE-2.0.txt 6 | */ 7 | !function(a){function d(){a(".dropdown-backdrop").remove(),a(b).each(function(){e(a(this)).removeClass("open")})}function e(b){var c=b.attr("data-target"),d;c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,"")),d=c&&a(c);if(!d||!d.length)d=b.parent();return d}var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||("ontouchstart"in document.documentElement&&a('