Skip to content

Commit

Permalink
1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
wode490390 committed Aug 14, 2019
1 parent 48a13b1 commit 2cb8633
Show file tree
Hide file tree
Showing 8 changed files with 852 additions and 1 deletion.
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,48 @@
# GeoIP
GeoIP plugin for Nukkit. GeoIP provides an approximate lookup of where your players come from, based on their public IP and public geographical databases.
[![](https://i.loli.net/2019/08/11/g9PU5ufFoqmeKjp.png)](http://www.mcbbs.net/thread-900823-1-1.html "IP定位")

GeoIP plugin for Nukkit.

GeoIP provides an approximate lookup of where your players come from, based on their public IP and public geographical databases.

Please see [mcbbs](http://www.mcbbs.net/thread-900823-1-1.html) for more information.
## Permissions
| Command | Permission | Description | Default |
| - | - | - | - |
| `/geoip` | geoip.show | Shows the GeoIP location of a player. | OP |
| `/geoip` | geoip.show.fullip | Shows the full ip address of a player. | false |
| | geoip.hide | Allows player to hide player's country and city from people who have permission geoip.show | false |
## config.yml
```yaml
database:
show-cities: false
download-if-missing: true
# Url for country
download-url: "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz"
# Url for cities
download-url-city: "https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz"
update:
enable: true
by-every-x-days: 30
show-on-login: true
# "enable-locale" enables locale on geolocation display.
enable-locale: true
# Not all languages are supported. See https://dev.maxmind.com/geoip/geoip2/web-services/#Languages
locale: en
```
## API Usage
```java
import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.wode490390.nukkit.geoip.GeoIP;

class Example {
Example() {
Player player = Server.getInstance().getPlayer("wode490390");
if (player != null) {
String geoLocation = GeoIP.query(player); //Our API :)
player.sendMessage("Your location: " + geoLocation);
}
}
}
```
86 changes: 86 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.wode490390.nukkit</groupId>
<artifactId>geoip</artifactId>
<version>1.0.0</version>
<name>GeoIP</name>
<description>GeoIP plugin for Nukkit</description>
<inceptionYear>2018</inceptionYear>
<url>http://wode490390.cn/</url>
<packaging>jar</packaging>
<licenses>
<license>
<name>GNU General Public License, Version 3.0</name>
<url>http://www.gnu.org/licenses/gpl.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>nukkitx</id>
<url>http://repo.nukkitx.com/main/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>cn.nukkit</groupId>
<artifactId>nukkit</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>javatar</groupId>
<artifactId>javatar</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<build>
<finalName>wodeGeoIP-${project.version}</finalName>
<defaultGoal>clean package</defaultGoal>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>*.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
</configuration>
</plugin>
</plugins>
</build>
</project>
144 changes: 144 additions & 0 deletions src/main/java/cn/wode490390/nukkit/geoip/GeoIP.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cn.wode490390.nukkit.geoip;

import cn.nukkit.Player;
import cn.nukkit.plugin.PluginBase;
import cn.nukkit.utils.Config;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.ice.tar.TarEntry;
import com.ice.tar.TarInputStream;
import com.maxmind.geoip2.DatabaseReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.zip.GZIPInputStream;

public class GeoIP extends PluginBase {

private static final Map<Player, String> cache = Maps.newHashMap();

/**
* Querys player's geographical location.
*
* @param palyer
* @return geographical location or null
*/
public static String query(Player palyer) {
Preconditions.checkNotNull(palyer, "Player cannot be null");
return cache.get(palyer);
}

static void setGeoLocation(Player palyer, String location) {
cache.put(palyer, location);
}

Config config;
private File databaseFile;

@Override
public void onEnable() {
try {
new MetricsLite(this);
} catch (Exception ignore) {

}
this.saveDefaultConfig();
this.config = this.getConfig();
if (this.config.getBoolean("database.show-cities", false)) {
this.databaseFile = new File(this.getDataFolder(), "GeoIP2-City.mmdb");
} else {
this.databaseFile = new File(this.getDataFolder(), "GeoIP2-Country.mmdb");
}
if (!this.databaseFile.exists()) {
if (this.config.getBoolean("database.download-if-missing", true)) {
this.downloadDatabase();
} else {
this.getLogger().warning("Can't find GeoIP database!");
this.setEnabled(false);
return;
}
} else if (this.config.getBoolean("database.update.enable", true)) {
// try to update expired mmdb files
long diff = new Date().getTime() - this.databaseFile.lastModified();
if (diff / 86400000 > this.config.getLong("database.update.by-every-x-days", 30)) {
this.downloadDatabase();
}
}
DatabaseReader mmreader;
try {
// locale setting
if (this.config.getBoolean("enable-locale")) {
// If the locale is not avaliable, use "en".
mmreader = new DatabaseReader.Builder(this.databaseFile).locales(Arrays.asList(this.config.getString("locale"), "en")).build();
} else {
mmreader = new DatabaseReader.Builder(this.databaseFile).build();
}
} catch (IOException ex) {
this.getLogger().warning("Failed to read GeoIP database", ex);
this.setEnabled(false);
return;
}
this.getServer().getPluginManager().registerEvents(new GeoIPListener(this, mmreader), this);
this.getServer().getCommandMap().register("geoip", new GeoIPCommand(this));
}

private void downloadDatabase() {
try {
String url;
if (this.config.getBoolean("database.show-cities", false)) {
url = this.config.getString("database.download-url-city");
} else {
url = this.config.getString("database.download-url");
}
if (url == null || url.isEmpty()) {
this.getLogger().warning("GeoIP download url is empty.");
return;
}
this.getLogger().info("Downloading GeoIP database... this might take a while.");
URL downloadUrl = new URL(url);
URLConnection conn = downloadUrl.openConnection();
conn.setConnectTimeout(10000);
conn.connect();
InputStream input = conn.getInputStream();
OutputStream output = new FileOutputStream(this.databaseFile);
byte[] buffer = new byte[2048];
if (url.endsWith(".gz")) {
input = new GZIPInputStream(input);
if (url.endsWith(".tar.gz")) {
// The new GeoIP2 uses tar.gz to pack the db file along with some other txt. So it makes things a bit complicated here.
String filename;
TarInputStream tarInputStream = new TarInputStream(input);
TarEntry entry;
while ((entry = tarInputStream.getNextEntry()) != null) {
if (!entry.isDirectory()) {
filename = entry.getName();
if (filename.substring(filename.length() - 5).equalsIgnoreCase(".mmdb")) {
input = tarInputStream;
break;
}
}
}
}
}
int length = input.read(buffer);
while (length >= 0) {
output.write(buffer, 0, length);
length = input.read(buffer);
}
output.close();
input.close();
} catch (MalformedURLException ex) {
this.getLogger().warning("GeoIP download url is invalid", ex);
} catch (IOException ex) {
this.getLogger().warning("Failed to open connection", ex);
}
}
}
60 changes: 60 additions & 0 deletions src/main/java/cn/wode490390/nukkit/geoip/GeoIPCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cn.wode490390.nukkit.geoip;

import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.command.Command;
import cn.nukkit.command.CommandSender;
import cn.nukkit.command.PluginIdentifiableCommand;
import cn.nukkit.command.data.CommandParamType;
import cn.nukkit.command.data.CommandParameter;
import cn.nukkit.lang.TranslationContainer;
import cn.nukkit.plugin.Plugin;
import cn.nukkit.utils.TextFormat;

public class GeoIPCommand extends Command implements PluginIdentifiableCommand {

private final Plugin plugin;

public GeoIPCommand(Plugin plugin) {
super("geoip", "Querys the GeoIP location of a player", "/geoip <player>");
this.setPermission("geoip.show");
this.getCommandParameters().clear();
this.addCommandParameters("default", new CommandParameter[]{
new CommandParameter("player", CommandParamType.TARGET, false)
});
this.plugin = plugin;
}

@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!this.plugin.isEnabled() || !this.testPermission(sender)) {
return false;
}
if (args.length > 0) {
Player player = Server.getInstance().getPlayer(args[0]);
if (player != null) {
String geoLocation = GeoIP.query(player);
if (geoLocation != null) {
String[] ip = player.getAddress().split("\\.");
try {
sender.sendMessage(TextFormat.colorize("&6Player &c" + player.getDisplayName() + " &6comes from &c" + geoLocation + "&6. (IP:&c" + (sender.hasPermission("geoip.show.fullip") ? player.getAddress() : ip[0] + ".*.*." + ip[3]) + "&6)"));
return true;
} catch (Exception ex) {

}
}
sender.sendMessage(TextFormat.colorize("&6Player &c" + player.getDisplayName() + " &6comes from &aan unknown country&6."));
} else {
sender.sendMessage(new TranslationContainer("commands.generic.player.notFound"));
}
} else {
sender.sendMessage(new TranslationContainer("commands.generic.usage", this.getUsage()));
}
return true;
}

@Override
public Plugin getPlugin() {
return this.plugin;
}
}
Loading

0 comments on commit 2cb8633

Please sign in to comment.