mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-26 20:26:01 +01:00
Rework Converter + Add CrazyLogin flat converter
This commit is contained in:
parent
b403374c2a
commit
1d83b398f0
@ -33,6 +33,7 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
import fr.xephi.authme.cache.limbo.LimboCache;
|
import fr.xephi.authme.cache.limbo.LimboCache;
|
||||||
import fr.xephi.authme.converter.Converter;
|
import fr.xephi.authme.converter.Converter;
|
||||||
|
import fr.xephi.authme.converter.CrazyLoginConverter;
|
||||||
import fr.xephi.authme.converter.FlatToSql;
|
import fr.xephi.authme.converter.FlatToSql;
|
||||||
import fr.xephi.authme.converter.FlatToSqlite;
|
import fr.xephi.authme.converter.FlatToSqlite;
|
||||||
import fr.xephi.authme.converter.RakamakConverter;
|
import fr.xephi.authme.converter.RakamakConverter;
|
||||||
@ -302,25 +303,33 @@ public class AdminCommand implements CommandExecutor {
|
|||||||
} else if (args[0].equalsIgnoreCase("convertflattosql")) {
|
} else if (args[0].equalsIgnoreCase("convertflattosql")) {
|
||||||
FlatToSql converter = new FlatToSql();
|
FlatToSql converter = new FlatToSql();
|
||||||
try {
|
try {
|
||||||
converter.convert();
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, converter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sender.sendMessage("[AuthMe] Error while converting to authme.sql");
|
sender.sendMessage("[AuthMe] Error while converting to authme.sql");
|
||||||
}
|
}
|
||||||
} else if (args[0].equalsIgnoreCase("flattosqlite")) {
|
} else if (args[0].equalsIgnoreCase("flattosqlite")) {
|
||||||
FlatToSqlite converter = new FlatToSqlite(sender);
|
FlatToSqlite converter = new FlatToSqlite(sender);
|
||||||
try {
|
try {
|
||||||
converter.convert();
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, converter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (args[0].equalsIgnoreCase("xauthimport")) {
|
} else if (args[0].equalsIgnoreCase("xauthimport")) {
|
||||||
Converter converter = new xAuthConverter(plugin, database, sender);
|
Converter converter = new xAuthConverter(plugin, database, sender);
|
||||||
try {
|
try {
|
||||||
converter.convert();
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, converter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sender.sendMessage("Error while importing xAuth data, check your logs");
|
sender.sendMessage("Error while importing xAuth data, check your logs");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else if (args[0].equalsIgnoreCase("crazyloginimport")) {
|
||||||
|
Converter converter = new CrazyLoginConverter(plugin, database, sender);
|
||||||
|
try {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, converter);
|
||||||
|
} catch (Exception e) {
|
||||||
|
sender.sendMessage("Error while importing CrazyLogin datas, check your logs");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else if (args[0].equalsIgnoreCase("getemail")) {
|
} else if (args[0].equalsIgnoreCase("getemail")) {
|
||||||
if (args.length != 2) {
|
if (args.length != 2) {
|
||||||
sender.sendMessage("Usage: /authme getemail playername");
|
sender.sendMessage("Usage: /authme getemail playername");
|
||||||
@ -356,7 +365,7 @@ public class AdminCommand implements CommandExecutor {
|
|||||||
} else if (args[0].equalsIgnoreCase("convertfromrakamak")) {
|
} else if (args[0].equalsIgnoreCase("convertfromrakamak")) {
|
||||||
Converter converter = new RakamakConverter(plugin, database, sender);
|
Converter converter = new RakamakConverter(plugin, database, sender);
|
||||||
try {
|
try {
|
||||||
converter.convert();
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, converter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sender.sendMessage("Error while importing Rakamak data, check your logs");
|
sender.sendMessage("Error while importing Rakamak data, check your logs");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package fr.xephi.authme.converter;
|
package fr.xephi.authme.converter;
|
||||||
|
|
||||||
public interface Converter {
|
public interface Converter extends Runnable {
|
||||||
|
|
||||||
void convert() throws Exception;
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package fr.xephi.authme.converter;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Xephi59
|
||||||
|
*/
|
||||||
|
public class CrazyLoginConverter implements Converter {
|
||||||
|
|
||||||
|
public AuthMe instance;
|
||||||
|
public DataSource database;
|
||||||
|
public CommandSender sender;
|
||||||
|
|
||||||
|
public CrazyLoginConverter (AuthMe instance, DataSource database, CommandSender sender) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.database = database;
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrazyLoginConverter getInstance() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String fileName;
|
||||||
|
private static File source;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
fileName = Settings.crazyloginFileName;
|
||||||
|
try {
|
||||||
|
source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName);
|
||||||
|
if (!source.exists()) {
|
||||||
|
sender.sendMessage("Error while trying to import datas, please put " + fileName + " in AuthMe folder!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
source.createNewFile();
|
||||||
|
BufferedReader users = null;
|
||||||
|
String line;
|
||||||
|
users = new BufferedReader(new FileReader(source));
|
||||||
|
while ((line = users.readLine()) != null) {
|
||||||
|
if (line.contains("|")) {
|
||||||
|
String[] args = line.split("\\|");
|
||||||
|
if (args.length < 2)
|
||||||
|
continue;
|
||||||
|
if (args[0].equalsIgnoreCase("name"))
|
||||||
|
continue;
|
||||||
|
String player = args[0];
|
||||||
|
String psw = args[1];
|
||||||
|
try {
|
||||||
|
if (player != null && psw != null) {
|
||||||
|
PlayerAuth auth = new PlayerAuth(player, psw, "127.0.0.1", System.currentTimeMillis());
|
||||||
|
database.saveAuth(auth);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
users.close();
|
||||||
|
ConsoleLogger.info("CrazyLogin database has been imported correctly");
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -49,7 +49,8 @@ public class FlatToSql implements Converter {
|
|||||||
columnID = Settings.getMySQLColumnId;
|
columnID = Settings.getMySQLColumnId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void convert() throws IOException {
|
@Override
|
||||||
|
public void run() {
|
||||||
try {
|
try {
|
||||||
source = new File(AuthMe.getInstance().getDataFolder() + File.separator + "auths.db");
|
source = new File(AuthMe.getInstance().getDataFolder() + File.separator + "auths.db");
|
||||||
source.createNewFile();
|
source.createNewFile();
|
||||||
@ -58,7 +59,7 @@ public class FlatToSql implements Converter {
|
|||||||
BufferedWriter sql = null;
|
BufferedWriter sql = null;
|
||||||
br = new BufferedReader(new FileReader(source));
|
br = new BufferedReader(new FileReader(source));
|
||||||
sql = new BufferedWriter(new FileWriter(output));
|
sql = new BufferedWriter(new FileWriter(output));
|
||||||
String createDB = " CREATE TABLE IF NOT EXISTS " + tableName + " ("
|
String createDB = "CREATE TABLE IF NOT EXISTS " + tableName + " ("
|
||||||
+ columnID + " INTEGER AUTO_INCREMENT,"
|
+ columnID + " INTEGER AUTO_INCREMENT,"
|
||||||
+ columnName + " VARCHAR(255) NOT NULL UNIQUE,"
|
+ columnName + " VARCHAR(255) NOT NULL UNIQUE,"
|
||||||
+ columnPassword + " VARCHAR(255) NOT NULL,"
|
+ columnPassword + " VARCHAR(255) NOT NULL,"
|
||||||
|
@ -42,7 +42,8 @@ public class FlatToSqlite implements Converter {
|
|||||||
private static String columnID;
|
private static String columnID;
|
||||||
private static Connection con;
|
private static Connection con;
|
||||||
|
|
||||||
public void convert() throws Exception {
|
@Override
|
||||||
|
public void run() {
|
||||||
database = Settings.getMySQLDatabase;
|
database = Settings.getMySQLDatabase;
|
||||||
tableName = Settings.getMySQLTablename;
|
tableName = Settings.getMySQLTablename;
|
||||||
columnName = Settings.getMySQLColumnName;
|
columnName = Settings.getMySQLColumnName;
|
||||||
|
@ -45,7 +45,8 @@ public class RakamakConverter implements Converter {
|
|||||||
private static File source;
|
private static File source;
|
||||||
private static File ipfiles;
|
private static File ipfiles;
|
||||||
|
|
||||||
public void convert() throws Exception {
|
@Override
|
||||||
|
public void run() {
|
||||||
HashAlgorithm hash = Settings.getPasswordHash;
|
HashAlgorithm hash = Settings.getPasswordHash;
|
||||||
useIP = Settings.rakamakUseIp;
|
useIP = Settings.rakamakUseIp;
|
||||||
fileName = Settings.rakamakUsers;
|
fileName = Settings.rakamakUsers;
|
||||||
@ -98,10 +99,13 @@ public class RakamakConverter implements Converter {
|
|||||||
database.saveAuth(auth);
|
database.saveAuth(auth);
|
||||||
}
|
}
|
||||||
ConsoleLogger.info("Rakamak database has been imported correctly");
|
ConsoleLogger.info("Rakamak database has been imported correctly");
|
||||||
|
sender.sendMessage("Rakamak database has been imported correctly");
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
sender.sendMessage("Error file not found");
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
sender.sendMessage("Error IOException");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
|
||||||
public class RoyalAuthConverter extends Thread implements Converter {
|
public class RoyalAuthConverter implements Converter {
|
||||||
|
|
||||||
public AuthMe plugin;
|
public AuthMe plugin;
|
||||||
private DataSource data;
|
private DataSource data;
|
||||||
@ -17,14 +17,10 @@ public class RoyalAuthConverter extends Thread implements Converter {
|
|||||||
public RoyalAuthConverter(AuthMe plugin) {
|
public RoyalAuthConverter(AuthMe plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.data = plugin.database;
|
this.data = plugin.database;
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convert() throws Exception {
|
public void run() {
|
||||||
for (OfflinePlayer o : plugin.getServer().getOfflinePlayers()) {
|
for (OfflinePlayer o : plugin.getServer().getOfflinePlayers()) {
|
||||||
try {
|
try {
|
||||||
String name = o.getName().toLowerCase();
|
String name = o.getName().toLowerCase();
|
||||||
@ -41,7 +37,6 @@ public class RoyalAuthConverter extends Thread implements Converter {
|
|||||||
ConsoleLogger.showError("Error while trying to import "+ o.getName() + " RoyalAuth datas");
|
ConsoleLogger.showError("Error while trying to import "+ o.getName() + " RoyalAuth datas");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.interrupt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import fr.xephi.authme.api.API;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
|
||||||
public class newxAuthToFlat extends Thread {
|
public class newxAuthToFlat {
|
||||||
|
|
||||||
public AuthMe instance;
|
public AuthMe instance;
|
||||||
public DataSource database;
|
public DataSource database;
|
||||||
@ -31,12 +31,6 @@ public class newxAuthToFlat extends Thread {
|
|||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
|
||||||
convert();
|
|
||||||
if (isAlive())
|
|
||||||
interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean convert() {
|
public boolean convert() {
|
||||||
if (instance.getServer().getPluginManager().getPlugin("xAuth") == null) {
|
if (instance.getServer().getPluginManager().getPlugin("xAuth") == null) {
|
||||||
sender.sendMessage("[AuthMe] xAuth plugin not found");
|
sender.sendMessage("[AuthMe] xAuth plugin not found");
|
||||||
|
@ -24,7 +24,7 @@ import fr.xephi.authme.datasource.DataSource;
|
|||||||
*
|
*
|
||||||
* @author Xephi59
|
* @author Xephi59
|
||||||
*/
|
*/
|
||||||
public class oldxAuthToFlat extends Thread {
|
public class oldxAuthToFlat {
|
||||||
|
|
||||||
public AuthMe instance;
|
public AuthMe instance;
|
||||||
public DataSource database;
|
public DataSource database;
|
||||||
@ -36,12 +36,6 @@ public class oldxAuthToFlat extends Thread {
|
|||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
|
||||||
convert();
|
|
||||||
if (isAlive())
|
|
||||||
interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean convert() {
|
public boolean convert() {
|
||||||
if (instance.getServer().getPluginManager().getPlugin("xAuth") == null) {
|
if (instance.getServer().getPluginManager().getPlugin("xAuth") == null) {
|
||||||
sender.sendMessage("[AuthMe] xAuth plugin not found");
|
sender.sendMessage("[AuthMe] xAuth plugin not found");
|
||||||
|
@ -16,18 +16,20 @@ public class xAuthConverter implements Converter {
|
|||||||
this.database = database;
|
this.database = database;
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convert() throws Exception {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Class.forName("com.cypherx.xauth.xAuth");
|
Class.forName("com.cypherx.xauth.xAuth");
|
||||||
oldxAuthToFlat converter = new oldxAuthToFlat(plugin, database, sender);
|
oldxAuthToFlat converter = new oldxAuthToFlat(plugin, database, sender);
|
||||||
converter.run();
|
converter.convert();
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
try {
|
try {
|
||||||
Class.forName("de.luricos.bukkit.xAuth.xAuth");
|
Class.forName("de.luricos.bukkit.xAuth.xAuth");
|
||||||
newxAuthToFlat converter = new newxAuthToFlat(plugin, database, sender);
|
newxAuthToFlat converter = new newxAuthToFlat(plugin, database, sender);
|
||||||
converter.run();
|
converter.convert();
|
||||||
} catch (ClassNotFoundException ce) {
|
} catch (ClassNotFoundException ce) {
|
||||||
|
sender.sendMessage("xAuth has not been found, please put xAuth.jar in your plugin folder and restart!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ public final class Settings extends YamlConfiguration {
|
|||||||
getcUnrestrictedName, getRegisteredGroup, messagesLanguage, getMySQLlastlocX, getMySQLlastlocY, getMySQLlastlocZ,
|
getcUnrestrictedName, getRegisteredGroup, messagesLanguage, getMySQLlastlocX, getMySQLlastlocY, getMySQLlastlocZ,
|
||||||
rakamakUsers, rakamakUsersIp, getmailAccount, getmailPassword, getmailSMTP, getMySQLColumnId, getmailSenderName,
|
rakamakUsers, rakamakUsersIp, getmailAccount, getmailPassword, getmailSMTP, getMySQLColumnId, getmailSenderName,
|
||||||
getMailSubject, getMailText, getMySQLlastlocWorld, defaultWorld,
|
getMailSubject, getMailText, getMySQLlastlocWorld, defaultWorld,
|
||||||
getPhpbbPrefix, getWordPressPrefix, getMySQLColumnLogged, spawnPriority;
|
getPhpbbPrefix, getWordPressPrefix, getMySQLColumnLogged, spawnPriority, crazyloginFileName;
|
||||||
|
|
||||||
public static int getWarnMessageInterval, getSessionTimeout, getRegistrationTimeout, getMaxNickLength,
|
public static int getWarnMessageInterval, getSessionTimeout, getRegistrationTimeout, getMaxNickLength,
|
||||||
getMinNickLength, getPasswordMinLen, getMovementRadius, getmaxRegPerIp, getNonActivatedGroup,
|
getMinNickLength, getPasswordMinLen, getMovementRadius, getmaxRegPerIp, getNonActivatedGroup,
|
||||||
@ -245,6 +245,7 @@ public void loadConfigOptions() {
|
|||||||
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false);
|
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false);
|
||||||
delayJoinMessage = configFile.getBoolean("settings.delayJoinMessage", false);
|
delayJoinMessage = configFile.getBoolean("settings.delayJoinMessage", false);
|
||||||
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false);
|
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false);
|
||||||
|
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
|
||||||
|
|
||||||
// Load the welcome message
|
// Load the welcome message
|
||||||
getWelcomeMessage(plugin);
|
getWelcomeMessage(plugin);
|
||||||
@ -405,6 +406,7 @@ public static void reloadConfigOptions(YamlConfiguration newConfig) {
|
|||||||
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false);
|
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false);
|
||||||
delayJoinMessage = configFile.getBoolean("settings.delayJoinMessage", false);
|
delayJoinMessage = configFile.getBoolean("settings.delayJoinMessage", false);
|
||||||
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false);
|
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false);
|
||||||
|
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
|
||||||
|
|
||||||
// Reload the welcome message
|
// Reload the welcome message
|
||||||
getWelcomeMessage(AuthMe.getInstance());
|
getWelcomeMessage(AuthMe.getInstance());
|
||||||
@ -517,6 +519,10 @@ public static void reloadConfigOptions(YamlConfiguration newConfig) {
|
|||||||
}
|
}
|
||||||
if(contains("Converter.Rakamak.newPasswordHash"))
|
if(contains("Converter.Rakamak.newPasswordHash"))
|
||||||
set("Converter.Rakamak.newPasswordHash", null);
|
set("Converter.Rakamak.newPasswordHash", null);
|
||||||
|
if(!contains("Converter.CrazyLogin.fileName")) {
|
||||||
|
set("Converter.CrazyLogin.fileName", "accounts.db");
|
||||||
|
changes = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (changes) {
|
if (changes) {
|
||||||
plugin.getLogger().warning("Merge new Config Options - I'm not an error, please don't report me");
|
plugin.getLogger().warning("Merge new Config Options - I'm not an error, please don't report me");
|
||||||
|
@ -329,6 +329,9 @@ Converter:
|
|||||||
useIP: false
|
useIP: false
|
||||||
# IP file name for rakamak
|
# IP file name for rakamak
|
||||||
ipFileName: UsersIp.rak
|
ipFileName: UsersIp.rak
|
||||||
|
CrazyLogin:
|
||||||
|
# CrazyLogin database file
|
||||||
|
fileName: accounts.db
|
||||||
Email:
|
Email:
|
||||||
# Email SMTP server host
|
# Email SMTP server host
|
||||||
mailSMTP: smtp.gmail.com
|
mailSMTP: smtp.gmail.com
|
||||||
|
@ -169,3 +169,6 @@ permissions:
|
|||||||
authme.admin.getip:
|
authme.admin.getip:
|
||||||
description: Get IP from a player ( fake and real )
|
description: Get IP from a player ( fake and real )
|
||||||
default: op
|
default: op
|
||||||
|
authme.admin.crazyloginimport:
|
||||||
|
description: Import CrazyLogin database into AuthMe database
|
||||||
|
default: op
|
Loading…
Reference in New Issue
Block a user