From e808a37fb2537cc4030e736de3ddd8160a2010e7 Mon Sep 17 00:00:00 2001 From: Eyre_S Date: Mon, 27 Dec 2021 17:01:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20tgapi.HTML=20=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E5=99=A8=E5=B9=B6=E8=A1=A5=E5=85=A8=E8=B0=83=E7=94=A8?= =?UTF-8?q?=20(#19)=EF=BC=8C=E8=A1=A5=E5=85=A8=20IP186/javadoc=20(#18)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修订 Telegram HTML 实体转义 (#19 - 为所有 HTML 内嵌输入补全转义代码 - 移除了 apache-commons-text 类库 - 添加了自己的 HTML 实体转义类 - 补充 IP186(#17) 的 javadoc (#18 --- build.gradle | 1 - gradle.properties | 3 +- .../cono/morny/GradleProjectConfigures.java | 4 +-- .../cono/morny/bot/event/OnCallMe.java | 23 ++++++++---- .../morny/bot/event/OnCommandExecute.java | 36 ++++++++++--------- .../morny/bot/event/OnEventHackHandle.java | 3 +- .../morny/bot/event/OnUserSlashAction.java | 12 ++++--- .../event/on_commands/GetUsernameAndId.java | 10 +++--- .../bot/event/on_commands/Ip186Query.java | 11 ++++-- .../cc/sukazyo/cono/morny/data/MornyJrrp.java | 22 ++++++++++++ .../morny/data/ip186/IP186QueryHandler.java | 35 ++++++++++++++++++ .../morny/data/ip186/IP186QueryResponse.java | 7 ++++ .../sukazyo/cono/morny/util/StringUtils.java | 16 ++++----- 13 files changed, 135 insertions(+), 48 deletions(-) diff --git a/build.gradle b/build.gradle index 5dc0fd9..2b36477 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,6 @@ repositories { dependencies { compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${libSpotbugsVersion}" - implementation "org.apache.commons:commons-text:${libApacheCommonsTextVersion}" api "cc.sukazyo:messiva:${libMessivaVersion}" diff --git a/gradle.properties b/gradle.properties index 9690518..f697b89 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,10 @@ ## Core -VERSION = 0.4.2.10 +VERSION = 0.4.2.11 # dependencies libSpotbugsVersion = 4.5.2 -libApacheCommonsTextVersion = 1.9 libMessivaVersion = 0.1.0.1 diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java index b810d23..4760921 100644 --- a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java +++ b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java @@ -4,6 +4,6 @@ package cc.sukazyo.cono.morny; * the final field that will be updated by gradle automatically. */ public class GradleProjectConfigures { - public static final String VERSION = "0.4.2.10"; - public static final long COMPILE_TIMESTAMP = 1640434011159L; + public static final String VERSION = "0.4.2.11"; + public static final long COMPILE_TIMESTAMP = 1640595623685L; } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java index 911cb4f..f105b9e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java @@ -13,6 +13,8 @@ import com.pengrad.telegrambot.request.SendSticker; import javax.annotation.Nonnull; +import static cc.sukazyo.cono.morny.util.StringUtils.escapeHtmlTelegram; + /** * 通过 bot 呼叫主人的事件监听管理类 * @since 0.4.2.1 @@ -69,11 +71,14 @@ public class OnCallMe extends EventListener { */ private static void requestSteamJoin (Update event) { MornyCoeur.getAccount().execute(new SendMessage( - ME, String.format(""" + ME, String.format( + """ request STEAM LIBRARY from %s""", event.message().from().id(), - event.message().from().firstName() + " " + event.message().from().lastName() + escapeHtmlTelegram( + event.message().from().firstName() + " " + event.message().from().lastName() + ) ) ).parseMode(ParseMode.HTML)); } @@ -86,11 +91,14 @@ public class OnCallMe extends EventListener { */ private static void requestHanaParesuJoin (Update event) { MornyCoeur.getAccount().execute(new SendMessage( - ME, String.format(""" + ME, String.format( + """ request Hana Paresu from %s""", event.message().from().id(), - event.message().from().firstName() + " " + event.message().from().lastName() + escapeHtmlTelegram( + event.message().from().firstName() + " " + event.message().from().lastName() + ) ) ).parseMode(ParseMode.HTML)); } @@ -111,11 +119,14 @@ public class OnCallMe extends EventListener { */ private static void requestCustomCall (Update event) { MornyCoeur.getAccount().execute(new SendMessage( - ME, String.format(""" + ME, String.format( + """ request [???] from %s""", event.message().from().id(), - event.message().from().firstName() + " " + event.message().from().lastName() + escapeHtmlTelegram( + event.message().from().firstName() + " " + event.message().from().lastName() + ) ) ).parseMode(ParseMode.HTML)); MornyCoeur.getAccount().execute(new ForwardMessage( diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java index 486430f..a49d884 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java @@ -10,7 +10,6 @@ import cc.sukazyo.cono.morny.bot.event.on_commands.GetUsernameAndId; import cc.sukazyo.cono.morny.bot.event.on_commands.Ip186Query; import cc.sukazyo.cono.morny.data.MornyJrrp; import cc.sukazyo.cono.morny.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.CommonFormatUtils; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; @@ -19,6 +18,9 @@ import com.pengrad.telegrambot.request.SendSticker; import javax.annotation.Nonnull; import static cc.sukazyo.cono.morny.Log.logger; +import static cc.sukazyo.cono.morny.util.CommonFormatUtils.formatDate; +import static cc.sukazyo.cono.morny.util.CommonFormatUtils.formatDuration; +import static cc.sukazyo.cono.morny.util.StringUtils.escapeHtmlTelegram; public class OnCommandExecute extends EventListener { @@ -117,7 +119,8 @@ public class OnCommandExecute extends EventListener { private void onCommandVersionExec (@Nonnull Update event) { MornyCoeur.getAccount().execute(new SendMessage( event.message().chat().id(), - String.format(""" + String.format( + """ version: - %s core md5_hash: @@ -125,10 +128,10 @@ public class OnCommandExecute extends EventListener { compile timestamp: - %d - %s [UTC]""", - MornySystem.VERSION, - MornySystem.getJarMd5(), + escapeHtmlTelegram(MornySystem.VERSION), + escapeHtmlTelegram(MornySystem.getJarMd5()), GradleProjectConfigures.COMPILE_TIMESTAMP, - CommonFormatUtils.formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0) + escapeHtmlTelegram(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)) ) ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } @@ -160,24 +163,24 @@ public class OnCommandExecute extends EventListener { - %s [UTC] - [%d]""", // system - System.getProperty("os.name"), - System.getProperty("os.version"), + escapeHtmlTelegram(System.getProperty("os.name")), + escapeHtmlTelegram(System.getProperty("os.version")), Runtime.getRuntime().availableProcessors(), // java - System.getProperty("java.vm.name"), - System.getProperty("java.version"), + escapeHtmlTelegram(System.getProperty("java.vm.name")), + escapeHtmlTelegram(System.getProperty("java.version")), // memory Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().maxMemory() / 1024 / 1024, // version - MornySystem.VERSION, - MornySystem.getJarMd5(), - CommonFormatUtils.formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0), + escapeHtmlTelegram(MornySystem.VERSION), + escapeHtmlTelegram(MornySystem.getJarMd5()), + escapeHtmlTelegram(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)), GradleProjectConfigures.COMPILE_TIMESTAMP, // continuous - CommonFormatUtils.formatDuration(System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp), + escapeHtmlTelegram(formatDuration(System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp)), System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp, - CommonFormatUtils.formatDate(MornyCoeur.coeurStartTimestamp, 0), + escapeHtmlTelegram(formatDate(MornyCoeur.coeurStartTimestamp, 0)), MornyCoeur.coeurStartTimestamp ) ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); @@ -190,8 +193,9 @@ public class OnCommandExecute extends EventListener { event.message().chat().id(), String.format( "%s 在(utc的)今天的运气指数是———— %.2f%% %s", - event.message().from().id(), event.message().from().firstName(), - jrrp, endChar + event.message().from().id(), + escapeHtmlTelegram(event.message().from().firstName()), + jrrp, escapeHtmlTelegram(endChar) ) ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java index ffabd4e..a4275a4 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java @@ -2,6 +2,7 @@ package cc.sukazyo.cono.morny.bot.event; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.bot.api.EventListener; +import cc.sukazyo.cono.morny.util.StringUtils; import com.google.gson.GsonBuilder; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; @@ -65,7 +66,7 @@ public class OnEventHackHandle extends EventListener { logger.debug("hacked event by " + x); MornyCoeur.getAccount().execute(new SendMessage(x.fromChatId, String.format( "%s", - new GsonBuilder().setPrettyPrinting().create().toJson(update) + StringUtils.escapeHtmlTelegram(new GsonBuilder().setPrettyPrinting().create().toJson(update)) )).parseMode(ParseMode.HTML).replyToMessageId((int)x.fromMessageId)); return true; } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.java index 19db7e5..67dff8a 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.java @@ -10,6 +10,8 @@ import com.pengrad.telegrambot.request.SendMessage; import javax.annotation.Nonnull; +import static cc.sukazyo.cono.morny.util.StringUtils.escapeHtmlTelegram; + public class OnUserSlashAction extends EventListener { @Override @@ -48,11 +50,11 @@ public class OnUserSlashAction extends EventListener { event.message().chat().id(), String.format( "%s %s%s %s%s%s", - origin.id(), origin.firstName(), - verb, (useVerbSuffix?"了":""), - target.id(), (origin==target ? "自己" : target.firstName()), - (hasObject ? (useObjectPrefix ?" 的": " ") : ""), - (hasObject ? object : "") + origin.id(), escapeHtmlTelegram(origin.firstName()), + verb, escapeHtmlTelegram((useVerbSuffix?"了":"")), + target.id(), escapeHtmlTelegram((origin==target ? "自己" : target.firstName())), + escapeHtmlTelegram((hasObject ? (useObjectPrefix ?" 的": " ") : "")), + escapeHtmlTelegram((hasObject ? object : "")) ) ).parseMode(ParseMode.HTML)); diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java index 6ed80af..b5cd025 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java @@ -10,6 +10,8 @@ import com.pengrad.telegrambot.response.GetChatMemberResponse; import javax.annotation.Nonnull; +import static cc.sukazyo.cono.morny.util.StringUtils.escapeHtmlTelegram; + public class GetUsernameAndId { public static void exec (@Nonnull String[] args, @Nonnull Update event) { @@ -65,7 +67,7 @@ public class GetUsernameAndId { username : - %s""", - user.username() + escapeHtmlTelegram(user.username()) )); } if (user.firstName() == null) { @@ -76,7 +78,7 @@ public class GetUsernameAndId { firstname : - %s""", - user.firstName() + escapeHtmlTelegram(user.firstName()) )); } if (user.lastName() == null) { @@ -87,7 +89,7 @@ public class GetUsernameAndId { lastname : - %s""", - user.lastName() + escapeHtmlTelegram(user.lastName()) )); } if (user.languageCode() != null) { @@ -96,7 +98,7 @@ public class GetUsernameAndId { language-code : - %s""", - user.languageCode() + escapeHtmlTelegram(user.languageCode()) )); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java index 9186707..3c73c8a 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java @@ -7,10 +7,15 @@ import cc.sukazyo.cono.morny.data.ip186.IP186QueryHandler; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; -import org.apache.commons.text.StringEscapeUtils; import javax.annotation.Nonnull; +import static cc.sukazyo.cono.morny.util.StringUtils.escapeHtmlTelegram; + +/** + * {@value IP186QueryHandler#SITE_URL} 查询的 telegram 命令前端 + * @since 0.4.2.10 + */ public class Ip186Query { public static void exec (@Nonnull Update event, @Nonnull InputCommand command) { @@ -33,12 +38,12 @@ public class Ip186Query { }; MornyCoeur.getAccount().execute(new SendMessage( event.message().chat().id(), - response.url() + "\n" + StringEscapeUtils.escapeHtml4(response.body()) + "" + escapeHtmlTelegram(response.url()) + "\n" + escapeHtmlTelegram(response.body()) + "" ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); } catch (Exception e) { MornyCoeur.getAccount().execute(new SendMessage( event.message().chat().id(), - "[Exception] in query:\n" + e.getMessage() + "" + "[Exception] in query:\n" + escapeHtmlTelegram(e.getMessage()) + "" ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); } diff --git a/src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java b/src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java index eb80f66..2fd858e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java +++ b/src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java @@ -12,10 +12,32 @@ import com.pengrad.telegrambot.model.User; */ public class MornyJrrp { + /** + * 通过 telegram 用户和时间戳作为参数获取 jrrp. + * + * @see #calcJrrpXmomi 当前版本的实现算法 {@code Xmomi} + * @since 0.4.2.9 + * @param user telegram 用户 + * @param timestamp 时间戳 + * @return 通过当前版本的算法计算出的用户 jrrp 值,取值为 {@code [0.00, 100.00]} + */ public static double getJrrpFromTelegramUser (User user, long timestamp) { return calcJrrpXmomi(user.id(), timestamp / (1000 * 60 * 60 * 24)) * 100.0; } + /** + * {@code Xmomi} 版本的 jrrp 算法. + *

+ * 算法规则为,将用户id与日期戳链接为 uid@daystamp 这样的字符串, + * 然后通过 MD5 计算出字符串的哈希值,取哈希值前4个字节,将其作为16进制数值表示法转换为取值为 {@code [0x0000, 0xffff]} 的数值, + * 得到的数值除以区间最大值 {@code 0xffff} 即可得到一个分布在 {@code [0.0, 1.0]} 之间的分布值, + * 这个分布值乘以 {@code 100.0},即为计算得到的 jrrp 数值。 + * + * @since 0.4.2.9 + * @param userId telegram 用户 uid + * @param dayStamp unix 时间戳转换为日期单位后的数值. 数值应该在转换前转换时区 + * @return 算法得到的 jrrp 值,取值为 {@code [0.00. 100.00]} + */ public static double calcJrrpXmomi (long userId, long dayStamp) { return (double)Long.parseLong(EncryptUtils.encryptByMD5(userId + "@" + dayStamp).substring(0, 4), 16) / (double)0xffff; } diff --git a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java index fcfe0da..c29d0b9 100644 --- a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java +++ b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java @@ -8,20 +8,55 @@ import okhttp3.ResponseBody; import javax.annotation.Nonnull; import java.io.IOException; +/** + * 通过 {@value #SITE_URL} 进行 {@link #queryIp ip}/{@link #queryWhois whois} 数据查询的工具类 + * + * @since 0.4.2.10 + */ public class IP186QueryHandler { + /** + * 请求所使用的 HTTP API 站点链接 + * @since 0.4.2.10 + */ public static final String SITE_URL = "https://ip.186526.xyz/"; + /** + * 进行 {@link #queryIp ip 查询}时所使用的 API 参数.
+ * 目的使 API 直接返回原始数据 + */ private static final String QUERY_IP_PARAM = "type=json&format=true"; + + /** + * 进行 {@link #queryWhois whois 查询}时所使用的 API 参数.
+ * 目的使 API 直接返回原始数据 + */ private static final String QUERY_WHOIS_PARAM = "type=plain"; + /** 请求时使用的 OkHttp 请求工具实例 */ private static final OkHttpClient httpClient = new OkHttpClient(); + /** + * 通过 {@value #SITE_URL} 获取 ip 信息. + * @see #QUERY_IP_PARAM 发送请求时所使用的 API 参数 + * @param ip 需要进行查询的 ip + * @return 查询结果。data 根据 {@value #SITE_URL} 的规则以 json 序列化 + * @throws IOException 任何请求或解析错误 + */ + @Nonnull public static IP186QueryResponse queryIp (String ip) throws IOException { final String requestUrl = SITE_URL + ip; return commonQuery(requestUrl, QUERY_IP_PARAM); } + /** + * 通过 {@value #SITE_URL} 获取域名信息. + * @see #QUERY_WHOIS_PARAM 发送请求时所使用的 API 参数 + * @param domain 需要进行查询的域名 + * @return 查询结果。data 根据 {@value #SITE_URL} 的规则以 plain 序列化 + * @throws IOException 任何请求或解析错误 + */ + @Nonnull public static IP186QueryResponse queryWhois (String domain) throws IOException { final String requestUrl = SITE_URL + "whois/" + domain; return commonQuery(requestUrl, QUERY_WHOIS_PARAM); diff --git a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryResponse.java b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryResponse.java index 24c075f..f30fb3d 100644 --- a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryResponse.java +++ b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryResponse.java @@ -1,4 +1,11 @@ package cc.sukazyo.cono.morny.data.ip186; +/** + * {@link IP186QueryHandler} 的请求结果数据的通用封装类. + * + * @since 0.4.2.10 + * @param url 请求数据的人类可读的来源链接,并非api链接 + * @param body API 传回的数据内容 + */ public record IP186QueryResponse(String url, String body) { } diff --git a/src/main/java/cc/sukazyo/cono/morny/util/StringUtils.java b/src/main/java/cc/sukazyo/cono/morny/util/StringUtils.java index 7ff40c2..ced5080 100644 --- a/src/main/java/cc/sukazyo/cono/morny/util/StringUtils.java +++ b/src/main/java/cc/sukazyo/cono/morny/util/StringUtils.java @@ -3,17 +3,9 @@ package cc.sukazyo.cono.morny.util; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import java.util.ArrayList; -import java.util.Arrays; public class StringUtils { - @Nonnull - public static String repeatChar (char c, int i) { - final char[] chars = new char[i]; - Arrays.fill(chars, c); - return new String(chars); - } - @Nonnull public static String[] formatCommand (@Nonnull String com) { @@ -66,4 +58,12 @@ public class StringUtils { return builder.toString(); } + @Nonnull + public static String escapeHtmlTelegram (String raw) { + raw = raw.replaceAll("&", "&"); + raw = raw.replaceAll("<", "<"); + raw = raw.replaceAll(">", ">"); + return raw; + } + }