Skip to content

Commit

Permalink
feat: At command
Browse files Browse the repository at this point in the history
  • Loading branch information
xslingcn committed May 11, 2022
1 parent 6932183 commit 475e7d3
Show file tree
Hide file tree
Showing 15 changed files with 170 additions and 4 deletions.
2 changes: 2 additions & 0 deletions bungee/src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ illegalArgument=Illegal arguments
invalidUserName=Invalid username
invalidQQID=&4Invalid QQ ID.
notBoundYet=You haven't bound your username
boundPlayerNotFound=Player record not found
atSent=&3Successfully sent &7&o@{1} &3in &7&o{0}
completeBindInGame=Perform following command in game to confirm
completeBindInGroup=&3Send following command in QQ group to confirm
clickToCopy=Click to copy
Expand Down
2 changes: 2 additions & 0 deletions bungee/src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ illegalArgument=Illegal arguments
invalidUserName=Invalid username
invalidQQID=&4Invalid QQ ID.
notBoundYet=You haven't bound your username
boundPlayerNotFound=Player record not found
atSent=&3Successfully sent &7&o@{1} &3in &7&o{0}
completeBindInGame=Perform following command in game to confirm
completeBindInGroup=&3Send following command in QQ group to confirm
clickToCopy=Click to copy
Expand Down
2 changes: 2 additions & 0 deletions bungee/src/main/resources/messages_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ illegalArgument=参数错误
invalidUserName=用户名无效
invalidQQID=&4QQ号无效
notBoundYet=您尚未绑定
boundPlayerNotFound=未查询到玩家绑定信息
atSent=&3已在&7&o{0}&3中&7&o@{1}
completeBindInGame=请在游戏内输入以下指令完成绑定
completeBindInGroup=&3请在QQ群输入以下指令完成绑定
clickToCopy=点击复制
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public String check() throws IllegalArgumentException {
throw new IllegalArgumentException(i18n("invalidCode"));

BindResult bindResult = new Confirm(identifier, code).get();
phenyl.updateBoundPlayerList();

// Code not found in binding queue.
if (bindResult == null) throw new IllegalArgumentException(i18n("invalidCode"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public enum ServerCommand {
BIND("bind", 2, "phenyl.use.bind"),
VERIFY("verify", 2, "phenyl.use.verify"),
SAY("say", 2, "phenyl.use.say"),
NOMESSAGE("nomessage", 1, "phenyl.use.nomessage");
NOMESSAGE("nomessage", 1, "phenyl.use.nomessage"),
AT("at", 2, "phenyl.use.at");

final String prompt;
final Integer argCnt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.mamoe.mirai.contact.Group;
import net.mamoe.mirai.contact.Member;
import net.mamoe.mirai.message.data.At;
import net.mamoe.mirai.message.data.MessageChain;
import net.mamoe.mirai.message.data.MessageChainBuilder;
import org.apache.logging.log4j.Logger;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
Expand Down Expand Up @@ -60,7 +66,7 @@ public void match() throws RuntimeException {
else match.forEach(cmd -> {
if (sender.isConsole())
switch (args[0].toLowerCase()) {
case "bind", "verify", "say", "nomessage" -> throw new RuntimeException(i18n("commandNotFoundPhenyl"));
case "bind", "verify", "say", "nomessage", "at" -> throw new RuntimeException(i18n("commandNotFoundPhenyl"));
}
if (!sender.hasPermission(cmd.permission)) throw new RuntimeException(i18n("noPermission"));
if (!cmd.argCnt.equals(args.length))
Expand All @@ -71,6 +77,7 @@ public void match() throws RuntimeException {
case "verify" -> verify();
case "say" -> say();
case "nomessage" -> noMessage();
case "at" -> at();
}
}
switch (args[0]) {
Expand Down Expand Up @@ -240,4 +247,31 @@ private void noMessage() {
phenyl.getMessenger().sendPlayer(i18n("noMessage"), sender);
}
}

private void at() {
List<Player> playerList = phenyl.getAllBoundPlayer();
if (playerList.isEmpty()) throw new RuntimeException(i18n("boundPlayerNotFound"));
if (playerList.stream().noneMatch(player -> player.mcname().equals(args[1])))
throw new RuntimeException(i18n("boundPlayerNotFound"));
Player targetPlayer = playerList.stream().filter(player -> player.mcname().equals(args[1])).findFirst().get();
// get the pattern before and after %message%
String[] format = Config.server_to_qq_format
.replace("%sub_server%", new MessageUtils(phenyl).getServerName(sender.getServerName()))
.replace("%username%", sender.getUsername())
.split("%message%");
for (Long id : Config.enabled_groups) {
try {
Group group = phenyl.getMirai().getBot().getGroupOrFail(id);
Member target = group.getOrFail(targetPlayer.qqid());
MessageChain message = new MessageChainBuilder()
.append(format[0])
.append(new At(target.getId()))
.append(format.length > 1 ? format[1] : "")
.build();
phenyl.getMessenger().sendGroup(group, message);
phenyl.getMessenger().sendPlayer(i18n("atSent", group.getName(), target.getNameCard().isEmpty() ? target.getNick() : target.getNameCard()), sender);
} catch (NoSuchElementException ignored) {
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package live.turna.phenyl.common.command;

import live.turna.phenyl.common.database.Player;
import live.turna.phenyl.common.instance.PSender;
import live.turna.phenyl.common.plugin.AbstractPhenyl;

Expand Down Expand Up @@ -41,6 +42,12 @@ public Iterable<String> onTabComplete() {
playerList.forEach(player -> completions.add(player.getUsername()));
return completions;
}
if (args[0].equals("at")) {
if (phenyl.getAllBoundPlayer().isEmpty()) return completions;
List<Player> playerList = phenyl.getAllBoundPlayer().stream().filter(player -> player.mcname().startsWith(args[1])).toList();
playerList.subList(0, Math.min(10, playerList.size())).forEach(player -> completions.add(player.mcname()));
return completions;
}
}
}
return completions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ public interface PhenylStorage {
*/
List<Player> getNoMessagePlayer();

/**
* Get the list of all bound players;
*
* @return A list of player instances, of which would never hold a NULL qqid. Could be empty if no one had bound yet.
*/
List<Player> getAllBoundPlayer();

/**
* Add a binding.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public List<Player> getNoMessagePlayer() {
return getPlayerList("nomessage", "1");
}

public List<Player> getAllBoundPlayer() {
return getNotNUllPlayerList("qqid");
}

public boolean addBinding(String uuid, Long qqid) {
return updatePlayer("qqid", qqid.toString(), "uuid", uuid);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class MySQL extends AbstractSQLStorage {
private static final String selectPlayer = "SELECT * FROM %splayer WHERE %s=%s LIMIT 1;";
private static final String selectPlayerList = "SELECT * FROM %splayer WHERE %s=%s;";
private static final String selectNotNullPlayerList = "SELECT * FROM %splayer WHERE %s IS NOT NULL;";
private static final String updatePlayer = "UPDATE %splayer SET %s=%s WHERE %s=%s;";
private static final String insertPlayer = "INSERT IGNORE INTO %splayer(%s) VALUES('%s');";
private static final String insertMessage = "INSERT IGNORE INTO %smessage(%s) VALUES(%s);";
Expand Down Expand Up @@ -112,6 +113,29 @@ public List<Player> getPlayerList(String selectColumn, String selectValue) {
return result;
}

public List<Player> getNotNUllPlayerList(String selectColumn) {
ResultSet resultSet;
List<Player> result = new java.util.ArrayList<>();
try {
Connection connection = dataSource.getConnection();
resultSet = connection.prepareStatement(String.format(selectNotNullPlayerList, Config.table_prefix, selectColumn)).executeQuery();
if (resultSet.isBeforeFirst()) {
while (resultSet.next()) {
result.add(new Player(resultSet.getInt("id"),
resultSet.getString("uuid"),
Long.parseLong(resultSet.getString("qqid")),
resultSet.getString("mcname")));
}
}
connection.close();
return result;
} catch (SQLException e) {
LOGGER.error(i18n("queryFail"), e.getLocalizedMessage());
if (Config.debug) e.printStackTrace();
}
return result;
}

public boolean updatePlayer(String setColumn, String setValue, String selectColumn, String selectValue) {
if (!setColumn.equalsIgnoreCase("qqid")) setValue = String.format("'%s'", setValue);
if (!selectColumn.equalsIgnoreCase("qqid")) selectValue = String.format("'%s'", selectValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class PostgreSQL extends AbstractSQLStorage {
private static final String selectPlayer = "SELECT * FROM %splayer WHERE %s=%s LIMIT 1;";
private static final String selectPlayerList = "SELECT * FROM %splayer WHERE %s=%s;";
private static final String selectNotNullPlayerList = "SELECT * FROM %splayer WHERE %s IS NOT NULL;";
private static final String updatePlayer = "UPDATE %splayer SET %s=%s WHERE %s=%s;";
private static final String insertPlayer = "INSERT INTO %splayer(%s) VALUES('%s') ON CONFLICT DO NOTHING;";
private static final String insertMessage = "INSERT INTO %smessage(%s) VALUES(%s) ON CONFLICT DO NOTHING;";
Expand Down Expand Up @@ -109,6 +110,29 @@ public List<Player> getPlayerList(String selectColumn, String selectValue) {
return result;
}

public List<Player> getNotNUllPlayerList(String selectColumn) {
ResultSet resultSet;
List<Player> result = new java.util.ArrayList<>();
try {
Connection connection = dataSource.getConnection();
resultSet = connection.prepareStatement(String.format(selectNotNullPlayerList, Config.table_prefix, selectColumn)).executeQuery();
if (resultSet.isBeforeFirst()) {
while (resultSet.next()) {
result.add(new Player(resultSet.getInt("id"),
resultSet.getString("uuid"),
Long.parseLong(resultSet.getString("qqid")),
resultSet.getString("mcname")));
}
}
connection.close();
return result;
} catch (SQLException e) {
LOGGER.error(i18n("queryFail"), e.getLocalizedMessage());
if (Config.debug) e.printStackTrace();
}
return result;
}

public boolean updatePlayer(String setColumn, String setValue, String selectColumn, String selectValue) {
if (!setColumn.equalsIgnoreCase("qqid")) setValue = String.format("'%s'", setValue);
if (!selectColumn.equalsIgnoreCase("qqid")) selectValue = String.format("'%s'", selectValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ public interface SQLQuery {
*/
List<Player> getPlayerList(String selectColumn, String selectValue);

/**
* Get a list of player of which the selected column IS NOT NULL.
*
* @param selectColumn The column to select.
* @return An empty list if not any player found, or a list of player instances.
*/
List<Player> getNotNUllPlayerList(String selectColumn);

/**
* Update players in database.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
public class SQLite extends AbstractSQLStorage {
private static final String selectPlayer = "SELECT * FROM player WHERE %s=%s LIMIT 1;";
private static final String selectPlayerList = "SELECT * FROM player WHERE %s=%s;";
private static final String selectNotNullPlayerList = "SELECT * FROM player WHERE %s IS NOT NULL;";
private static final String updatePlayer = "UPDATE player SET %s=%s WHERE %s=%s;";
private static final String insertPlayer = "INSERT OR IGNORE INTO player(%s) VALUES('%s');";
private static final String insertMessage = "INSERT INTO message(%s) VALUES(%s);";
Expand Down Expand Up @@ -117,6 +118,29 @@ public List<Player> getPlayerList(String selectColumn, String selectValue) {
return result;
}

public List<Player> getNotNUllPlayerList(String selectColumn) {
ResultSet resultSet;
List<Player> result = new java.util.ArrayList<>();
try {
player = playerConnection.createStatement();
resultSet = player.executeQuery(String.format(selectNotNullPlayerList, selectColumn));
if (resultSet.isBeforeFirst()) {
while (resultSet.next()) {
result.add(new Player(resultSet.getInt("id"),
resultSet.getString("uuid"),
Long.parseLong(resultSet.getString("qqid")),
resultSet.getString("mcname")));
}
player.close();
return result;
}
} catch (SQLException e) {
LOGGER.error(i18n("queryFail"), e.getLocalizedMessage());
if (Config.debug) e.printStackTrace();
}
return result;
}

public boolean updatePlayer(String setColumn, String setValue, String selectColumn, String selectValue) {
if (!setColumn.equalsIgnoreCase("qqid")) setValue = String.format("'%s'", setValue);
if (!selectColumn.equalsIgnoreCase("qqid") && !selectValue.equalsIgnoreCase("null"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public abstract class AbstractPhenyl implements PhenylPlugin {
protected BindHandler bindHandler;
protected List<Player> mutedPlayer = new ArrayList<>();
protected List<Player> noMessagePlayer = new ArrayList<>();
protected List<Player> allBoundPlayer = new ArrayList<>();

private Logger LOGGER;

Expand Down Expand Up @@ -59,6 +60,9 @@ public final boolean enable() {
if (!postConfig()) return false;

storage = new StorageFactory(this).createStorage(Config.storage.toLowerCase());
mutedPlayer = storage.getMutedPlayer();
noMessagePlayer = storage.getNoMessagePlayer();
allBoundPlayer = storage.getAllBoundPlayer();
initMirai();
initSenderFactory();
initMessenger();
Expand All @@ -70,6 +74,7 @@ public final boolean enable() {
public final boolean reload() {
mutedPlayer = null;
noMessagePlayer = null;
allBoundPlayer = null;
storage.shutdown();

loadConfig();
Expand All @@ -83,6 +88,9 @@ public final boolean reload() {
mirai = null;

storage = new StorageFactory(this).createStorage(Config.storage.toLowerCase());
mutedPlayer = storage.getMutedPlayer();
noMessagePlayer = storage.getNoMessagePlayer();
allBoundPlayer = storage.getAllBoundPlayer();
initMirai();
return true;
}
Expand All @@ -95,8 +103,6 @@ public final void disable() {
}

private void initMirai() {
mutedPlayer = storage.getMutedPlayer();
noMessagePlayer = storage.getNoMessagePlayer();
CompletableFuture.supplyAsync(() -> {
try {
mirai = new MiraiHandler(this, Config.user_id, Config.user_pass, Config.login_protocol);
Expand Down Expand Up @@ -131,6 +137,14 @@ public List<Player> getNoMessagePlayer() {
return noMessagePlayer;
}

public List<Player> getAllBoundPlayer() {
return allBoundPlayer;
}

public void updateBoundPlayerList() {
allBoundPlayer = storage.getAllBoundPlayer();
}

public BindHandler getBindHandler() {
return bindHandler;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ public interface PhenylPlugin {
*/
List<Player> getNoMessagePlayer();

/**
* Get the list of all bound players;
*
* @return A list of player instances, of which would never hold a NULL qqid. Could be empty if no one had bound yet.
*/
List<Player> getAllBoundPlayer();

/**
* Get the bound player list from storage again. Called after each binding operation.
*/
void updateBoundPlayerList();

/**
* Get a player instance by username.
*
Expand Down

0 comments on commit 475e7d3

Please # to comment.