Skip to content

Commit

Permalink
fix bugs and sort mountain of "if"
Browse files Browse the repository at this point in the history
  • Loading branch information
Sodium-Aluminate committed Apr 20, 2021
1 parent 3d199ac commit 4b34563
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 53 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# HEX Counter
自动删掉群内除了数数之外的消息。

## 滥权
* 相比隔壁[乌鸦长老](https://github.com/sorz/ahgroupbot)不会线程堵塞,防止刷屏时删除消息滞后的困扰。
* 允许提前设置白名单~~让一部分人更加平等~~
* 允许多群组工作,群组列表和白名单支持 username
* 数数可以以 `0x` 开头表示是 16 进制,但即使没有也会被视为 16 进制。
* 禁止修改旧消息,否则在删除消息的同时禁言用户。

## 计数
* 十六进制
* 有用户修改时计数器半回滚防止数数失败。
* 数数可以以 `0x` 开头表示是 16 进制,但即使没有也会被视为 16 进制。
* 如果 bot 停止工作(因为关机或更新),需要白名单用户来重新起头

## Feature
* 允许提前设置白名单,可以发送其他消息和修改消息而不被禁言。
* 但白名单用户数数错误依旧会被删除
* 允许多群组工作,群组列表和白名单支持 username。
181 changes: 131 additions & 50 deletions src/com/NaAlOH4/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,27 @@

import javax.annotation.ParametersAreNonnullByDefault;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.regex.Pattern;

@ParametersAreNonnullByDefault

public class Main {

public static final Gson prettyGson = new GsonBuilder().setPrettyPrinting().create();
public static final String URL_HEAD = "https://api.telegram.org/bot";
public static final Options options = new Options()
.addOption("h", "help", false, "do nothing but print usage.")
.addOption("t", "token", true, "token from bot father")
.addOption("g", "group", true, "group id or @Username(ignore case).\n"+
.addOption("g", "group", true, "group id or @Username(ignore case).\n" +
"bot will only works in these group.\ncan be a regex(case sensitive), or split by \",\" or \"\"")
.addOption("c","continue",true,"continue count from a number(last sent).")
.addOption("i", "ignore", true, "a white list of uid or @Username(ignore case).\n"+
.addOption("i", "ignore", true, "a white list of uid or @Username(ignore case).\n" +
"bot will do nothing to their message. \ncan be a regex(case sensitive), or split by \",\" or \"\"")
.addOption(null,"keep-service-message",false, "keep service message like \"xxx joined group\"")
.addOption(null, "keep-service-message", false, "keep service message like \"xxx joined group\"")
.addOption("v", "verbose", false, "show more information.");

private static final OkHttpClient updateClient = new OkHttpClient.Builder().readTimeout(120, TimeUnit.SECONDS).build();
Expand All @@ -36,6 +39,10 @@ public class Main {
private static String token;
private static boolean verbose = false;

private static final Map<String, Long> latestCounts = new HashMap<>();
private static final Map<String, String> latestCounterIDs = new HashMap<>();
private static final Map<String, Boolean> rollBackTags = new HashMap<>();

public static void main(String[] args) {

CommandLine commandLine;
Expand All @@ -55,9 +62,7 @@ public static void main(String[] args) {
token = commandLine.getOptionValue("t");
final String whiteUser = commandLine.getOptionValue("i");
final boolean deleteServiceMessage = !commandLine.hasOption("keep-service-message");
final String continueNumber = commandLine.getOptionValue("c");
long latestCount = continueNumber==null ? -1 : Long.parseLong(continueNumber, 16);
@Nullable String latestCounterID = null;

verbose = commandLine.hasOption("v");


Expand All @@ -78,13 +83,12 @@ public static void main(String[] args) {
getCheckFunctionByArgument(whiteUser);



int offset = 0;
JsonArray result;
// update loop
while (true) {

if(verbose){
if (verbose) {
System.out.println("getting Updates...");
}
try {
Expand All @@ -95,14 +99,14 @@ public static void main(String[] args) {
.post(
new FormBody.Builder()
.add("timeout", "110")
.add("offset", String.valueOf(offset+1))
.add("offset", String.valueOf(offset + 1))
.build()
)
.build()
).execute();
JsonObject responseBody = new Gson().fromJson(response.body().string(), JsonObject.class);
if(verbose){
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(responseBody));
if (verbose) {
System.out.println(prettyGson.toJson(responseBody));
}
if (!responseBody.get("ok").getAsBoolean()) {
System.err.println(responseBody);
Expand All @@ -116,56 +120,119 @@ public static void main(String[] args) {
JsonObject jsonObject = (JsonObject) jsonElement;
offset = Math.max(jsonObject.get("update_id").getAsInt(), offset);


JsonObject message = jsonObject.getAsJsonObject("message");

if(message!=null) {
if (message != null) {
if (checkGroupInclude.test(message.getAsJsonObject("chat"))) {

boolean deleteMessage = true;

// check service message
if (message.has("new_chat_members") || message.has("left_chat_member")) {
deleteMessage = deleteServiceMessage;
} else if (message.has("text") && !message.has("reply_to_message")) {
if (deleteServiceMessage) deleteMessage(message);
if (verbose) System.out.println(prettyGson.toJson(message));
continue;
}

// check whiteList message
if (checkUserWhitelistInclude.test(message.getAsJsonObject("from"))) {
// if count
if (!message.has("text")) continue;
String text = message.get("text").getAsString();
if (text.startsWith("0x")) text = text.substring(2);
long currentCount;
try {
String text = message.get("text").getAsString();
if(text.startsWith("0x"))text = text.substring(2);
long currentCount = Long.parseLong(text, 16);
String currentCounterID = message.getAsJsonObject("from").get("id").getAsString();
if (currentCount - latestCount == 1 && !currentCounterID.equals(latestCounterID)) {
latestCount++;
latestCounterID = currentCounterID;
deleteMessage = false;
if(verbose){
System.out.println("counted to 0x"+ Long.toString(latestCount,16));
System.out.println("latest Counter id: "+latestCounterID);
currentCount = Long.parseLong(text, 16);
} catch (NumberFormatException ignore) {
continue;
}
String chatID = message.getAsJsonObject("chat").get("id").getAsString();
String currentCounterID = message.getAsJsonObject("from").get("id").getAsString();

// check if group init
if (latestCounts.containsKey(chatID)) {

if (checkDelta(currentCount, chatID)) {
// is normal count, ignore.
latestCounts.put(chatID, currentCount);
latestCounterIDs.put(chatID, currentCounterID);
if (verbose) {
System.out.println(chatID + " counted to 0x" + Long.toString(currentCount, 16));
System.out.println("latest Counter id: " + currentCounterID + " (whitelist user)");
}
} else {
// delete wrong count
deleteMessage(message);
if (verbose) {
System.err.println("whitelist user " + message.getAsJsonObject("from").get("id").getAsString() + " counts wrong!");
System.err.println("latest is 0x" + Long.toString(latestCounts.get(chatID), 16) + " but he count 0x" + Long.toString(currentCount, 16));
}
}
} catch (NumberFormatException ignore) {
} else {
//init
if (verbose)
System.out.println("(whitelist user) inited group " + chatID + ", count to 0x" + Long.toString(currentCount, 16));
latestCounts.put(chatID, currentCount);
latestCounterIDs.put(chatID, message.getAsJsonObject("from").get("id").getAsString());
}
continue;
}

// Easter egg: @xierch can send "啊啊啊" at ANY times
if (
message.getAsJsonObject("from").has("username") &&
message.getAsJsonObject("from").get("username").getAsString().equals("xierch") &&
message.has("text") &&
message.get("text").getAsString().matches("啊*")
) {
continue;
}

if (checkUserWhitelistInclude.test(message.getAsJsonObject("from")))
deleteMessage = false;
// check is normal text message
if (message.has("text") && !message.has("reply_to_message")) {
String text = message.get("text").getAsString();
if (text.startsWith("0x")) text = text.substring(2);
long currentCount;
try {
currentCount = Long.parseLong(text, 16);
} catch (NumberFormatException e) {
// not a number, delete.
deleteMessage(message);
continue;
}

String currentCounterID = message.getAsJsonObject("from").get("id").getAsString();
String chatID = message.getAsJsonObject("chat").get("id").getAsString();

if (deleteMessage) {
if (checkDelta(currentCount, chatID) && !currentCounterID.equals(latestCounterIDs.get(chatID))) {
latestCounts.put(chatID, currentCount);
latestCounterIDs.put(chatID, currentCounterID);
if (verbose) {
System.out.println(chatID + "counted to 0x" + Long.toString(currentCount, 16));
System.out.println("latest Counter id: " + currentCounterID);
}
} else {
deleteMessage(message);
}
} else {
// delete non-text message and replys
deleteMessage(message);
}

}
}else {
if (jsonObject.has("edited_message")){
} else {
if (jsonObject.has("edited_message")) {
JsonObject editedMessage = jsonObject.getAsJsonObject("edited_message");
if (checkGroupInclude.test(editedMessage.getAsJsonObject("chat"))
&& !checkUserWhitelistInclude.test(editedMessage.getAsJsonObject("from"))) {
deleteMessage(editedMessage);
banUser(editedMessage);
rollBackTags.put(editedMessage.getAsJsonObject("chat").get("id").getAsString(), true);
}
}
}
}

} catch (IOException | NullPointerException e) {
if(verbose){
if (verbose) {
e.printStackTrace();
}
}
Expand All @@ -190,11 +257,13 @@ private static boolean isNumber(String string) {
/**
* split a string by "," or ","
* any of them must be
*
* @return null if not a list.
*/

private static @Nullable String[] parseList(String string) {
if (!string.toLowerCase().matches("[a-z0-9_,,]")) return null;
private static @Nullable
String[] parseList(String string) {
if (!string.toLowerCase().matches("[@a-z0-9_,,]*")) return null;
final String[] keys = string.split("[,,]");
for (String key : keys) {
if (!isNumber(key) && !isUsername(key)) {
Expand All @@ -205,20 +274,21 @@ private static boolean isNumber(String string) {
}



private static Predicate<JsonObject> getCheckFunctionByArgument(String arg) {
if (isNumber(arg)) return json -> arg.equals(json.get("id").getAsString());
if (isUsername(arg)) {
final String username = arg.substring((arg.startsWith("@")) ? 1 : 0);
return json -> username.equalsIgnoreCase(json.get("username").getAsString());
}
final String[] keys = parseList(arg);
if(keys != null) {
if (keys != null) {
final LinkedList<String> UIDs = new LinkedList<>();
final LinkedList<String> usernames = new LinkedList<>();
for (String key : keys) {
if (isNumber(key)) UIDs.add(key);
else if (isUsername(key)) usernames.add(key);
else if (isUsername(key)) usernames.add(
key.startsWith("@") ? key.substring(1) : key
);
else throw new WTFException();
}

Expand All @@ -242,7 +312,19 @@ private static Predicate<JsonObject> getCheckFunctionByArgument(String arg) {
};
}

private static void deleteMessage(JsonObject message){
private static boolean checkDelta(long current, String chatID) {
if (!latestCounts.containsKey(chatID)) return false;
long delta = current - latestCounts.get(chatID);

if (delta == 1) return true;
if (delta == 0 && rollBackTags.containsKey(chatID) && rollBackTags.get(chatID)) {
rollBackTags.put(chatID, false);
return true;
}
return false;
}

private static void deleteMessage(JsonObject message) {
new Thread(() -> {
boolean deleted = false;
for (int i = 1; i <= 3; i++) {
Expand All @@ -269,22 +351,22 @@ private static void deleteMessage(JsonObject message){
} catch (IOException | NullPointerException | JsonSyntaxException e) {
if (verbose) {
System.err.println("trying to delete message failed(" + i + "/3): ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(message));
System.err.println(prettyGson.toJson(message));
if (deleteResponseJson != null) {
System.err.println("return: ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(deleteResponseJson));
System.err.println(prettyGson.toJson(deleteResponseJson));
}
}
}
}
if (!deleted) {
System.err.println("trying to delete message failed 3 times: ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(message));
System.err.println(prettyGson.toJson(message));
}
}).start();
}

private static void banUser(JsonObject message){
private static void banUser(JsonObject message) {
new Thread(() -> {
boolean banned = false;
for (int i = 1; i <= 3; i++) {
Expand Down Expand Up @@ -314,19 +396,18 @@ private static void banUser(JsonObject message){
} catch (IOException | NullPointerException | JsonSyntaxException e) {
if (verbose) {
System.err.println("trying to ban user failed(" + i + "/3): ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(message));
System.err.println(prettyGson.toJson(message));
if (responseJson != null) {
System.err.println("return: ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(responseJson));
System.err.println(prettyGson.toJson(responseJson));
}
}
}
}
if (!banned) {
System.err.println("trying to ban user failed 3 times: ");
System.err.println(new GsonBuilder().setPrettyPrinting().create().toJson(message));
System.err.println(prettyGson.toJson(message));
}
}).start();
}

}

0 comments on commit 4b34563

Please sign in to comment.