-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
48a13b1
commit 2cb8633
Showing
8 changed files
with
852 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
60
src/main/java/cn/wode490390/nukkit/geoip/GeoIPCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.