diff --git a/.dockerignore b/.dockerignore index df3d0f1..e23a3f5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -10,6 +10,8 @@ #build /build/ /bin/ +.metals/ +.bloop/ .project lcoal.properties diff --git a/.gitignore b/.gitignore index df3d0f1..e23a3f5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ #build /build/ /bin/ +.metals/ +.bloop/ .project lcoal.properties diff --git a/build.gradle b/build.gradle index aff5df9..a15ac59 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'java' + id 'scala' id 'java-library' id 'application' id 'maven-publish' @@ -50,7 +50,9 @@ final long proj_code_time = proj_clean ? grgit.head().dateTime.toInstant().toEpo final JavaVersion proj_java = JavaVersion.VERSION_17 final Charset proj_file_encoding = StandardCharsets.UTF_8 - +final proj_scala_api = 3 +//final proj_scala_lib = proj_scala_api+'.4.0-RC1-bin-20230901-89e8dba-NIGHTLY' +final proj_scala_lib = proj_scala_api+'.3.1-RC7' String publish_local_url = null String publish_remote_url = null String publish_remote_username = null @@ -72,6 +74,7 @@ repositories { dependencies { + api "org.scala-lang:scala3-library_3:${proj_scala_lib}" compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}" implementation "cc.sukazyo:messiva:${lib_messiva_v}" @@ -86,8 +89,30 @@ dependencies { } -application { - mainClass = proj_application_main +sourceSets { + main { + scala { srcDirs = ['src/main/scala', 'src/main/old'] } + } +} + +scala { + + compileJava { + + sourceCompatibility '17' + targetCompatibility '17' + + options.encoding = proj_file_encoding.name() + + } + + compileScala { + + options.encoding = proj_file_encoding.name() + scalaCompileOptions.encoding = proj_file_encoding.name() + + } + } test { @@ -97,27 +122,8 @@ test { } } -java { - - sourceCompatibility proj_java - targetCompatibility proj_java - - withSourcesJar() - -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = proj_file_encoding.name() -} - -tasks.withType(Javadoc).configureEach { - options.encoding = proj_file_encoding.name() - options.docEncoding = proj_file_encoding.name() - options.charSet = proj_file_encoding.name() -} - -tasks.test { - useJUnitPlatform() +application { + mainClass = proj_application_main } buildConfig { diff --git a/gradle.properties b/gradle.properties index 2996049..908c69b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,8 +7,8 @@ MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s VERSION = 1.0.0-RC4 -USE_DELTA = false -VERSION_DELTA = +USE_DELTA = true +VERSION_DELTA = scalaport1 CODENAME = beiping diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java deleted file mode 100644 index 208ed1b..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java +++ /dev/null @@ -1,296 +0,0 @@ -package cc.sukazyo.cono.morny; - -import cc.sukazyo.cono.morny.util.CommonFormat; - -import javax.annotation.Nonnull; - -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.List; - -import static cc.sukazyo.cono.morny.Log.logger; - -/** - * 程序启动入口
- *
- * 会处理程序传入的参数和选项等数据,并执行对应的启动方式
- * - * @since 0.4.0.0 - */ -public class ServerMain { - - public static final long systemStartupTime = System.currentTimeMillis(); - - private static final String THREAD_MORNY_INIT = "morny-init"; - - /** - * 程序入口,也是参数处理器
- *
- * 以 {@code -} 开头的参数会被解析为选项
- *
- * 支持以下选项 - * - * 除去选项之外,第一个参数会被赋值为 bot 的 telegram bot api token, - * 第二个参数会被赋值为 bot 的 username 限定名。其余的参数会被认定为无法理解。
- * 自 {@code 0.4.2.3},token 和 username 的赋值已被选项组支持
- * 自 {@code 0.5.0.4},旧的直接通过参数为 bot token & username 赋值的方式已被删除 - * 使用参数所进行取值的 token 和 username 已被转移至 {@code --token} 和 {@code --username} 参数
- * - * @see MornyCoeur#init - * @since 0.4.0.0 - * @param args 参数组 - */ - public static void main (@Nonnull String[] args) { - - //# - //# 启动参数设置区块 - //# - final MornyConfig.Prototype config = new MornyConfig.Prototype(); - boolean versionEchoMode = false; - boolean welcomeEchoMode = false; - boolean showWelcome = true; - - config.eventOutdatedTimestamp = systemStartupTime; - - List unknownArgs = new ArrayList<>(); - - //# 从命令行参数设置启动参数 - for (int i = 0; i < args.length; i++) { - - if (args[i].startsWith("-")) { - - switch (args[i]) { - case "-d", "--dbg", "--debug" -> { - Log.debug(true); - continue; - } - case "--outdated-block", "-ob" -> { - config.eventIgnoreOutdated = true; - continue; - } - case "--no-hello", "-hf", "--quiet", "-q" -> { - showWelcome = false; - continue; - } - case "--only-hello", "-ho", "-o", "-hi" -> { - welcomeEchoMode = true; - continue; - } - case "--version", "-v" -> { - versionEchoMode = true; - continue; - } - case "--token", "-t" -> { - i++; - config.telegramBotKey = args[i]; - continue; - } - case "--username", "-u" -> { - i++; - config.telegramBotUsername = args[i]; - continue; - } - case "--master", "-mm" -> { - i++; - config.trustedMaster = Long.parseLong(args[i]); - continue; - } - case "--trusted-chat", "-trs" -> { - i++; - config.trustedChat = Long.parseLong(args[i]); - continue; - } - // noinspection SpellCheckingInspection - case "--trusted-reader-dinner", "-trsd" -> { - i++; - config.dinnerTrustedReaders.add(Long.parseLong(args[i])); - continue; - } - case "--dinner-chat", "-chd" -> { - i++; - config.dinnerChatId = Long.parseLong(args[i]); - continue; - } - case "--auto-cmd", "-cmd", "-c" -> { - config.commandLoginRefresh = true; - config.commandLogoutClear = true; - continue; - } - case "--auto-cmd-list", "-ca" -> { - config.commandLoginRefresh = true; - continue; - } - case "--auto-cmd-remove", "-cr" -> { - config.commandLogoutClear = true; - continue; - } - case "--api", "-a" -> { - i++; - config.telegramBotApiServer = args[i]; - continue; - } - case "--api-files", "files-api", "-af" -> { - i++; - config.telegramBotApiServer4File = args[i]; - continue; - } - case "--report-to" -> { - i++; - config.reportToChat = Long.parseLong(args[i]); - continue; - } - case "--medication-notify-chat", "-medc" -> { - i++; - config.medicationNotifyToChat = Long.parseLong(args[i]); - continue; - } - case "--medication-notify-timezone", "-medtz" -> { - i++; - config.medicationTimerUseTimezone = ZoneOffset.ofHours(Integer.parseInt(args[i])); - continue; - } - case "--medication-notify-times", "-medt" -> { - i++; - for (String u : args[i].split(",")) - config.medicationNotifyAt.add(Integer.parseInt(u)); - continue; - } - } - - } - - unknownArgs.add(args[i]); - - } - - //# 从环境变量设置启动参数 - String propToken = null; - String propTokenKey = null; - for (String iKey : MornyConfig.PROP_TOKEN_KEY) { - if (System.getenv(iKey) != null) { - propToken = System.getenv(iKey); - propTokenKey = iKey; - } - } - - - //# - //# 启动信息输出 - //# 启动相关参数的检查和处理 - //# - - if (showWelcome) logger.info(MornyAbout.MORNY_PREVIEW_IMAGE_ASCII); - if (welcomeEchoMode) return; - - unknownArgs.forEach(arg -> logger.warn("Can't understand arg to some meaning :\n " + arg)); - - if (Log.debug()) - logger.warn("Debug log output enabled.\n It may lower your performance, make sure that you are not in production environment."); - - logger.debug("Debug log output enabled."); - - if (versionEchoMode) { - - logger.info(String.format(""" - Morny Cono Version - - version : - Morny %s - %s%s - - md5hash : - %s - - gitstat : - %s - - co.time : - %d - %s [UTC]""", - MornySystem.CODENAME.toUpperCase(), - MornySystem.VERSION_BASE, - MornySystem.isUseDelta() ? "-δ"+MornySystem.VERSION_DELTA : "", - MornySystem.getJarMd5(), - MornySystem.isGitBuild() ? (String.format( - "on commit %s\n %s", - MornySystem.isCleanBuild() ? "- clean-build" : "<δ/non-clean-build>", - BuildConfig.COMMIT - )) : "", - BuildConfig.CODE_TIMESTAMP, - CommonFormat.formatDate(BuildConfig.CODE_TIMESTAMP, 0) - )); - return; - - } - - logger.info(String.format(""" - ServerMain.java Loaded >>> - - version %s - - Morny %s - - <%s> [%d]""", - MornySystem.VERSION_FULL, - MornySystem.CODENAME.toUpperCase(), - MornySystem.getJarMd5(), BuildConfig.CODE_TIMESTAMP - )); - - //# - //# Coeur 参数检查和正式启动主程序 - //# - - if (propToken != null) { - config.telegramBotKey = propToken; - logger.info("Parameter set by EnvVar $"+propTokenKey); - } - - Thread.currentThread().setName(THREAD_MORNY_INIT); - try { - MornyCoeur.init(new MornyConfig(config)); - } catch (MornyConfig.CheckFailure.NullTelegramBotKey ignore) { - logger.info("Parameter required has no value:\n --token."); - } catch (MornyConfig.CheckFailure e) { - logger.error("Unknown failure occurred while starting ServerMain!:"); - e.printStackTrace(System.out); - } - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.java deleted file mode 100644 index 54b850a..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.java +++ /dev/null @@ -1,58 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Chat; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.DeleteMessage; -import com.pengrad.telegrambot.request.GetChatMember; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static cc.sukazyo.cono.morny.Log.logger; - -public class DirectMsgClear implements ISimpleCommand { - - @Nonnull @Override public String getName () { return "r"; } - - @Nullable @Override public String[] getAliases () { return new String[0]; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - logger.debug("Executing command /r"); - if (event.message().replyToMessage() == null) return; - logger.trace("Message is a reply"); - if (event.message().replyToMessage().from().id() != MornyCoeur.getUserid()) return; - logger.trace("Message is from me"); - if (System.currentTimeMillis()/1000 - event.message().replyToMessage().date() > 48*60*60) return; - logger.trace("Message is not older than 48 hours"); - - final boolean isTrusted = MornyCoeur.trustedInstance().isTrusted(event.message().from().id()); - - if ( - isTrusted || ( - event.message().replyToMessage().replyToMessage() != null && - event.message().replyToMessage().replyToMessage().from().id().equals(event.message().from().id()) - ) - ) { - - MornyCoeur.extra().exec(new DeleteMessage( - event.message().chat().id(), event.message().replyToMessage().messageId() - )); - if (event.message().chat().type() == Chat.Type.Private || ( - MornyCoeur.extra().exec( - new GetChatMember(event.message().chat().id(), event.message().from().id()) - ).chatMember().canDeleteMessages() - )) { - MornyCoeur.extra().exec(new DeleteMessage( - event.message().chat().id(), event.message().messageId() - )); - } - - } else logger.trace("User is not trusted"); - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Encryptor.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Encryptor.java deleted file mode 100644 index 5ceb213..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/Encryptor.java +++ /dev/null @@ -1,208 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.daemon.MornyReport; -import cc.sukazyo.cono.morny.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.CommonConvert; -import cc.sukazyo.cono.morny.util.CommonEncrypt; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape; -import com.pengrad.telegrambot.model.PhotoSize; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.GetFile; -import com.pengrad.telegrambot.request.SendDocument; -import com.pengrad.telegrambot.request.SendMessage; -import com.pengrad.telegrambot.request.SendSticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Base64; - -import static cc.sukazyo.cono.morny.Log.logger; - -public class Encryptor implements ITelegramCommand { - - @Nonnull @Override public String getName () { return "encrypt"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return "[algorithm|(l)] [(uppercase)]"; } - @Nonnull @Override public String getDescription () { return "通过指定算法加密回复的内容 (目前只支持文本)"; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - // show a simple help page - // the first paragraph lists available encrypt algorithms, and its aliases. - // with the separator "---", - // the second paragraphs shows the mods available and its aliases. - if (!command.hasArgs() || (command.getArgs()[0].equals("l") && command.getArgs().length==1)) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), """ - base64, b64 - base64url, base64u, b64u - base64decode, base64d, b64d - base64url-decode, base64ud, b64ud - sha1 - sha256 - sha512 - md5 - --- - uppercase, upper, u (sha1/sha256/sha512/md5 only) - """ - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - return; - } - - // param1 is the encrypting algorithm, it MUST EXIST. - // so the mod will be set in param2. - // and for now only support UPPERCASE mod, so it exists in param2, or there should no any params. - boolean modUpperCase = false; - if (command.getArgs().length > 1) { - if (command.getArgs().length < 3 && ( - command.getArgs()[1].equalsIgnoreCase("uppercase") || - command.getArgs()[1].equalsIgnoreCase("u") || - command.getArgs()[1].equalsIgnoreCase("upper") - )) { - modUpperCase = true; - } else { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - return; - } - } - - // for now, only support reply to A TEXT MESSAGE or ONE UNIVERSAL FILE - // if the replied message contains a UNIVERSAL FILE, it will use the file and will not use the text with it - // do not support TELEGRAM INLINE IMAGE/VIDEO/AUDIO yet - // do not support MULTI_FILE yet - // if there's no text message in reply, it will report null as result. - boolean inputText; - byte[] data; - String dataName; - if (event.message().replyToMessage() != null && event.message().replyToMessage().document() != null) { - inputText = false; - try { - data = MornyCoeur.getAccount().getFileContent(MornyCoeur.extra().exec(new GetFile( - event.message().replyToMessage().document().fileId() - )).file()); - } catch (IOException e) { - logger.warn("NetworkRequest error: TelegramFileAPI:\n\t" + e.getMessage()); - MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI"); - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_NETWORK_ERR - ).replyToMessageId(event.message().messageId())); - return; - } - dataName = event.message().replyToMessage().document().fileName(); - } else if (event.message().replyToMessage() != null && event.message().replyToMessage().photo() != null) { - inputText = false; - try { - PhotoSize originPhoto = null; - long photoSize = 0; - for (PhotoSize size : event.message().replyToMessage().photo()) if (photoSize < (long)size.width() *size.height()) { - originPhoto = size; - photoSize = (long)size.width() *size.height(); - } // found max size (original) image in available sizes - if (originPhoto==null) throw new IOException("no photo object from api."); - data = MornyCoeur.getAccount().getFileContent(MornyCoeur.extra().exec(new GetFile( - originPhoto.fileId() - )).file()); - } catch (IOException e) { - logger.warn("NetworkRequest error: TelegramFileAPI:\n\t" + e.getMessage()); - MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI"); - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_NETWORK_ERR - ).replyToMessageId(event.message().messageId())); - return; - } - dataName = "photo"+CommonConvert.byteArrayToHex(CommonEncrypt.hashMd5(String.valueOf(System.currentTimeMillis()))).substring(32-12).toUpperCase()+".png"; - } else if (event.message().replyToMessage() != null && event.message().replyToMessage().text() != null) { - inputText = true; - data = event.message().replyToMessage().text().getBytes(CommonEncrypt.ENCRYPT_STANDARD_CHARSET); - dataName = null; - } else { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "null" - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - return; - } - - boolean echoString = true; - String resultString = null; - byte[] result = null; - String resultName = null; - switch (command.getArgs()[0]) { - case "base64", "b64", "base64url", "base64u", "b64u" -> { - final Base64.Encoder b64tool = command.getArgs()[0].contains("u") ? Base64.getUrlEncoder() : Base64.getEncoder(); - result = b64tool.encode(data); - if (!inputText) { - echoString = false; - resultName = dataName+".b64.txt"; - } else { - resultString = new String(result, CommonEncrypt.ENCRYPT_STANDARD_CHARSET); - } - } - case "base64decode", "base64d", "b64d", "base64url-decode", "base64ud", "b64ud" -> { - final Base64.Decoder b64tool = command.getArgs()[0].contains("u") ? Base64.getUrlDecoder() : Base64.getDecoder(); - try { result = b64tool.decode(data); } - catch (IllegalArgumentException e) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - return; - } - if (!inputText) { - echoString = false; - resultName = CommonEncrypt.base64FilenameLint(dataName); - } else { - resultString = new String(result, CommonEncrypt.ENCRYPT_STANDARD_CHARSET); - } - } - case "md5" -> resultString = CommonConvert.byteArrayToHex(CommonEncrypt.hashMd5(data)); - case "sha1" -> resultString = CommonConvert.byteArrayToHex(CommonEncrypt.hashSha1(data)); - case "sha256" -> resultString = CommonConvert.byteArrayToHex(CommonEncrypt.hashSha256(data)); - case "sha512" -> resultString = CommonConvert.byteArrayToHex(CommonEncrypt.hashSha512(data)); - default -> { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - return; - } - } - if (modUpperCase) { - // modUpperCase support only algorithm that showed as HEX value. - // it means md5, sha1, sha256, sha512 here. - // other will report wrong param. - switch (command.getArgs()[0]) { - case "md5", "sha1", "sha256", "sha512" -> { - assert resultString != null; - resultString = resultString.toUpperCase(); - } - default -> { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - return; - } - } - } - if (echoString) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "
" + MsgEscape.escapeHtml(resultString) + "
" - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } else { - MornyCoeur.extra().exec(new SendDocument( - event.message().chat().id(), - result - ).fileName(resultName).replyToMessageId(event.message().messageId())); - } - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java deleted file mode 100644 index dbcfc81..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java +++ /dev/null @@ -1,99 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.MornyTrusted; -import cc.sukazyo.cono.morny.bot.event.OnEventHackHandle; -import cc.sukazyo.cono.morny.data.TelegramStickers; - -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendSticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * {@link OnEventHackHandle} 的命令行前端 - * @since 0.4.2.0 - */ -public class EventHack implements ITelegramCommand { - - @Nonnull @Override public String getName () { return "event_hack"; } - @Nullable @Override public String[] getAliases () { return null; } - @Nonnull @Override public String getParamRule () { return "[(user|group|any)]"; } - @Nonnull @Override public String getDescription () { return "输出 bot 下一个获取到的事件序列化数据"; } - - /** - * {@link OnEventHackHandle} 的命令行前端
- *
- * 实现了通过命令行进行 EventHack 功能。
- * 支持三种模式,默认为 {@link OnEventHackHandle.HackType#USER USER}, - * {@link OnEventHackHandle.HackType#ANY ANY} 时,将会通过 {@link MornyTrusted#isTrusted(long)} 检查触发用户的权限 - * - * @param event 命令基础参数,触发的事件对象本身 - * @param command 命令基础参数,解析出的命令对象 - * @since 0.4.2.0 - */ - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - enum Status { - OK, - FORBIDDEN_FOR_ANY - } - Status status; - - String x_mode = ""; - if (command.hasArgs()) { - x_mode = command.getArgs()[0]; - } - switch (x_mode) { - case "any" -> { - if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) { - OnEventHackHandle.registerHack( - event.message().messageId(), - event.message().from().id(), - event.message().chat().id(), - OnEventHackHandle.HackType.ANY - ); - status = Status.OK; - } else { - status = Status.FORBIDDEN_FOR_ANY; - } - } - case "group" -> { - OnEventHackHandle.registerHack( - event.message().messageId(), - event.message().from().id(), - event.message().chat().id(), - OnEventHackHandle.HackType.GROUP - ); - status = Status.OK; - } - default -> { - OnEventHackHandle.registerHack( - event.message().messageId(), - event.message().from().id(), - event.message().chat().id(), - OnEventHackHandle.HackType.USER - ); - status = Status.OK; - } - } - - switch (status) { - case OK -> MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_WAITING - ).replyToMessageId(event.message().messageId()) - ); - case FORBIDDEN_FOR_ANY -> MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_403 - ).replyToMessageId(event.message().messageId()) - ); - } - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java deleted file mode 100644 index 553b14f..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java +++ /dev/null @@ -1,85 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.User; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.GetChatMember; -import com.pengrad.telegrambot.request.SendMessage; -import com.pengrad.telegrambot.response.GetChatMemberResponse; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class GetUsernameAndId implements ITelegramCommand { - - @Nonnull @Override public String getName () { return "user"; } - @Nullable @Override public String[] getAliases () { return null; } - @Nonnull @Override public String getParamRule () { return "[userid]"; } - @Nonnull @Override public String getDescription () { return "获取指定或回复的用户相关信息"; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - final String[] args = command.getArgs(); - - // 不支持大于一个参数 - if (args.length > 1) { MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Unavailable] Too much arguments." - ).replyToMessageId(event.message().messageId())); return; } - - // 发送者自己的 id - long userId = event.message().from().id(); - - // 如果有回复某个人,则使用被回复人的 id - if (event.message().replyToMessage()!= null) { - userId = event.message().replyToMessage().from().id(); - } - // 如果有指定 id,则使用指定的 id - if (args.length > 0) { - try { - userId = Long.parseLong(args[0]); - } catch (NumberFormatException e) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Unavailable] " + e.getMessage() - ).replyToMessageId(event.message().messageId())); - return; - } - } - - // 重新获取用户对象 - final GetChatMemberResponse response = MornyCoeur.getAccount().execute( - new GetChatMember(event.message().chat().id(), userId) - ); - - if (response.chatMember() == null) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Unavailable] user not found." - ).replyToMessageId(event.message().messageId())); - return; - } - - // 获取并发送用户信息 - final User user = response.chatMember().user(); - - if (user.id() == 136817688) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "$__channel_identify" - )); - return; - } - - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - TelegramUserInformation.informationOutputHTML(user) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java deleted file mode 100644 index 4d5b4f3..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java +++ /dev/null @@ -1,85 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.data.ip186.IP186QueryResponse; -import cc.sukazyo.cono.morny.data.ip186.IP186QueryHandler; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml; - - -/** - * {@value IP186QueryHandler#SITE_URL} 查询的 telegram 命令前端 - * @since 0.4.2.10 - */ -public class Ip186Query { - - public static final String CMD_IP = "ip"; - public static final String CMD_WHOIS = "whois"; - - public static class Ip implements ITelegramCommand { - @Nonnull @Override public String getName () { return CMD_IP; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return "[ip]"; } - @Nonnull @Override public String getDescription () { return "通过 https://ip.186526.xyz 查询 ip 资料"; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { exec(event, command); } - } - - public static class Whois implements ITelegramCommand { - @Nonnull @Override public String getName () { return CMD_WHOIS; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return "[domain]"; } - @Nonnull @Override public String getDescription () { return "通过 https://ip.186526.xyz 查询域名资料"; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { exec(event, command); } - } - - private static void exec (@Nonnull Update event, @Nonnull InputCommand command) { - - String arg = null; - if (!command.hasArgs()) { - if (event.message().replyToMessage() != null) { - arg = event.message().replyToMessage().text(); - } - } else if (command.getArgs().length > 1) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Unavailable] Too much arguments." - ).replyToMessageId(event.message().messageId())); - return; - } else { - arg = command.getArgs()[0]; - } - if (arg == null) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Unavailable] No ip defined." - ).replyToMessageId(event.message().messageId())); - return; - } - - try { - IP186QueryResponse response = switch (command.getCommand()) { - case CMD_IP -> IP186QueryHandler.queryIp(arg); - case CMD_WHOIS -> IP186QueryHandler.queryWhoisPretty(arg); - default -> throw new IllegalArgumentException("Unknown 186-IP query method " + command.getCommand()); - }; - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - escapeHtml(response.url()) + "\n" + escapeHtml(response.body()) + "" - ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); - } catch (Exception e) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Exception] in query:\n" + escapeHtml(e.getMessage()) + "" - ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); - } - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java deleted file mode 100644 index 245bae8..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java +++ /dev/null @@ -1,44 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendPhoto; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * The implementation of Telegram special command `/start`. - * - * @see MornyInformation related class where some data comes from. - * - * @since 1.0.0-RC4 - */ -public class MornyInfoOnHello implements ISimpleCommand { - - @Nonnull @Override public String getName() { return "start"; } - @Nullable @Override public String[] getAliases() { return new String[0]; } - // @Override public String getParamRule() { return ""; } - // @Override public String getDescription() { return "" } - - @Override - public void execute(@Nonnull InputCommand command, @Nonnull Update event) { - MornyCoeur.extra().exec(new SendPhoto( - event.message().chat().id(), - MornyInformation.getAboutPic() - ).caption(""" - 欢迎使用 Morny Cono来自安妮的侍从小鼠。 - Morny 具有各种各样的功能。 - - ———————————————— - %s - ———————————————— - - (你可以随时通过 /info 重新获得这些信息)""".formatted(MornyInformation.getMornyAboutLinksHTML()) - ).parseMode(ParseMode.HTML)); - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java deleted file mode 100644 index 6a204e0..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java +++ /dev/null @@ -1,301 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.BuildConfig; -import cc.sukazyo.cono.morny.MornyAbout; -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.MornySystem; -import cc.sukazyo.cono.morny.data.TelegramImages; -import cc.sukazyo.cono.morny.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.tgapi.ExtraAction; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; -import com.pengrad.telegrambot.request.SendPhoto; -import com.pengrad.telegrambot.request.SendSticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Objects; - -import static cc.sukazyo.cono.morny.util.CommonFormat.formatDate; -import static cc.sukazyo.cono.morny.util.CommonFormat.formatDuration; -import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml; - -public class MornyInformation implements ITelegramCommand { - - private static final String SUB_STICKER = "stickers"; - private static final String SUB_RUNTIME = "runtime"; - private static final String SUB_VERSION = "version"; - private static final String SUB_VERSION_2 = "v"; - - @Nonnull @Override public String getName () { return "info"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return "[(version|runtime|stickers[.IDs])]"; } - @Nonnull @Override public String getDescription () { return "输出当前 Morny 的各种信息"; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - if (!command.hasArgs()) { - echoInfo(event.message().chat().id(), event.message().messageId()); - return; - } - - final String action = command.getArgs()[0]; - - if (action.startsWith(SUB_STICKER)) { - echoStickers(command, event); - } else if (action.equals(SUB_RUNTIME)) { - echoRuntime(event); - } else if (action.equals(SUB_VERSION) || action.equals(SUB_VERSION_2)) { - echoVersion(event); - } else { - echo404(event); - } - - } - - /** - * Subcommand /info without params. - * - * @since 1.0.0-RC4 - */ - public void echoInfo (long chatId, int replayToMessage) { - MornyCoeur.extra().exec(new SendPhoto( - chatId, - getAboutPic() - ).caption(""" - Morny Cono - 来自安妮的侍从小鼠。 - ———————————————— - %s""".formatted(getMornyAboutLinksHTML()) - ).parseMode(ParseMode.HTML).replyToMessageId(replayToMessage)); - } - - /** - * subcommand /info stickers - * - * @see #SUB_STICKER - */ - public void echoStickers (@Nonnull InputCommand command, @Nonnull Update event) { - final long echoTo = event.message().chat().id(); - final int replyToMessage = event.message().messageId(); - String id = null; - if (command.getArgs()[0].equals(SUB_STICKER)) { - if (command.getArgs().length == 1) { - id = ""; - } else if (command.getArgs().length == 2) { - id = command.getArgs()[1]; - } - } else if (command.getArgs().length == 1) { - if (command.getArgs()[0].startsWith(SUB_STICKER+".") || command.getArgs()[0].startsWith(SUB_STICKER+"#")) { - id = command.getArgs()[0].substring(SUB_STICKER.length()+1); - } - } - if (id == null) { echo404(event); return; } - echoStickers(id, echoTo, replyToMessage); - } - - /** - * 向 telegram 输出一个或全部 sticker. - * - * @param id - * sticker 在 {@link TelegramStickers} 中的字段名。 - * 使用 {@link ""}(空字符串)(不是{@link null}) 表示输出全部 sticker - * @param chatId 目标 chat id - * @param messageId 要回复的消息 id,依据 {@link TelegramStickers#echoStickerByID(String, ExtraAction, long, int) 上游} - * 逻辑,使用 {@link -1} 表示不回复消息。 - * - * @see TelegramStickers#echoStickerByID(String, ExtraAction, long, int) - * @see TelegramStickers#echoAllStickers(ExtraAction, long, int) - */ - public static void echoStickers (@Nonnull String id, long chatId, int messageId) { - if (id.isEmpty()) TelegramStickers.echoAllStickers(MornyCoeur.extra(), chatId, messageId); - else TelegramStickers.echoStickerByID(id, MornyCoeur.extra(), chatId, messageId); - } - - /** - * Subcommand /info runtime. - * - * @see #SUB_RUNTIME - * - * @since 1.0.0-alpha4 - */ - public static void echoRuntime (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - String.format(""" - system: - - %s - - %s (%s) %s - java runtime: - - %s - - %s - vm memory: - - %d / %d MB - - %d cores - coeur version: - - %s - - %s - - %s [UTC] - - [%d] - continuous: - - %s - - [%d] - - %s [UTC] - - [%d]""", - // system - escapeHtml(getRuntimeHostName()==null ? "" : getRuntimeHostName()), - escapeHtml(System.getProperty("os.name")), - escapeHtml(System.getProperty("os.arch")), - escapeHtml(System.getProperty("os.version")), - // java - escapeHtml(System.getProperty("java.vm.vendor")+"."+System.getProperty("java.vm.name")), - escapeHtml(System.getProperty("java.vm.version")), - // memory - Runtime.getRuntime().totalMemory() / 1024 / 1024, - Runtime.getRuntime().maxMemory() / 1024 / 1024, - Runtime.getRuntime().availableProcessors(), - // version - getVersionAllFullTagHtml(), - escapeHtml(MornySystem.getJarMd5()), - escapeHtml(formatDate(BuildConfig.CODE_TIMESTAMP, 0)), - BuildConfig.CODE_TIMESTAMP, - // continuous - escapeHtml(formatDuration(System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp)), - System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp, - escapeHtml(formatDate(MornyCoeur.coeurStartTimestamp, 0)), - MornyCoeur.coeurStartTimestamp - ) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } - - /** - * Subcommand /info version or /info v. - * - * @see #SUB_VERSION - * @see #SUB_VERSION_2 - * - * @since 1.0.0-alpha4 - */ - public static void echoVersion (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - String.format( - """ - version: - - Morny %s - - %s%s%s - core md5_hash: - - %s - coding timestamp: - - %d - - %s [UTC]""", - escapeHtml(MornySystem.CODENAME.toUpperCase()), - escapeHtml(MornySystem.VERSION_BASE), - MornySystem.isUseDelta() ? String.format("-δ%s", escapeHtml(Objects.requireNonNull(MornySystem.VERSION_DELTA))) : "", - MornySystem.isGitBuild() ? "\n- git "+getVersionGitTagHtml() : "", - escapeHtml(MornySystem.getJarMd5()), - BuildConfig.CODE_TIMESTAMP, - escapeHtml(formatDate(BuildConfig.CODE_TIMESTAMP, 0)) - ) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } - - /** - * 取得 {@link MornySystem} 的 git commit 相关版本信息的 HTML 格式化标签. - * - * @return 格式类似于 {@code 28e8c82a.δ} 的以 HTML 方式格式化的版本号组件。 - * 其中 {@code .δ} 对应着 {@link MornySystem#isCleanBuild}; - * commit tag 字段如果支援 {@link MornySystem#currentCodePath} 则会以链接形式解析,否则则为 code 格式 - * 为了对 telegram api html 格式兼容所以不支援嵌套链接与code标签。 - * 如果 {@link MornySystem#isGitBuild} 为 {@link false},则方法会返回 {@link ""} - * - * @since 1.0.0-beta2 - */ - @Nonnull - public static String getVersionGitTagHtml () { - if (!MornySystem.isGitBuild()) return ""; - final StringBuilder g = new StringBuilder(); - final String cp = MornySystem.currentCodePath(); - if (cp == null) g.append(String.format("%s", BuildConfig.COMMIT.substring(0, 8))); - else g.append(String.format("%s", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8))); - if (!MornySystem.isCleanBuild()) g.append(".δ"); - return g.toString(); - } - - /** - * 取得完整 Morny 版本的 HTML 格式化标签. - *

- * 相比于 {@link MornySystem#VERSION_FULL},这个版本号还包含了 {@link MornySystem#CODENAME 版本 codename}。 - * 各个部分也被以 HTML 的格式进行了格式化以可以更好的在富文本中插入使用. - * @return 基于 HTML 标签进行了格式化了的类似于 - * {@link MornySystem#VERSION_BASE 5.38.2-alpha1}{@link MornySystem#isUseDelta() -δ}{@link MornySystem#VERSION_DELTA tt}{@link MornySystem#isGitBuild() +git.}{@link #getVersionGitTagHtml() 28e8c82a.δ}*{@link MornySystem#CODENAME TOKYO} - * 的版本号。 - * @since 1.0.0-beta2 - */ - @Nonnull - public static String getVersionAllFullTagHtml () { - final StringBuilder v = new StringBuilder(); - v.append("").append(MornySystem.VERSION_BASE).append(""); - if (MornySystem.isUseDelta()) v.append("-δ").append(MornySystem.VERSION_DELTA).append(""); - if (MornySystem.isGitBuild()) v.append("+git.").append(getVersionGitTagHtml()); - v.append("*").append(MornySystem.CODENAME.toUpperCase()).append(""); - return v.toString(); - } - - /** - * 获取 coeur 运行时的宿主机的主机名 - * @return coeur 宿主机主机名,或者 {@link null} 表示获取失败 - */ - @Nullable - public static String getRuntimeHostName () { - try { - return InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException e) { - return null; - } - } - - /** - * Get the about-pic (intro picture or featured image) of Morny. - * - * @return the Telegram file binary data of the about-pic. - * @throws IllegalStateException {@link TelegramImages.AssetsFileImage#get() get() image data} may - * throws {@link IllegalStateException} while read error. - */ - @Nonnull - public static byte[] getAboutPic () { - return TelegramImages.IMG_ABOUT.get(); - } - - private static void echo404 (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - } - - /** - * The formatted about links of Morny Cono and Morny Coeur. - *

- * With the Telegram HTML formatting, used in /info and /start. - * Provided the end user the links that can find resources about Morny. - */ - @Nonnull - public static String getMornyAboutLinksHTML () { - return """ - source code | backup - 反馈 / issue tracker - 使用说明书 / user guide & docs""".formatted( - MornyAbout.MORNY_SOURCECODE_LINK, MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK, - MornyAbout.MORNY_ISSUE_TRACKER_LINK, - MornyAbout.MORNY_USER_GUIDE_LINK - ); - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java deleted file mode 100644 index 20adb23..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java +++ /dev/null @@ -1,80 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.data.NbnhhshQuery; -import com.pengrad.telegrambot.request.SendSticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static cc.sukazyo.cono.morny.util.CommonConvert.stringsConnecting; -import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml; - -public class Nbnhhsh implements ITelegramCommand { - - @Nonnull @Override public String getName () { return "nbnhhsh"; } - @Nullable @Override public String[] getAliases () { return null; } - @Nonnull @Override public String getParamRule () { return "[text]"; } - @Nonnull @Override public String getDescription () { return "检索文本内 nbnhhsh 词条"; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - class TagNoContent extends Exception {} - try { - - String queryTarget; - if (event.message().replyToMessage() != null && event.message().replyToMessage().text() != null) - queryTarget = event.message().replyToMessage().text(); - else if (command.hasArgs()) - queryTarget = stringsConnecting(command.getArgs(), " ", 0, command.getArgs().length-1); - else { - throw new TagNoContent(); - } - - NbnhhshQuery.GuessResult response = NbnhhshQuery.sendGuess(queryTarget); - - StringBuilder message = new StringBuilder("## Result of nbnhhsh query :"); - - for (NbnhhshQuery.Word word : response.words) { - if (word.trans != null && word.trans.length == 0) word.trans = null; - if (word.inputting != null && word.inputting.length == 0) word.inputting = null; - if (word.trans == null && word.inputting == null) continue; - message.append("\n\n[[ ").append(escapeHtml(word.name)).append(" ]]"); - if (word.trans != null) for (String trans : word.trans) { - message.append("\n* ").append(escapeHtml(trans)).append(""); - } - if (word.inputting != null) { - if (word.trans != null) message.append("\n"); - message.append(" maybe:"); - for (String trans : word.inputting) { - message.append("\n` ").append(escapeHtml(trans)).append(""); - } - } - } - - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - message.toString() - ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); - - } catch (TagNoContent tag) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId())); - } catch (Exception e) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "[Exception] in query:\n" + escapeHtml(e.getMessage()) + "" - ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); - } - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Testing.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Testing.java deleted file mode 100644 index 8039ce7..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/Testing.java +++ /dev/null @@ -1,36 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class Testing implements ISimpleCommand { - - @Nonnull - @Override - public String getName () { - return "test"; - } - - @Nullable - @Override - public String[] getAliases () { - return null; - } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - "Just a TEST command." - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/喵呜.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/喵呜.java deleted file mode 100644 index 692ce2a..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/喵呜.java +++ /dev/null @@ -1,82 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Message; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; -import com.pengrad.telegrambot.request.SendSticker; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * WARNING that {@link cc.sukazyo.cono.morny.bot.event.OnTelegramCommand} - * 并不能够处理非 english word 字符之外的命令. - *

- * 出于这个限制,以下几个命令目前都无法使用 - * @see 抱抱 - * @see 揉揉 - * @see 蹭蹭 - * @see 贴贴 - */ -@SuppressWarnings("NonAsciiCharacters") -public class 喵呜 { - - public static class 抱抱 implements ISimpleCommand { - @Nonnull @Override public String getName () { return "抱抱"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - replyingSet(event, "抱抱", "抱抱"); - } - } - - public static class 揉揉 implements ISimpleCommand { - @Nonnull @Override public String getName () { return "揉揉"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - replyingSet(event, "蹭蹭", "摸摸"); - } - } - - public static class 蹭蹭 implements ISimpleCommand { - @Nonnull @Override public String getName () { return "蹭蹭"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - replyingSet(event, "揉揉", "蹭蹭"); - } - } - - public static class 贴贴 implements ISimpleCommand { - @Nonnull @Override public String getName () { return "贴贴"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - replyingSet(event, "贴贴", "贴贴"); - } - } - - private static void replyingSet (@Nonnull Update event, @Nonnull String whileRec, @Nonnull String whileNew) { - final boolean isNew = event.message().replyToMessage() == null; - final Message target = isNew ? event.message() : event.message().replyToMessage(); - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - isNew ? whileNew : whileRec - ).replyToMessageId(target.messageId()).parseMode(ParseMode.HTML)); - } - - public static class Progynova implements ITelegramCommand { - @Nonnull @Override public String getName () { return "install"; } - @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return ""; } - @Nonnull @Override public String getDescription () { return "抽取一个神秘盒子"; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_PROGYNOVA - ).replyToMessageId(event.message().messageId())); - } - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/私わね.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/私わね.java deleted file mode 100644 index 6006c0d..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/私わね.java +++ /dev/null @@ -1,40 +0,0 @@ -package cc.sukazyo.cono.morny.bot.command; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.util.tgapi.InputCommand; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static cc.sukazyo.cono.morny.util.CommonRandom.probabilityTrue; - -@SuppressWarnings("NonAsciiCharacters") -public class 私わね implements ISimpleCommand { - - @Nonnull - @Override public String getName () { return "me"; } - - @Nullable - @Override public String[] getAliases () { return null; } - - @Override - public void execute (@Nonnull InputCommand command, @Nonnull Update event) { - if (probabilityTrue(521)) { - // 可以接入未来的心情系统(如果有的话) -// final String text = switch (ThreadLocalRandom.current().nextInt(11)) { -// case 0,7,8,9,10 -> "才不是"; -// case 1,2,3,6 -> "才不是!"; -// case 4,5 -> "才不是.."; -// default -> throw new IllegalStateException("Unexpected random value in 私わね command."); -// }; - final String text = "/打假"; - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - text - ).replyToMessageId(event.message().messageId())); - } - } - -} 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 deleted file mode 100644 index 89ed0fc..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java +++ /dev/null @@ -1,181 +0,0 @@ -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.data.TelegramStickers; -import cc.sukazyo.cono.morny.util.CommonFormat; -import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape; -import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString; -import com.pengrad.telegrambot.model.Chat; -import com.pengrad.telegrambot.model.Message; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.ForwardMessage; -import com.pengrad.telegrambot.request.GetChat; -import com.pengrad.telegrambot.request.SendMessage; -import com.pengrad.telegrambot.request.SendSticker; -import com.pengrad.telegrambot.response.SendResponse; - -import javax.annotation.Nonnull; - -/** - * 通过 bot 呼叫主人的事件监听管理类 - * @since 0.4.2.1 - */ -public class OnCallMe extends EventListener { - - /** - * 主人的 telegram user id,同时被用于 chat id
- * 跟随 {@link cc.sukazyo.cono.morny.MornyConfig#trustedMaster} 的值 - * @since 0.4.2.1 - */ - private static final long ME = MornyCoeur.config().trustedMaster; - - /** - * 监听私聊 bot 的消息进行呼叫关键字匹配。 - * 如果成功,将会执行呼叫函数,并向呼叫者回显{@link TelegramStickers#ID_WAITING "已呼叫"贴纸} - * - * @param update 事件基础参数,消息事件所属的 tgapi:update 对象 - * @return 事件基础返回值,是否已完成处理事件:
- * 如果匹配到呼叫,则返回{@code true},反之返回{@code false} - */ - @Override - public boolean onMessage (@Nonnull Update update) { - if (update.message().text() == null) - return false; - if (update.message().chat().type() != Chat.Type.Private) - return false; - switch (update.message().text().toLowerCase()) { - case "steam", "sbeam", "sdeam" -> - requestSteamJoin(update); - case "hana paresu", "花宫", "内群" -> - requestHanaParesuJoin(update); - case "dinner", "lunch", "breakfast", "meal", "eating", "安妮今天吃什么" -> - requestLastDinner(update); - default -> { - if (update.message().text().startsWith("cc::")) { - requestCustomCall(update); - break; - } - return false; - } - } - MornyCoeur.extra().exec(new SendSticker( - update.message().chat().id(), - TelegramStickers.ID_SENT - ).replyToMessageId(update.message().messageId()) - ); - return true; - } - - /** - * 执行 steam library 呼叫
- * 将会向 {@link #ME} 发送 - * - * @param event 执行呼叫的tg事件 - */ - private static void requestSteamJoin (Update event) { - MornyCoeur.extra().exec(new SendMessage( - ME, String.format( - """ - request STEAM LIBRARY - from %s""", - TGToString.as(event.message().from()).fullnameRefHtml() - ) - ).parseMode(ParseMode.HTML)); - } - - /** - * 执行花宫呼叫
- * 将会向 {@link #ME} 发送 - * - * @param event 执行呼叫的tg事件 - */ - private static void requestHanaParesuJoin (Update event) { - MornyCoeur.extra().exec(new SendMessage( - ME, String.format( - """ - request Hana Paresu - from %s""", - TGToString.as(event.message().from()).fullnameRefHtml() - ) - ).parseMode(ParseMode.HTML)); - } - - /** - * 对访问最近一次的饭局的请求进行回复
- * - * @param event 执行呼叫的tg事件 - */ - private static void requestLastDinner (Update event) { - boolean isAllowed = false; - Message lastDinnerData = null; - if (MornyCoeur.trustedInstance().isTrustedForDinnerRead(event.message().from().id())) { - lastDinnerData = MornyCoeur.extra().exec(new GetChat(MornyCoeur.config().dinnerChatId)).chat().pinnedMessage(); - SendResponse sendResp = MornyCoeur.extra().exec(new ForwardMessage( - event.message().from().id(), - lastDinnerData.forwardFromChat().id(), - lastDinnerData.forwardFromMessageId() - )); - MornyCoeur.extra().exec(new SendMessage( - event.message().from().id(), - String.format("on %s [UTC+8]\n- %s before", - MsgEscape.escapeHtml( - CommonFormat.formatDate((long)lastDinnerData.forwardDate()*1000, 8) - ), MsgEscape.escapeHtml( - CommonFormat.formatDuration(System.currentTimeMillis()-(long)lastDinnerData.forwardDate()*1000) - ) - ) - ).replyToMessageId(sendResp.message().messageId()).parseMode(ParseMode.HTML)); - isAllowed = true; - } else { - MornyCoeur.extra().exec(new SendSticker( - event.message().from().id(), - TelegramStickers.ID_403 - ).replyToMessageId(event.message().messageId())); - } - MornyCoeur.extra().exec(new SendMessage( - ME, String.format( - """ - request Last Annie Dinner - from %s - %s""", - TGToString.as(event.message().from()).fullnameRefHtml(), - isAllowed ? "Allowed and returned " + String.format( - "https://t.me/c/%d/%d", Math.abs(lastDinnerData.forwardFromChat().id()+1000000000000L), lastDinnerData.forwardFromMessageId() - ) : "Forbidden by perm check." - ) - ).parseMode(ParseMode.HTML)); - } - - /** - * 执行自定义呼叫
- * 将会向 {@link #ME} 发送一个 request 数据消息和转发的原始请求消息
- *
- * known issue

    - *
  • 无法处理与转发带有媒体的消息
  • - *
- *
- * 现在你可以通过这个 bot 来呼叫主人(sukazyo)任何事情了 —— - * 但是直接私聊sukazyo不好吗 - * - * @param event 执行呼叫的tg事件 - * @since 0.4.2.2 - */ - private static void requestCustomCall (Update event) { - MornyCoeur.extra().exec(new SendMessage( - ME, String.format( - """ - request [???] - from %s""", - TGToString.as(event.message().from()).fullnameRefHtml() - ) - ).parseMode(ParseMode.HTML)); - MornyCoeur.extra().exec(new ForwardMessage( - ME, - event.message().chat().id(), - event.message().messageId() - )); - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java deleted file mode 100644 index ed06f0b..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java +++ /dev/null @@ -1,47 +0,0 @@ -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.bot.api.InlineQueryUnit; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResult; -import com.pengrad.telegrambot.request.AnswerInlineQuery; - -import javax.annotation.Nonnull; -import java.util.List; - -/** - * telegram inlineQuery 功能的处理类, - * 也是一个 InlineQueryManager(还没做) - * - * @since 0.4.1.3 - */ -public class OnInlineQueries extends EventListener { - - /** - * @since 0.4.1.3 - */ - @Override - public boolean onInlineQuery (@Nonnull Update update) { - - List> results = MornyCoeur.queryManager().query(update); - - int cacheTime = Integer.MAX_VALUE; - boolean isPersonal = InlineQueryUnit.DEFAULT_INLINE_PERSONAL_RESP; - InlineQueryResult[] inlineQueryResults = new InlineQueryResult[results.size()]; - for (int i = 0; i < results.size(); i++) { - inlineQueryResults[i] = results.get(i).result; - if (cacheTime > results.get(i).cacheTime()) cacheTime = results.get(i).cacheTime(); - if (results.get(i).isPersonal()) isPersonal = true; - } - - if (results.size() == 0) return false; - - MornyCoeur.extra().exec(new AnswerInlineQuery( - update.inlineQuery().id(), inlineQueryResults - ).cacheTime(cacheTime).isPersonal(isPersonal)); - return true; - - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserRandoms.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserRandoms.java deleted file mode 100644 index b1deec4..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserRandoms.java +++ /dev/null @@ -1,42 +0,0 @@ -package cc.sukazyo.cono.morny.bot.event; - -import cc.sukazyo.cono.morny.MornyCoeur; -import cc.sukazyo.cono.morny.bot.api.EventListener; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; - -import javax.annotation.Nonnull; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static cc.sukazyo.cono.morny.util.CommonRandom.iif; - -public class OnUserRandoms extends EventListener { - - private static final Pattern USER_OR_QUERY = Pattern.compile("(.+)(?:还是|or)(.+)"); - private static final Pattern USER_IF_QUERY = Pattern.compile("(.+)[吗?|?]+$"); - - @Override - public boolean onMessage (@Nonnull Update update) { - - if (update.message().text() == null) return false; - if (!update.message().text().startsWith("/")) return false; - - final String query = update.message().text().substring(1); - String result = null; - Matcher matcher; - if ((matcher = USER_OR_QUERY.matcher(query)).find()) { - result = iif() ? matcher.group(1) : matcher.group(2); - } else if ((matcher = USER_IF_QUERY.matcher(query)).matches()) { - result = (iif()?"":"不") + matcher.group(1); - } - - if (result == null) return false; - MornyCoeur.extra().exec(new SendMessage( - update.message().chat().id(), result - ).replyToMessageId(update.message().messageId())); - 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 deleted file mode 100644 index cf1910b..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.java +++ /dev/null @@ -1,84 +0,0 @@ -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.UniversalCommand; -import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString; - -import com.pengrad.telegrambot.model.Message; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.ParseMode; -import com.pengrad.telegrambot.request.SendMessage; - -import javax.annotation.Nonnull; - -import static cc.sukazyo.cono.morny.util.CommonConvert.stringsConnecting; -import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml; - -public class OnUserSlashAction extends EventListener { - - @Override - public boolean onMessage (@Nonnull Update event) { - final String text = event.message().text(); - if (text == null) return false; - - if (text.startsWith("/")) - { - - /// Due to @Lapis_Apple, we stopped slash action function at .DP7 groups. - /// It may be enabled after some updates when the function will not be conflicted to other bots. - // if (event.message().chat().id() == ) return false; -//{ if (event.message().chat().title() != null && event.message().chat().title().contains(".DP7")) { -// logger.info(String.format(""" -// Chat slash action ignored due to the following keyword. -// - %s -// - ".DP7\"""", -// TGToString.as(event.message().chat()).toStringFullNameId() -// )); -// return false; -// } - - final String[] action = UniversalCommand.format(text); - action[0] = action[0].substring(1); - - if (action[0].matches("^\\w+(@\\w+)?$")) { - return false; // 忽略掉 Telegram 命令格式的输入 - } else if (action[0].contains("/")) { - return false; // 忽略掉疑似目录格式的输入 - } - - final boolean isHardParse = "".equals(action[0]); - /* 忽略空数据 */ if (isHardParse && action.length < 2) { return false; } - final String verb = isHardParse ? action[1] : action[0]; - final boolean hasObject = action.length != (isHardParse?2:1); - final String object = - hasObject ? - stringsConnecting(action, " ", isHardParse?2:1, action.length-1) : - ""; - final Message origin = event.message(); - final Message target = (event.message().replyToMessage() == null ? ( - origin - ): ( - event.message().replyToMessage() - )); - - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - String.format( - "%s %s%s %s %s!", - TGToString.as(origin).getSenderFirstNameRefHtml(), - escapeHtml(verb), escapeHtml((hasObject?"":"了")), - origin==target ? - "自己" : - TGToString.as(target).getSenderFirstNameRefHtml(), - escapeHtml(hasObject ? object+" " : "") - ) - ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); - - return true; - - } - return false; - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java deleted file mode 100644 index c79ab37..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java +++ /dev/null @@ -1,15 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import javax.annotation.Nullable; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; -import com.pengrad.telegrambot.model.Update; - -import java.util.List; - -public interface ITelegramQuery { - - @Nullable - List> query (Update event); - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java deleted file mode 100644 index b0dc135..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java +++ /dev/null @@ -1,31 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; -import com.pengrad.telegrambot.model.Update; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; - -public class MornyQueries { - - private final List queryInstances = new ArrayList<>(); - - public MornyQueries () { - queryInstances.add(new RawText()); - queryInstances.add(new MyInformation()); - queryInstances.add(new ShareToolTwitter()); - queryInstances.add(new ShareToolBilibili()); - } - - @Nonnull - public List> query (@Nonnull Update event) { - final List> results = new ArrayList<>(); - for (ITelegramQuery instance : queryInstances) { - final List> r = instance.query(event); - if (r!=null) results.addAll(r); - } - return results; - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java deleted file mode 100644 index 7921174..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java +++ /dev/null @@ -1,35 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import javax.annotation.Nullable; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; -import com.pengrad.telegrambot.model.request.InputTextMessageContent; -import com.pengrad.telegrambot.model.request.ParseMode; - -import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation; - -import java.util.Collections; -import java.util.List; - -import static cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds; - -public class MyInformation implements ITelegramQuery { - - public static final String ID_PREFIX = "[morny/info/me]"; - public static final String TITLE = "My Account Information"; - - @Override - @Nullable - public List> query(Update event) { - if (!(event.inlineQuery().query() == null || "".equals(event.inlineQuery().query()))) return null; - return Collections.singletonList(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX), TITLE, - new InputTextMessageContent( - TelegramUserInformation.informationOutputHTML(event.inlineQuery().from()) - ).parseMode(ParseMode.HTML) - )).isPersonal(true).cacheTime(10)); - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java deleted file mode 100644 index a773f6b..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java +++ /dev/null @@ -1,31 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; - -import javax.annotation.Nullable; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; -import com.pengrad.telegrambot.model.request.InputTextMessageContent; - -import java.util.Collections; -import java.util.List; - -import static cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds; - -public class RawText implements ITelegramQuery { - - public static final String ID_PREFIX = "[morny/r/text]"; - public static final String TITLE = "Raw Text"; - - @Override - @Nullable - public List> query (Update event) { - if (event.inlineQuery().query() == null || "".equals(event.inlineQuery().query())) return null; - return Collections.singletonList(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX, event.inlineQuery().query()), TITLE, - new InputTextMessageContent(event.inlineQuery().query()) - ))); - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.java deleted file mode 100644 index da6c2fa..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.java +++ /dev/null @@ -1,80 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; -import cc.sukazyo.cono.morny.util.BiliTool; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; -import com.pengrad.telegrambot.model.request.InputTextMessageContent; -import com.pengrad.telegrambot.model.request.ParseMode; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static cc.sukazyo.cono.morny.Log.logger; -import static cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds; - -public class ShareToolBilibili implements ITelegramQuery { - - public static final String TITLE_BILI_AV = "[bilibili] Share video / av"; - public static final String TITLE_BILI_BV = "[bilibili] Share video / BV"; - public static final String ID_PREFIX_BILI_AV = "[morny/share/bili/av]"; - public static final String ID_PREFIX_BILI_BV = "[morny/share/bili/bv]"; - public static final Pattern REGEX_BILI_VIDEO = Pattern.compile("^(?:(?:https?://)?(?:www\\.)?bilibili\\.com(?:/s)?/video/((?:av|AV)(\\d{1,12})|(?:bv|BV)([A-HJ-NP-Za-km-z1-9]{10}))/?(\\?(?:p=(\\d+))?.*)?|(?:av|AV)(\\d{1,12})|(?:bv|BV)([A-HJ-NP-Za-km-z1-9]{10}))$"); - - private static final String SHARE_FORMAT_HTML = "%s"; - - @Nullable - @Override - public List> query (Update event) { - if (event.inlineQuery().query() == null) return null; - final Matcher regex = REGEX_BILI_VIDEO.matcher(event.inlineQuery().query()); - if (regex.matches()) { - - logger.debug(String.format( - "====== Share Tool Bilibili Catch ok\n1: %s\n2: %s\n3: %s\n4: %s\n5: %s\n6: %s\n7: %s", - regex.group(1), regex.group(2), regex.group(3), regex.group(4), - regex.group(5), regex.group(6), regex.group(7) - )); - - // get video id from input, also get video part id - String av = regex.group(2)==null ? regex.group(6)==null ? null : regex.group(6) : regex.group(2); - String bv = regex.group(3)==null ? regex.group(7)==null ? null : regex.group(7) : regex.group(3); - logger.trace(String.format("catch id av[%s] bv[%s]", av, bv)); - final int part = regex.group(5)==null ? -1 : Integer.parseInt(regex.group(5)); - logger.trace(String.format("catch part [%s]", part)); - if (av == null) { - assert bv != null; - av = String.valueOf(BiliTool.toAv(bv)); - logger.trace(String.format("converted bv[%s] to av[%s]", bv, av)); - } else { - bv = BiliTool.toBv(Long.parseLong(av)); - logger.trace(String.format("converted av[%s] to bv[%s]", av, bv)); - } - // build standard share links - final String linkPartParam = part==-1 ? "" : "?p="+part; - final String linkAv = "https://www.bilibili.com/video/av"+av + linkPartParam; - final String linkBv = "https://www.bilibili.com/video/BV"+bv + linkPartParam; - final String idAv = "av"+av; - final String idBv = "BV"+bv; - logger.trace("built all data."); - - // build share message element - List> result = new ArrayList<>(); - result.add(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX_BILI_AV+av), TITLE_BILI_AV+av, - new InputTextMessageContent(String.format(SHARE_FORMAT_HTML, linkAv, idAv)).parseMode(ParseMode.HTML) - ))); - result.add(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX_BILI_BV+bv), TITLE_BILI_BV+bv, - new InputTextMessageContent(String.format(SHARE_FORMAT_HTML, linkBv, idBv)).parseMode(ParseMode.HTML) - ))); - return result; - - } - return null; - } - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.java deleted file mode 100644 index 9c50d6f..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.java +++ /dev/null @@ -1,50 +0,0 @@ -package cc.sukazyo.cono.morny.bot.query; - -import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds; - -public class ShareToolTwitter implements ITelegramQuery { - - public static final String TITLE_VX = "[tweet] Share as VxTwitter"; - public static final String TITLE_VX_COMBINED = "[tweet] Share as VxTwitter(combination)"; - public static final String ID_PREFIX_VX = "[morny/share/twitter/vxtwi]"; - public static final String ID_PREFIX_VX_COMBINED = "[morny/share/twitter/vxtwi_combine]"; - - public static final Pattern REGEX_TWEET_LINK = Pattern.compile( - "^(?:https?://)?((?:(?:c\\.)?vx|fx|www\\.)?twitter\\.com)/((\\w+)/status/(\\d+)(?:/photo/(\\d+))?)/?(\\?[\\w&=-]+)?$"); - - @Nullable - @Override - public List> query (@Nonnull Update event) { - if (event.inlineQuery().query() == null) return null; - final Matcher regex = REGEX_TWEET_LINK.matcher(event.inlineQuery().query()); - if (regex.matches()) { - - List> result = new ArrayList<>(); - - result.add(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX_VX+event.inlineQuery().query()), TITLE_VX, - String.format("https://vxtwitter.com/%s", regex.group(2)) - ))); - result.add(new InlineQueryUnit<>(new InlineQueryResultArticle( - inlineIds(ID_PREFIX_VX_COMBINED+event.inlineQuery().query()), TITLE_VX_COMBINED, - String.format("https://c.vxtwitter.com/%s", regex.group(2)) - ))); - - return result; - - } - return null; - } - -} 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 deleted file mode 100644 index 0f60d81..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -package cc.sukazyo.cono.morny.data.ip186; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -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); - } - - /** - * 将 {@link #queryWhois(String)} 的结果进行裁剪. - *
- * 将会删除返回内容中 {@code >>> XXX <<<} 行以后的注释串, - * 以达到只保留重要信息的目的。 - * - * @see #queryWhois(String) - */ - @Nonnull - public static IP186QueryResponse queryWhoisPretty (String domain) throws IOException { - final IP186QueryResponse raw = queryWhois(domain); - return new IP186QueryResponse(raw.url(), raw.body().substring(0, raw.body().indexOf("<<<")+3)); - } - - @Nonnull - private static IP186QueryResponse commonQuery (String requestUrl, String queryIpParam) throws IOException { - Request request = new Request.Builder().url(requestUrl + "?" + queryIpParam).build(); - try (Response response = httpClient.newCall(request).execute()) { - final ResponseBody body = response.body(); - if (body == null) throw new IOException("Null body."); - return new IP186QueryResponse(requestUrl, body.string()); - } - } - -} 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 deleted file mode 100644 index f30fb3d..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -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/Log.java b/src/main/old/cc/sukazyo/cono/morny/Log.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/Log.java rename to src/main/old/cc/sukazyo/cono/morny/Log.java diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyAbout.java b/src/main/old/cc/sukazyo/cono/morny/MornyAbout.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/MornyAbout.java rename to src/main/old/cc/sukazyo/cono/morny/MornyAbout.java diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyAssets.java b/src/main/old/cc/sukazyo/cono/morny/MornyAssets.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/MornyAssets.java rename to src/main/old/cc/sukazyo/cono/morny/MornyAssets.java diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java b/src/main/old/cc/sukazyo/cono/morny/MornyCoeur.java similarity index 99% rename from src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java rename to src/main/old/cc/sukazyo/cono/morny/MornyCoeur.java index d891a84..517332d 100644 --- a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java +++ b/src/main/old/cc/sukazyo/cono/morny/MornyCoeur.java @@ -58,7 +58,7 @@ public class MornyCoeur { * morny 主程序启动时间
* 用于统计数据 */ - public static final long coeurStartTimestamp = ServerMain.systemStartupTime; + public static final long coeurStartTimestamp = ServerMain.systemStartupTime(); private Object whileExitReason = null; diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyConfig.java b/src/main/old/cc/sukazyo/cono/morny/MornyConfig.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/MornyConfig.java rename to src/main/old/cc/sukazyo/cono/morny/MornyConfig.java diff --git a/src/main/java/cc/sukazyo/cono/morny/MornySystem.java b/src/main/old/cc/sukazyo/cono/morny/MornySystem.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/MornySystem.java rename to src/main/old/cc/sukazyo/cono/morny/MornySystem.java diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java b/src/main/old/cc/sukazyo/cono/morny/MornyTrusted.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java rename to src/main/old/cc/sukazyo/cono/morny/MornyTrusted.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/api/EventListener.java b/src/main/old/cc/sukazyo/cono/morny/bot/api/EventListener.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/api/EventListener.java rename to src/main/old/cc/sukazyo/cono/morny/bot/api/EventListener.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/api/EventListenerManager.java b/src/main/old/cc/sukazyo/cono/morny/bot/api/EventListenerManager.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/api/EventListenerManager.java rename to src/main/old/cc/sukazyo/cono/morny/bot/api/EventListenerManager.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/api/InlineQueryUnit.java b/src/main/old/cc/sukazyo/cono/morny/bot/api/InlineQueryUnit.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/api/InlineQueryUnit.java rename to src/main/old/cc/sukazyo/cono/morny/bot/api/InlineQueryUnit.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/api/OnUpdate.java b/src/main/old/cc/sukazyo/cono/morny/bot/api/OnUpdate.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/api/OnUpdate.java rename to src/main/old/cc/sukazyo/cono/morny/bot/api/OnUpdate.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java b/src/main/old/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java rename to src/main/old/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java b/src/main/old/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java rename to src/main/old/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java b/src/main/old/cc/sukazyo/cono/morny/bot/command/MornyCommands.java similarity index 96% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java rename to src/main/old/cc/sukazyo/cono/morny/bot/command/MornyCommands.java index e84ab3e..d3cf37f 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java +++ b/src/main/old/cc/sukazyo/cono/morny/bot/command/MornyCommands.java @@ -55,15 +55,15 @@ public class MornyCommands { register( new ON(), new Hello(), /* new {@link HelloOnStart}, */ - new MornyInfoOnHello(), - new GetUsernameAndId(), - new EventHack(), - new Nbnhhsh(), - new Ip186Query.Ip(), - new Ip186Query.Whois(), - new Encryptor(), + MornyInformation$.MODULE$, + GetUsernameAndId$.MODULE$, + EventHack$.MODULE$, + Nbnhhsh$.MODULE$, + IP186Query.IP$.MODULE$, + IP186Query.Whois$.MODULE$, + Encryptor$.MODULE$, new SaveData(), - new MornyInformation(), + MornyInfoOnHello$.MODULE$, new Version(), new MornyRuntime(), new Jrrp(), @@ -72,21 +72,21 @@ public class MornyCommands { // 特殊的命令 register( - new Testing(), - new DirectMsgClear() + Testing$.MODULE$, + DirectMsgClear$.MODULE$ ); // 统一注册这些奇怪的东西&.& register( - new 私わね(), - new 喵呜.Progynova() + 私わね$.MODULE$, + 喵呜.Progynova$.MODULE$ ); // special: 注册出于兼容使用的特别 event 的数据 OnUniMeowTrigger.register( - new 喵呜.抱抱(), - new 喵呜.揉揉(), - new 喵呜.蹭蹭(), - new 喵呜.贴贴() + 喵呜.抱抱$.MODULE$, + 喵呜.揉揉$.MODULE$, + 喵呜.蹭蹭$.MODULE$, + 喵呜.贴贴$.MODULE$ ); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Roll.java b/src/main/old/cc/sukazyo/cono/morny/bot/command/Roll.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/Roll.java rename to src/main/old/cc/sukazyo/cono/morny/bot/command/Roll.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/package-info.java b/src/main/old/cc/sukazyo/cono/morny/bot/command/package-info.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/package-info.java rename to src/main/old/cc/sukazyo/cono/morny/bot/command/package-info.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/EventListeners.java similarity index 79% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/EventListeners.java index 76c9256..f60095e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java +++ b/src/main/old/cc/sukazyo/cono/morny/bot/event/EventListeners.java @@ -1,18 +1,15 @@ package cc.sukazyo.cono.morny.bot.event; import cc.sukazyo.cono.morny.bot.api.EventListenerManager; +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit; public class EventListeners { public static final OnTelegramCommand COMMANDS_LISTENER = new OnTelegramCommand(); // public static final OnActivityRecord ACTIVITY_RECORDER = new OnActivityRecord(); - public static final OnUserSlashAction USER_SLASH_ACTION = new OnUserSlashAction(); public static final OnUpdateTimestampOffsetLock UPDATE_TIMESTAMP_OFFSET_LOCK = new OnUpdateTimestampOffsetLock(); - public static final OnInlineQueries INLINE_QUERY = new OnInlineQueries(); - public static final OnCallMe CALL_ME = new OnCallMe(); public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle(); // static final OnKuohuanhuanNeedSleep KUOHUANHUAN_NEED_SLEEP = new OnKuohuanhuanNeedSleep(); - public static final OnUserRandoms USER_RANDOMS = new OnUserRandoms(); public static final OnCallMsgSend CALL_MSG_SEND = new OnCallMsgSend(); public static final OnMedicationNotifyApply MEDICATION_NOTIFY_APPLY = new OnMedicationNotifyApply(); public static final OnRandomlyTriggered RANDOMLY_TRIGGERED = new OnRandomlyTriggered(); @@ -28,11 +25,11 @@ public class EventListeners { COMMANDS_LISTENER, UNI_MEOW_TRIGGER, RANDOMLY_TRIGGERED, - USER_RANDOMS, + OnUserRandom$.MODULE$, QUESTION_MARK_REPLY, - USER_SLASH_ACTION, - INLINE_QUERY, - CALL_ME, + OnUserSlashAction$.MODULE$, + OnInlineQuery$.MODULE$, + OnCallMe$.MODULE$, CALL_MSG_SEND, MEDICATION_NOTIFY_APPLY, EVENT_HACK_HANDLE diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnActivityRecord.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnActivityRecord.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnActivityRecord.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnActivityRecord.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnEventHackHandle.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnKuohuanhuanNeedSleep.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnKuohuanhuanNeedSleep.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnKuohuanhuanNeedSleep.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnKuohuanhuanNeedSleep.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnQuestionMarkReply.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnQuestionMarkReply.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnQuestionMarkReply.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnQuestionMarkReply.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnRandomlyTriggered.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnRandomlyTriggered.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnRandomlyTriggered.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnRandomlyTriggered.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUniMeowTrigger.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnUniMeowTrigger.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnUniMeowTrigger.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnUniMeowTrigger.java diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java b/src/main/old/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java rename to src/main/old/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java b/src/main/old/cc/sukazyo/cono/morny/daemon/MedicationTimer.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java rename to src/main/old/cc/sukazyo/cono/morny/daemon/MedicationTimer.java diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/MornyDaemons.java b/src/main/old/cc/sukazyo/cono/morny/daemon/MornyDaemons.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/daemon/MornyDaemons.java rename to src/main/old/cc/sukazyo/cono/morny/daemon/MornyDaemons.java diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java b/src/main/old/cc/sukazyo/cono/morny/daemon/MornyReport.java similarity index 99% rename from src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java rename to src/main/old/cc/sukazyo/cono/morny/daemon/MornyReport.java index 11a646c..9a81a5e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java +++ b/src/main/old/cc/sukazyo/cono/morny/daemon/MornyReport.java @@ -88,7 +88,7 @@ public class MornyReport { as config fields: %s """, - MornyInformation.getVersionAllFullTagHtml(), + MornyInformation.getVersionAllFullTagHTML(), MornyCoeur.getUsername(), sectionConfigFields(MornyCoeur.config()) ) diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/TrackerDataManager.java b/src/main/old/cc/sukazyo/cono/morny/daemon/TrackerDataManager.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/daemon/TrackerDataManager.java rename to src/main/old/cc/sukazyo/cono/morny/daemon/TrackerDataManager.java diff --git a/src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java b/src/main/old/cc/sukazyo/cono/morny/data/MornyJrrp.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/data/MornyJrrp.java rename to src/main/old/cc/sukazyo/cono/morny/data/MornyJrrp.java diff --git a/src/main/java/cc/sukazyo/cono/morny/data/NbnhhshQuery.java b/src/main/old/cc/sukazyo/cono/morny/data/NbnhhshQuery.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/data/NbnhhshQuery.java rename to src/main/old/cc/sukazyo/cono/morny/data/NbnhhshQuery.java diff --git a/src/main/java/cc/sukazyo/cono/morny/data/TelegramImages.java b/src/main/old/cc/sukazyo/cono/morny/data/TelegramImages.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/data/TelegramImages.java rename to src/main/old/cc/sukazyo/cono/morny/data/TelegramImages.java diff --git a/src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java b/src/main/old/cc/sukazyo/cono/morny/data/TelegramStickers.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java rename to src/main/old/cc/sukazyo/cono/morny/data/TelegramStickers.java diff --git a/src/main/java/cc/sukazyo/cono/morny/internal/BuildConfigField.java b/src/main/old/cc/sukazyo/cono/morny/internal/BuildConfigField.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/internal/BuildConfigField.java rename to src/main/old/cc/sukazyo/cono/morny/internal/BuildConfigField.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/BiliTool.java b/src/main/old/cc/sukazyo/cono/morny/util/BiliTool.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/BiliTool.java rename to src/main/old/cc/sukazyo/cono/morny/util/BiliTool.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/CommonConvert.java b/src/main/old/cc/sukazyo/cono/morny/util/CommonConvert.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/CommonConvert.java rename to src/main/old/cc/sukazyo/cono/morny/util/CommonConvert.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/CommonEncrypt.java b/src/main/old/cc/sukazyo/cono/morny/util/CommonEncrypt.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/CommonEncrypt.java rename to src/main/old/cc/sukazyo/cono/morny/util/CommonEncrypt.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/CommonFormat.java b/src/main/old/cc/sukazyo/cono/morny/util/CommonFormat.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/CommonFormat.java rename to src/main/old/cc/sukazyo/cono/morny/util/CommonFormat.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/CommonRandom.java b/src/main/old/cc/sukazyo/cono/morny/util/CommonRandom.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/CommonRandom.java rename to src/main/old/cc/sukazyo/cono/morny/util/CommonRandom.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/FileUtils.java b/src/main/old/cc/sukazyo/cono/morny/util/FileUtils.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/FileUtils.java rename to src/main/old/cc/sukazyo/cono/morny/util/FileUtils.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/OkHttpPublic.java b/src/main/old/cc/sukazyo/cono/morny/util/OkHttpPublic.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/OkHttpPublic.java rename to src/main/old/cc/sukazyo/cono/morny/util/OkHttpPublic.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/UniversalCommand.java b/src/main/old/cc/sukazyo/cono/morny/util/UniversalCommand.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/UniversalCommand.java rename to src/main/old/cc/sukazyo/cono/morny/util/UniversalCommand.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/ExtraAction.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/ExtraAction.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/ExtraAction.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/ExtraAction.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/InputCommand.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/InputCommand.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/InputCommand.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/InputCommand.java diff --git a/src/main/old/cc/sukazyo/cono/morny/util/tgapi/Standardize.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/Standardize.java new file mode 100644 index 0000000..ae3efa3 --- /dev/null +++ b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/Standardize.java @@ -0,0 +1,7 @@ +package cc.sukazyo.cono.morny.util.tgapi; + +public class Standardize { + + public static final int CHANNEL_SPEAKER_MAGIC_ID = 136817688; + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/MsgEscape.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/MsgEscape.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/MsgEscape.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/MsgEscape.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/NamedUtils.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/NamedUtils.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/NamedUtils.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/NamedUtils.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToString.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToString.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToString.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToString.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java similarity index 92% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java index 8671056..46045f0 100644 --- a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java +++ b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromChat.java @@ -1,6 +1,7 @@ package cc.sukazyo.cono.morny.util.tgapi.formatting; import com.pengrad.telegrambot.model.Chat; +import com.pengrad.telegrambot.model.Message; public class TGToStringFromChat { diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromMessage.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromMessage.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromMessage.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromMessage.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromUser.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromUser.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromUser.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TGToStringFromUser.java diff --git a/src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramUserInformation.java b/src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramUserInformation.java similarity index 100% rename from src/main/java/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramUserInformation.java rename to src/main/old/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramUserInformation.java diff --git a/src/main/scala/cc/sukazyo/cono/morny/ServerMain.scala b/src/main/scala/cc/sukazyo/cono/morny/ServerMain.scala new file mode 100644 index 0000000..91907ae --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/ServerMain.scala @@ -0,0 +1,156 @@ +package cc.sukazyo.cono.morny + +import cc.sukazyo.cono.morny.Log.logger +import cc.sukazyo.cono.morny.MornyConfig.CheckFailure +import cc.sukazyo.cono.morny.util.CommonFormat + +import java.time.ZoneOffset +import scala.collection.mutable.ArrayBuffer +import scala.language.postfixOps + +object ServerMain { + + private val THREAD_MORNY_INIT: String = "morny-init" + + val systemStartupTime: Long = System.currentTimeMillis() + + def main (args: Array[String]): Unit = { + + val config = new MornyConfig.Prototype() + var mode_echoVersion = false + var mode_echoHello = false + var showHello = true + + config.eventOutdatedTimestamp = systemStartupTime + + val unknownArgs = ArrayBuffer[String]() + + var i = 0 + while (i < args.length) { + args(i) match { + + case "-d" | "--dbg" | "--debug" => Log.debug(true) + + case "--no-hello" | "-hf" | "--quiet" | "-q" => showHello = false + case "--only-hello" | "-ho" | "-o" | "-hi" => mode_echoHello = true + case "--version" | "-v" => mode_echoVersion = true + + case "--outdated-block" | "-ob" => config.eventIgnoreOutdated = true + + case "--api" | "-a" => i+=1 ; config.telegramBotApiServer = args(i) + case "--api-files" | "files-api" | "-af" => i+=1; config.telegramBotApiServer4File = args(i) + + case "--token" | "-t" => i+=1 ; config.telegramBotKey = args(i) + case "--username" | "-u" => i+=1 ; config.telegramBotUsername = args(i) + + case "--master" | "-mm" => i+=1 ; config.trustedMaster = args(i)toLong + case "--trusted-chat" | "-trs" => i+=1 ; config.trustedChat = args(i)toLong + case "--report-to" => i+=1; config.reportToChat = args(i)toLong + + case "--trusted-reader-dinner" | "-trsd" => i+=1 ; config.dinnerTrustedReaders add (args(i)toLong) + case "--dinner-chat" | "-chd" => i+=1 ; config.dinnerChatId = args(i)toLong + + case "--medication-notify-chat" | "-medc" => i+=1 ; config.medicationNotifyToChat = args(i)toLong + case "--medication-notify-timezone" | "-medtz" => + i+=1 + config.medicationTimerUseTimezone = ZoneOffset.ofHours(args(i)toInt) + case "--medication-notify-times" | "-medt" => + i+=1 + for (u <- args(i) split ",") { + config.medicationNotifyAt add (u toInt) + } + + case "--auto-cmd-list" | "-ca" => config.commandLoginRefresh = true + case "--auto-cmd-remove" | "-cr" => config.commandLogoutClear = true + case "--auto-cmd" | "-cmd" | "-c" => + config.commandLoginRefresh = true + config.commandLogoutClear = true + + case _ => unknownArgs append args(i) + + } + i+=1 + } + + /// Setup launch params from ENVIRONMENT + var propToken: String = null + var propTokenKey: String = null + for (iKey <- MornyConfig.PROP_TOKEN_KEY) { + if ((System getenv iKey) != null) { + propToken = System getenv iKey + propTokenKey = iKey + } + } + + /// + /// Output startup message + /// process startup params - like startup mode + /// + + if (showHello) logger info MornyAbout.MORNY_PREVIEW_IMAGE_ASCII + if (mode_echoHello) return; + + if (unknownArgs.nonEmpty) logger warn + s"""Can't understand arg to some meaning + | ${unknownArgs mkString "\n "}""" + .stripMargin + + if (Log debug) + logger warn + """Debug log output enabled. + | It may lower your performance, make sure that you are not in production environment.""" + .stripMargin + + if (mode_echoVersion) { + + logger info + s"""Morny Cono Version + |- version : + | Morny ${MornySystem.CODENAME toUpperCase} + | ${MornySystem.VERSION_BASE}${if (MornySystem.isUseDelta) "-δ"+MornySystem.VERSION_DELTA else ""} + |- md5hash : + | ${MornySystem.getJarMd5} + |- gitstat : + |${ if (MornySystem.isGitBuild) { + s""" on commit ${if (MornySystem.isCleanBuild) "- clean-build" else "<δ/non-clean-build>"} + | ${BuildConfig.COMMIT}""" + .stripMargin + } else " "} + |- buildtd : + | ${BuildConfig.CODE_TIMESTAMP} + | ${CommonFormat.formatDate(BuildConfig.CODE_TIMESTAMP, 0)} [UTC]""" + .stripMargin + return + + } + + logger info + s"""ServerMain.java Loaded >>> + |- version ${MornySystem.VERSION_FULL} + |- Morny ${MornySystem.CODENAME toUpperCase} + |- <${MornySystem.getJarMd5}> [${BuildConfig.CODE_TIMESTAMP}]""".stripMargin + + /// + /// Check Coeur arguments + /// finally start Coeur Program + /// + + if (propToken != null) { + config.telegramBotKey = propToken + logger info s"Parameter set by EnvVar $$$propTokenKey" + } + + Thread.currentThread setName THREAD_MORNY_INIT + + try + MornyCoeur.init(new MornyConfig(config)) + catch { + case _: CheckFailure.NullTelegramBotKey => + logger.info("Parameter required has no value:\n --token.") + case e: CheckFailure => + logger.error("Unknown failure occurred while starting ServerMain!:") + e.printStackTrace(System.out) + } + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.scala new file mode 100644 index 0000000..e3e1761 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/DirectMsgClear.scala @@ -0,0 +1,54 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.Log.logger +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.data.TelegramStickers +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.{Chat, Update} +import com.pengrad.telegrambot.request.{DeleteMessage, GetChatMember, SendSticker} + +import scala.language.postfixOps + +object DirectMsgClear extends ISimpleCommand { + + override def getName: String = "r" + override def getAliases: Array[String] = null + + override def execute (command: InputCommand, event: Update): Unit = { + + logger debug "executing command /r" + if (event.message.replyToMessage == null) return; + logger trace "message is a reply" + if (event.message.replyToMessage.from.id != MornyCoeur.getUserid) return; + logger trace "message replied is from me" + if (System.currentTimeMillis/1000 - event.message.replyToMessage.date > 48*60*60) return; + logger trace "message is not outdated(48 hrs ago)" + + val isTrusted = MornyCoeur.trustedInstance isTrusted event.message.from.id + def _isReplyTrusted: Boolean = + if (event.message.replyToMessage.replyToMessage == null) false + else if (event.message.replyToMessage.replyToMessage.from.id == event.message.from.id) true + else false + + if (isTrusted || _isReplyTrusted) { + + MornyCoeur.extra exec DeleteMessage( + event.message.chat.id, event.message.replyToMessage.messageId + ) + + def _isPrivate: Boolean = event.message.chat.`type` == Chat.Type.Private + def _isPermission: Boolean = + (MornyCoeur.extra exec GetChatMember(event.message.chat.id, event.message.from.id)) + .chatMember.canDeleteMessages + if (_isPrivate || _isPermission) { + MornyCoeur.extra exec DeleteMessage(event.message.chat.id, event.message.messageId) + } + + } else MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_403 + ).replyToMessageId(event.message.messageId) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/Encryptor.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Encryptor.scala new file mode 100644 index 0000000..77be888 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Encryptor.scala @@ -0,0 +1,178 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.Log.logger +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.daemon.MornyReport +import cc.sukazyo.cono.morny.data.TelegramStickers +import cc.sukazyo.cono.morny.util.CommonConvert.byteArrayToHex +import cc.sukazyo.cono.morny.util.CommonEncrypt +import cc.sukazyo.cono.morny.util.CommonEncrypt.* +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.{PhotoSize, Update} +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.{GetFile, SendDocument, SendMessage, SendSticker} + +import java.io.IOException +import java.util.Base64 +import scala.language.postfixOps + +object Encryptor extends ITelegramCommand { + + override def getName: String = "encrypt" + override def getAliases: Array[String] = null + override def getParamRule: String = "[algorithm|(l)] [(uppercase)]" + override def getDescription: String = "通过指定算法加密回复的内容 (目前只支持文本)" + + override def execute (command: InputCommand, event: Update): Unit = { + + val args = command.getArgs + + if ((args isEmpty) || ((args(0) equals "l") && (args.length == 1))) + echoHelp(event.message.chat.id, event.message.messageId) + return + + def _is_mod_u(arg: String): Boolean = + if (arg equalsIgnoreCase "uppercase") return true + if (arg equalsIgnoreCase "u") return true + if (arg equalsIgnoreCase "upper") return true + false + val mod_uppercase = if (args.length > 1) { + if (args.length < 3 && _is_mod_u(args(1))) true + else + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_404 + ).replyToMessageId(event.message.messageId) + return + } else false + + trait XEncryptable { val asByteArray: Array[Byte] } + case class XFile (data: Array[Byte], name: String) extends XEncryptable { + val asByteArray: Array[Byte] = data + } + case class XText (data: String) extends XEncryptable { + val asByteArray: Array[Byte] = data getBytes CommonEncrypt.ENCRYPT_STANDARD_CHARSET + } + val input: XEncryptable = + val _r = event.message.replyToMessage + if ((_r ne null) && (_r.document ne null)) { + try {XFile( + MornyCoeur.getAccount getFileContent (MornyCoeur.extra exec GetFile(_r.document.fileId)).file, + _r.document.fileName + )} catch case e: IOException => + logger warn s"NetworkRequest error: TelegramFileAPI:\n\t${e.getMessage}" + MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI") + return + } else if ((_r ne null) && (_r.photo ne null)) { + try { + var _photo_origin: PhotoSize = null + var _photo_size: Long = 0 + for (size <- _r.photo) + val _size = (size.width longValue)*size.height + if (_photo_size < _size) + _photo_origin = size + _photo_size = _size + if (_photo_origin eq null) throw IllegalArgumentException("no photo from api.") + XFile( + MornyCoeur.getAccount getFileContent (MornyCoeur.extra exec GetFile(_photo_origin.fileId)).file, + s"photo${byteArrayToHex(hashMd5(System.currentTimeMillis toString)) substring 32-12 toUpperCase}.png" + ) + } catch + case e: IOException => + logger warn s"NetworkRequest error: TelegramFileAPI:\n\t${e.getMessage}" + MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI") + return + case e: IllegalArgumentException => + logger warn s"FileProcess error: PhotoSize:\n\t${e.getMessage}" + MornyReport.exception(e, "FileProcess error: PhotoSize") + return + } else if ((_r ne null) && (_r.text ne null)) { + XText(_r.text) + } else { + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + "null" + ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) + return + } + + + trait EXTextLike { val text: String } + case class EXFile (result: Array[Byte], resultName: String) + case class EXText (result: String) extends EXTextLike { override val text:String = result } + case class EXHash (result: String) extends EXTextLike { override val text:String = result } + def genResult_encrypt (source: XEncryptable, processor: Array[Byte]=>Array[Byte], filenameProcessor: String=>String): EXFile|EXText = { + source match + case x_file: XFile => EXFile(processor(x_file asByteArray), filenameProcessor(x_file.name)) + case x: XText => EXText(String(processor(x asByteArray), ENCRYPT_STANDARD_CHARSET)) + } + def genResult_hash (source: XEncryptable, processor: Array[Byte]=>Array[Byte]): EXHash = + val hashed = byteArrayToHex(processor(source asByteArray)) + EXHash(if mod_uppercase then hashed toUpperCase else hashed) + val result: EXHash|EXFile|EXText = args(0) match + case "base64" | "b64" | "base64url" | "base64u" | "b64u" => + val _tool_b64 = + if args(0) contains "u" then Base64.getUrlEncoder + else Base64.getEncoder + genResult_encrypt( + input, + _tool_b64.encode, + n => n+".b64.txt" + ) + case "base64decode" | "base64d" | "b64d" | "base64url-decode" | "base64ud" | "b64ud" => + val _tool_b64d = + if args(0) contains "u" then Base64.getUrlDecoder + else Base64.getDecoder + try { genResult_encrypt( + input, + _tool_b64d.decode, + CommonEncrypt.base64FilenameLint + ) } catch case _: IllegalArgumentException => + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_404 // todo: is here better erro notify? + ).replyToMessageId(event.message.messageId) + return + case "md5" => genResult_hash(input, hashMd5) + case "sha1" => genResult_hash(input, hashSha1) + case "sha256" => genResult_hash(input, hashSha256) + case "sha512" => genResult_hash(input, hashSha512) + case _ => + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_404 + ).replyToMessageId(event.message.messageId) + return; + + result match + case _file: EXFile => + MornyCoeur.extra exec SendDocument( + event.message.chat.id, + _file.result + ).fileName(_file.resultName).replyToMessageId(event.message.messageId) + case _text: EXTextLike => + import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + s"
${h(_text.text)}
" + ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) + + } + + private def echoHelp(chat: Long, replyTo: Int): Unit = + MornyCoeur.extra exec SendMessage( + chat, + s"""base64, b64 + |base64url, base64u, b64u + |base64decode, base64d, b64d + |base64url-decode, base64ud, b64ud + |sha1 + |sha256 + |sha512 + |md5 + |--- + |uppercase, upper, u (sha1/sha256/sha512/md5 only)""" + .stripMargin + ).replyToMessageId(replyTo).parseMode(ParseMode HTML) + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/EventHack.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/EventHack.scala new file mode 100644 index 0000000..a4fddb0 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/EventHack.scala @@ -0,0 +1,56 @@ +package cc.sukazyo.cono.morny.bot.command +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.bot.event.OnEventHackHandle +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.Update +import OnEventHackHandle.{HackType, registerHack} +import cc.sukazyo.cono.morny.data.TelegramStickers +import com.pengrad.telegrambot.request.SendSticker + +import scala.language.postfixOps + +object EventHack extends ITelegramCommand { + + override def getName: String = "event_hack" + override def getAliases: Array[String] = null + override def getParamRule: String = "[(user|group|any)]" + override def getDescription: String = "输出 bot 下一个获取到的事件序列化数据" + + override def execute (command: InputCommand, event: Update): Unit = { + + val x_mode = if (command.hasArgs) command.getArgs()(0) else "" + + def done_ok = + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_WAITING + ).replyToMessageId(event.message.messageId) + def done_forbiddenForAny = + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_403 + ).replyToMessageId(event.message.messageId) + + def doRegister (t: HackType): Unit = + registerHack( + event.message.messageId longValue, + event.message.from.id, + event.message.chat.id, + t + ) + x_mode match + case "any" => + if (MornyCoeur.trustedInstance isTrusted event.message.from.id) + doRegister(HackType ANY) + done_ok + else done_forbiddenForAny + case "group" => + doRegister(HackType GROUP) + done_ok + case _ => + doRegister(HackType USER) + done_ok + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.scala new file mode 100644 index 0000000..3f03650 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.scala @@ -0,0 +1,66 @@ +package cc.sukazyo.cono.morny.bot.command +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation +import cc.sukazyo.cono.morny.util.tgapi.{InputCommand, Standardize} +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.{GetChatMember, SendMessage} + +import scala.language.postfixOps + +object GetUsernameAndId extends ITelegramCommand { + + override def getName: String = "user" + override def getAliases: Array[String] = Array() + override def getParamRule: String = "[userid]" + override def getDescription: String = "获取指定或回复的用户相关信息" + + override def execute (command: InputCommand, event: Update): Unit = { + + val args = command.getArgs + + if (args.length > 1) + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + "[Unavailable] Too much arguments." + ).replyToMessageId(event.message.messageId) + return + + val userId: Long = + if (args nonEmpty) { + try args(0) toLong + catch case e: NumberFormatException => + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + s"[Unavailable] ${e.getMessage}" + ).replyToMessageId(event.message.messageId) + return + } else if (event.message.replyToMessage eq null) event.message.from.id + else event.message.replyToMessage.from.id + + val response = MornyCoeur.getAccount execute GetChatMember(event.message.chat.id, userId) + + if (response.chatMember eq null) + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + "[Unavailable] user not found." + ).replyToMessageId(event.message.messageId) + return + + val user = response.chatMember.user + + if (user.id eq Standardize.CHANNEL_SPEAKER_MAGIC_ID) + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + "$__channel_identify" + ).replyToMessageId(event.message.messageId) + return; + + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + TelegramUserInformation informationOutputHTML user + ).replyToMessageId(event.message.messageId()).parseMode(ParseMode HTML) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/IP186Query.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/IP186Query.scala new file mode 100644 index 0000000..a901580 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/IP186Query.scala @@ -0,0 +1,77 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.data.ip186.IP186QueryHandler +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.SendMessage + +import scala.language.postfixOps + +object IP186Query { + + private enum Subs (val cmd: String): + case IP extends Subs("ip") + case WHOIS extends Subs("whois") + + object IP extends ITelegramCommand: + override def getName: String = "ip" + override def getAliases: Array[String] = null + override def getParamRule: String = "[ip]" + override def getDescription: String = "通过 https://ip.186526.xyz 查询 ip 资料" + override def execute (command: InputCommand, event: Update): Unit = query(event, command) + object Whois extends ITelegramCommand: + override def getName: String = "whois" + override def getAliases: Array[String] = null + override def getParamRule: String = "[domain]" + override def getDescription: String = "通过 https://ip.186526.xyz 查询域名资料" + override def execute (command: InputCommand, event: Update): Unit = query(event, command) + + private def query (event: Update, command: InputCommand): Unit = { + + val target: String|Null = + if (command.getArgs isEmpty) + if event.message.replyToMessage eq null then null else event.message.replyToMessage.text + else if (command.getArgs.length > 1) + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + "[Unavailable] Too much arguments." + ).replyToMessageId(event.message.messageId) + return + else command.getArgs()(0) + + if (target eq null) + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + "[Unavailable] No ip defined." + ).replyToMessageId(event.message.messageId) + return; + + try { + + val response = command.getCommand match + case Subs.IP.cmd => IP186QueryHandler.query_ip(target) + case Subs.WHOIS.cmd => IP186QueryHandler.query_whoisPretty(target) + case _ => throw IllegalArgumentException(s"Unknown 186-IP query method ${command.getCommand}") + + import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + s"""${h(response.url)} + |${h(response.body)}""" + .stripMargin + ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) + + } catch case e: Exception => + import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + s"""[Exception] in query: + |${h(e.getMessage)}""" + .stripMargin + ).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId())); + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.scala new file mode 100644 index 0000000..2df1ba5 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.scala @@ -0,0 +1,35 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.SendPhoto + +import scala.language.postfixOps + +object MornyInfoOnHello extends ISimpleCommand { + + override def getName: String = "start" + override def getAliases: Array[String] = Array() + + override def execute (command: InputCommand, event: Update): Unit = { + + MornyCoeur.extra exec new SendPhoto( + event.message.chat.id, + MornyInformation.getAboutPic + ).caption( + s"""欢迎使用 Morny Cono来自安妮的侍从小鼠。 + |Morny 具有各种各样的功能。 + | + |———————————————— + |${MornyInformation.getMornyAboutLinksHTML} + |———————————————— + | + |(你可以随时通过 /info 重新获得这些信息)""" + .stripMargin + ).parseMode(ParseMode HTML) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInformation.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInformation.scala new file mode 100644 index 0000000..e81a9fb --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/MornyInformation.scala @@ -0,0 +1,167 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.data.{TelegramImages, TelegramStickers} +import cc.sukazyo.cono.morny.util.CommonFormat.{formatDate, formatDuration} +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h +import cc.sukazyo.cono.morny.{BuildConfig, MornyAbout, MornyCoeur, MornySystem} +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.{SendMessage, SendPhoto, SendSticker} + +import java.lang.System +import java.net.InetAddress +import java.rmi.UnknownHostException +import scala.language.postfixOps + +object MornyInformation extends ITelegramCommand { + + private case object Subs { + val STICKERS = "stickers" + val RUNTIME = "runtime" + val VERSION = "version" + val VERSION_2 = "v" + } + + override def getName: String = "info" + override def getAliases: Array[String] = Array() + override def getParamRule: String = "[(version|runtime|stickers[.IDs])]" + override def getDescription: String = "输出当前 Morny 的各种信息" + + override def execute (command: InputCommand, event: Update): Unit = { + + if (!command.hasArgs) { + echoInfo(event.message.chat.id, event.message.messageId) + return + } + + val action: String = command.getArgs()(0) + + action match { + case Subs.STICKERS => echoStickers(command, event) + case Subs.RUNTIME => echoRuntime(event) + case Subs.VERSION | Subs.VERSION_2 => echoVersion(event) + case _ => echo404(event) + } + + } + + def getVersionGitTagHTML: String = { + if (!MornySystem.isGitBuild) return "" + val g = StringBuilder() + val cm = BuildConfig.COMMIT substring(0, 8) + val cp = MornySystem.currentCodePath + if (cp == null) g++= s"$cm" + else g++= s"$cm" + if (!MornySystem.isCleanBuild) g++= ".δ" + g toString + } + + def getVersionAllFullTagHTML: String = { + val v = StringBuilder() + v ++= s"${MornySystem VERSION_BASE}" + if (MornySystem isUseDelta) v++=s"-δ${MornySystem VERSION_DELTA}" + if (MornySystem isGitBuild) v++="+"++=getVersionGitTagHTML + v ++= s"*${MornySystem.CODENAME toUpperCase}" + v toString + } + + def getRuntimeHostname: String|Null = { + try InetAddress.getLocalHost.getHostName + catch case _:UnknownHostException => null + } + + def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT get + + def getMornyAboutLinksHTML: String = + s"""source code | backup + |反馈 / issue tracker + |使用说明书 / user guide & docs""" + .stripMargin + + private def echoInfo (chatId: Long, replyTo: Int): Unit = { + MornyCoeur.extra exec new SendPhoto( + chatId, + getAboutPic + ).caption( + s"""Morny Cono + |来自安妮的侍从小鼠。 + |———————————————— + |$getMornyAboutLinksHTML""" + .stripMargin + ).parseMode(ParseMode HTML).replyToMessageId(replyTo) + } + + private def echoStickers (command: InputCommand, event: Update): Unit = { + val chat = event.message.chat.id + val replyTo = event.message.messageId + var sid: String|Null = null + if (command.getArgs()(0) eq Subs.STICKERS) { + if (command.getArgs.length == 1) sid = "" + else if (command.getArgs.length == 2) sid = command.getArgs()(1) + } else if (command.getArgs.length == 1) { + if ((command.getArgs()(0) startsWith s"${Subs.STICKERS}.") || (command.getArgs()(0) startsWith s"${Subs.STICKERS}#")) { + sid = command.getArgs()(0) substring Subs.STICKERS.length+1 + } + } + if (sid == null) echo404(event) + else echoStickers(sid, chat, replyTo) + } + + private def echoStickers (sid: String, send_chat: Long, send_replyTo: Int): Unit = { + if (sid isEmpty) TelegramStickers echoAllStickers(MornyCoeur.extra, send_chat, send_replyTo) + else TelegramStickers echoStickerByID(sid, MornyCoeur.extra, send_chat, send_replyTo) + } + + private[command] def echoVersion (event: Update): Unit = { + val versionDeltaHTML = if (MornySystem.isUseDelta) s"-δ${h(MornySystem.VERSION_DELTA)}" else "" + val versionGitHTML = if (MornySystem.isGitBuild) s"git $getVersionGitTagHTML" else "" + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + s"""version: + |- Morny ${h(MornySystem.CODENAME toUpperCase)} + |- ${h(MornySystem.VERSION_BASE)}$versionDeltaHTML${if (MornySystem.isGitBuild) "\n- " + versionGitHTML else ""} + |coeur md5_hash: + |- ${h(MornySystem.getJarMd5)} + |coding timestamp: + |- ${BuildConfig.CODE_TIMESTAMP} + |- ${h(formatDate(BuildConfig.CODE_TIMESTAMP, 0))} [UTC] + |""".stripMargin + ).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML) + } + + private[command] def echoRuntime (event: Update): Unit = { + def sysprop (p: String): String = System.getProperty(p) + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + /* html */ + s"""system: + |- Morny ${h(if (getRuntimeHostname == null) "" else getRuntimeHostname)} + |- ${h(sysprop("os.name"))} ${h(sysprop("os.arch"))} ${h(sysprop("os.version"))} + |java runtime: + |- ${h(sysprop("java.vm.vendor"))}.${h(sysprop("java.vm.name"))} + |- ${h(sysprop("java.vm.version"))} + |vm memory: + |- ${Runtime.getRuntime.totalMemory/1024/1024} / ${Runtime.getRuntime.maxMemory/1024/1024} + |- ${Runtime.getRuntime.availableProcessors} cores + |coeur version: + |- $getVersionAllFullTagHTML + |- ${h(MornySystem.getJarMd5)} + |- ${h(formatDate(BuildConfig.CODE_TIMESTAMP, 0))} [UTC] + |- [${BuildConfig.CODE_TIMESTAMP}] + |continuous: + |- ${h(formatDuration(System.currentTimeMillis - MornyCoeur.coeurStartTimestamp))} + |- [${System.currentTimeMillis - MornyCoeur.coeurStartTimestamp}] + |- ${h(formatDate(MornyCoeur.coeurStartTimestamp, 0))} + |- [${MornyCoeur.coeurStartTimestamp}]""" + .stripMargin + ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) + } + + private def echo404 (event: Update): Unit = + MornyCoeur.extra exec new SendSticker( + event.message.chat.id, + TelegramStickers ID_404 + ).replyToMessageId(event.message.messageId) + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.scala new file mode 100644 index 0000000..5c7d799 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.scala @@ -0,0 +1,85 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.data.{NbnhhshQuery, TelegramStickers} +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.{SendMessage, SendSticker} + +import java.io.IOException +import scala.language.postfixOps + +object Nbnhhsh extends ITelegramCommand { + + private val NBNHHSH_RESULT_HEAD_HTML = "## Result of nbnhhsh query :" + + override def getName: String = "nbnhhsh" + override def getAliases: Array[String]|Null = null + override def getParamRule: String = "[text]" + override def getDescription: String = "检索文本内 nbnhhsh 词条" + + override def execute (command: InputCommand, event: Update): Unit = { + + val queryTarget: String|Null = + import cc.sukazyo.cono.morny.util.CommonConvert.stringsConnecting + if (event.message.replyToMessage != null && event.message.replyToMessage.text != null) + event.message.replyToMessage.text + else if command hasArgs then + stringsConnecting(command.getArgs, " ", 0, command.getArgs.length-1) + else null + + if (queryTarget == null) + MornyCoeur.extra exec SendSticker( + event.message.chat.id, + TelegramStickers ID_404 + ).replyToMessageId(event.message.messageId) + return; + + try { + + val queryResp = NbnhhshQuery sendGuess queryTarget + + val message = StringBuilder(NBNHHSH_RESULT_HEAD_HTML) + + import cc.sukazyo.cono.morny.Log.logger + logger debug s"**xx len=${queryResp.words.length}" + for (_word <- queryResp.words) { + logger debug "**exec" + if ((_word.trans ne null) && (_word.trans isEmpty)) _word.trans = null + if ((_word.inputting ne null) && (_word.inputting isEmpty)) _word.inputting = null + if ((_word.trans ne null) || (_word.inputting ne null)) + message ++= s"\n\n[[ ${h(_word.name)} ]]" + logger debug s"**used [${_word.name}]" + if (_word.trans != null) for (_trans <- _word.trans) + message ++= s"\n* ${h(_trans)}" + logger debug s"**used [${_word.name}] used `${_trans}``" + if (_word.inputting != null) + logger debug s"**used [${_word.name}] inputting" + if (_word.trans != null) + message += '\n' + message ++= " maybe:" + for (_inputting <- _word.inputting) + logger debug s"**used [${_word.name}] used-i ${_inputting}" + message ++= s"\n` ${h(_inputting)}" + logger debug s"**exec as ${_word.name}" + } + + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + message toString + ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) + + } catch case e: IOException => { + MornyCoeur.extra exec SendMessage( + event.message.chat.id, + s"""[Exception] in query: + |${h(e.getMessage)} + |""".stripMargin + ) + } + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/Testing.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Testing.scala new file mode 100644 index 0000000..4d453da --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/Testing.scala @@ -0,0 +1,30 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.SendMessage + +import javax.annotation.Nonnull +import javax.annotation.Nullable +import scala.language.postfixOps + +object Testing extends ISimpleCommand { + + override def getName: String = "test" + override def getAliases: Array[String] = null + + override def execute (command: InputCommand, event: Update): Unit = { + + val a = StringBuilder("value") + a ++= "Changed" + + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + "Just a TEST command. num is:" + (a toString) + ).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/喵呜.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/喵呜.scala new file mode 100644 index 0000000..c870e8e --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/喵呜.scala @@ -0,0 +1,67 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.data.TelegramStickers +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.model.{Message, Update} +import com.pengrad.telegrambot.request.{SendMessage, SendSticker} + +import javax.swing.text.html.HTML +import scala.annotation.unused +import scala.language.postfixOps + +@SuppressWarnings(Array("NonAsciiCharacters")) +object 喵呜 { + + object 抱抱 extends ISimpleCommand { + override def getName: String = "抱抱" + override def getAliases: Array[String] = Array() + override def execute (command: InputCommand, event: Update): Unit = + replyingSet(event, "贴贴", "贴贴") + } + + object 揉揉 extends ISimpleCommand { + override def getName: String = "揉揉" + override def getAliases: Array[String] = Array() + override def execute (command: InputCommand, event: Update): Unit = + replyingSet(event, "蹭蹭", "摸摸") + } + + object 蹭蹭 extends ISimpleCommand { + override def getName: String = "蹭蹭" + override def getAliases: Array[String] = Array() + override def execute (command: InputCommand, event: Update): Unit = + replyingSet(event, "揉揉", "蹭蹭") + } + + object 贴贴 extends ISimpleCommand { + override def getName: String = "贴贴" + override def getAliases: Array[String] = Array() + override def execute (command: InputCommand, event: Update): Unit = + replyingSet(event, "贴贴", "贴贴") + } + + object Progynova extends ITelegramCommand { + override def getName: String = "install" + override def getAliases: Array[String] = Array() + override def getParamRule: String = "" + override def getDescription: String = "抽取一个神秘盒子" + override def execute (command: InputCommand, event: Update): Unit = { + MornyCoeur.extra exec new SendSticker( + event.message.chat.id, + TelegramStickers ID_PROGYNOVA + ).replyToMessageId(event.message.messageId) + } + } + + private def replyingSet (event: Update, whileRec: String, whileNew: String): Unit = { + val isNew = event.message.replyToMessage == null; + val target = if (isNew) event.message else event.message.replyToMessage + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + if (isNew) whileNew else whileRec + ).replyToMessageId(target.messageId).parseMode(ParseMode HTML) + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/command/私わね.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/command/私わね.scala new file mode 100644 index 0000000..67da3f5 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/command/私わね.scala @@ -0,0 +1,26 @@ +package cc.sukazyo.cono.morny.bot.command + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.util.tgapi.InputCommand +import cc.sukazyo.cono.morny.util.CommonRandom.probabilityTrue +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.request.SendMessage + +object 私わね extends ISimpleCommand { + + override def getName: String = "me" + override def getAliases: Array[String] = Array() + + override def execute (command: InputCommand, event: Update): Unit = { + + if (probabilityTrue(521)) { + val text = "/打假" + MornyCoeur.extra exec new SendMessage( + event.message.chat.id, + text + ).replyToMessageId(event.message.messageId) + } + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnCallMe.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnCallMe.scala new file mode 100644 index 0000000..1f51e4d --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnCallMe.scala @@ -0,0 +1,90 @@ +package cc.sukazyo.cono.morny.bot.event + +import cc.sukazyo.cono.morny.Log.logger +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.bot.api.EventListener +import cc.sukazyo.cono.morny.data.TelegramStickers +import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.model.{Chat, Message, Update, User} +import com.pengrad.telegrambot.request.{ForwardMessage, GetChat, SendMessage, SendSticker} + +import scala.language.postfixOps + +object OnCallMe extends EventListener { + + private val me = MornyCoeur.config.trustedMaster + + override def onMessage (update: Update): Boolean = { + + if update.message.text == null then return false + if update.message.chat.`type` != (Chat.Type Private) then return false + + (update.message.text toLowerCase) match + case "steam" | "sbeam" | "sdeam" => + requestItem(update.message.from, "STEAM LIBRARY") + case "hana paresu" | "花宫" | "内群" => + requestItem(update.message.from, "Hana Paresu") + case "dinner" | "lunch" | "breakfast" | "meal" | "eating" | "安妮今天吃什么" => + requestLastDinner(update.message) + case cc if cc startsWith "cc::" => + requestCustom(update.message) + case _ => + return false + + MornyCoeur.extra exec SendSticker( + update.message.chat.id, + TelegramStickers ID_SENT + ).replyToMessageId(update.message.messageId) + true + + } + + private def requestItem (user: User, itemHTML: String, extra: String|Null = null): Unit = + MornyCoeur.extra exec SendMessage( + me, + s"""request $itemHTML + |from ${(TGToString as user) fullnameRefHtml}${if extra == null then "" else "\n"+extra}""" + .stripMargin + ).parseMode(ParseMode HTML) + + private def requestLastDinner (req: Message): Unit = { + var isAllowed = false + var lastDinnerData: Message|Null = null + if (MornyCoeur.trustedInstance isTrustedForDinnerRead req.from.id) { + lastDinnerData = (MornyCoeur.extra exec GetChat(MornyCoeur.config.dinnerChatId)).chat.pinnedMessage + val sendResp = MornyCoeur.extra exec ForwardMessage( + req.from.id, + lastDinnerData.forwardFromChat.id, + lastDinnerData.forwardFromMessageId + ) + import cc.sukazyo.cono.morny.util.CommonFormat.{formatDate, formatDuration} + import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h + def lastDinner_dateMillis: Long = lastDinnerData.forwardDate longValue; + MornyCoeur.extra exec SendMessage( + req.from.id, + "on %s [UTC+8]\n- %s before".formatted( + h(formatDate(lastDinner_dateMillis, 8)), + h(formatDuration(lastDinner_dateMillis)) + ) + ).parseMode(ParseMode HTML).replyToMessageId(sendResp.message.messageId) + isAllowed = true + } else { + MornyCoeur.extra exec SendSticker( + req.from.id, + TelegramStickers ID_403 + ).replyToMessageId(req.messageId) + } + import Math.abs + requestItem( + req.from, "Last Annie Dinner", + if isAllowed then s"Allowed and returned https://t.me/c/${abs(lastDinnerData.forwardFromChat.id+1000000000000L)}/${lastDinnerData.forwardFromMessageId}" + else "Forbidden by perm check." + ) + } + + private def requestCustom (message: Message): Unit = + requestItem(message.from, "[???]") + MornyCoeur.extra exec ForwardMessage(me, message.chat.id, message.messageId) + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnInlineQuery.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnInlineQuery.scala new file mode 100644 index 0000000..96f2ad0 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnInlineQuery.scala @@ -0,0 +1,37 @@ +package cc.sukazyo.cono.morny.bot.event + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.bot.api.{EventListener, InlineQueryUnit} +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.InlineQueryResult +import com.pengrad.telegrambot.request.AnswerInlineQuery + +import scala.collection.mutable.ListBuffer +import scala.language.postfixOps +import scala.reflect.ClassTag + +object OnInlineQuery extends EventListener { + + override def onInlineQuery (update: Update): Boolean = { + + val results: List[InlineQueryUnit[_]] = MornyCoeur.queryManager query update + + var cacheTime = Int.MaxValue + var isPersonal = InlineQueryUnit.DEFAULT_INLINE_PERSONAL_RESP + val resultAnswers = ListBuffer[InlineQueryResult[_]]() + for (r <- results) { + if (cacheTime > r.cacheTime) cacheTime = r.cacheTime + if (r isPersonal) isPersonal = true + resultAnswers += r.result + } + + if (results isEmpty) return false + + MornyCoeur.extra exec AnswerInlineQuery( + update.inlineQuery.id, resultAnswers toArray:_* + ).cacheTime(cacheTime).isPersonal(isPersonal) + true + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserRandom.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserRandom.scala new file mode 100644 index 0000000..2e21f63 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserRandom.scala @@ -0,0 +1,38 @@ +package cc.sukazyo.cono.morny.bot.event + +import cc.sukazyo.cono.morny.MornyCoeur +import cc.sukazyo.cono.morny.bot.api.EventListener +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.request.SendMessage + +import scala.language.postfixOps + +object OnUserRandom extends EventListener { + + private val USER_OR_QUERY = "(.+)(?:还是|or)(.+)"r + private val USER_IF_QUERY = "(.+)[吗?|?]+$"r + + override def onMessage(update: Update): Boolean = { + + if update.message.text == null then return false + if update.message.text startsWith "/" then return false + + import cc.sukazyo.cono.morny.util.CommonRandom.iif + val query = update.message.text substring 1 + val result: String|Null = query match + case USER_OR_QUERY(_con1, _con2) => + if iif then _con1 else _con2 + case USER_IF_QUERY(_con) => + (if iif then "不" else "") + _con + case _ => null + + if result == null then return false + + MornyCoeur.extra exec SendMessage( + update.message.chat.id, result + ).replyToMessageId(update.message.messageId) + true + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.scala new file mode 100644 index 0000000..1970726 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnUserSlashAction.scala @@ -0,0 +1,67 @@ +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.UniversalCommand +import cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml as h +import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.ParseMode +import com.pengrad.telegrambot.request.SendMessage + +import scala.language.postfixOps + +object OnUserSlashAction extends EventListener { + + private val TG_FORMAT = "^\\w+(@\\w+)?$"r + + override def onMessage (update: Update): Boolean = { + + val text = update.message.text; + if text == null then return false + + if (text startsWith "/") { + + val actions = UniversalCommand format text + actions(0) = actions(0) substring 1 + + actions(0) + + actions(0) match + case TG_FORMAT(_) => + return false + case x if x contains "/" => return false + + val isHardParse = actions(0) isBlank + def hp_len(i: Int) = if isHardParse then i+1 else i + if isHardParse && actions.length < 2 then return false + val v_verb = actions(hp_len(0)) + val hasObject = actions.length != hp_len(1) + val v_object = + if hasObject then + actions slice(hp_len(1), actions.length) mkString(" ") + else "" + val origin = update.message + val target = + if update.message.replyToMessage == null then + origin + else update.message.replyToMessage + + MornyCoeur.extra exec SendMessage( + update.message.chat.id, + "%s %s%s %s %s!".format( + (TGToString as origin) getSenderFirstNameRefHtml, + h(v_verb), if hasObject then "" else "了", + if (origin == target) + s"自己" + else (TGToString as target) getSenderFirstNameRefHtml, + if hasObject then h(v_object+" ") else "" + ) + ).parseMode(ParseMode HTML).replyToMessageId(update.message.messageId) + true + + } else false + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.scala new file mode 100644 index 0000000..d03a05c --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.scala @@ -0,0 +1,11 @@ +package cc.sukazyo.cono.morny.bot.query + +import javax.annotation.Nullable +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import com.pengrad.telegrambot.model.Update + +trait ITelegramQuery { + + def query (event: Update): List[InlineQueryUnit[_]] | Null + +} \ No newline at end of file diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/MornyQueries.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/MornyQueries.scala new file mode 100644 index 0000000..faeaefb --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/MornyQueries.scala @@ -0,0 +1,27 @@ +package cc.sukazyo.cono.morny.bot.query + +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import cc.sukazyo.cono.morny.bot.query +import com.pengrad.telegrambot.model.Update + +import scala.collection.mutable.ListBuffer + +class MornyQueries { + + private val queryInstances = Set[ITelegramQuery]( + RawText, + MyInformation, + ShareToolTwitter, + ShareToolBilibili + ) + + def query (event: Update): List[InlineQueryUnit[_]] = { + val results = ListBuffer[InlineQueryUnit[_]]() + for (instance <- queryInstances) { + val r = instance query event + if (r != null) results ++= r + } + results.result() + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/MyInformation.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/MyInformation.scala new file mode 100644 index 0000000..c98feb6 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/MyInformation.scala @@ -0,0 +1,31 @@ +package cc.sukazyo.cono.morny.bot.query + +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds +import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTextMessageContent, ParseMode} + +import scala.language.postfixOps + +object MyInformation extends ITelegramQuery { + + private val ID_PREFIX = "[morny/info/me]" + private val TITLE = "My Account Information" + + override def query (event: Update): List[InlineQueryUnit[_]] | Null = { + + if (event.inlineQuery.query == null || (event.inlineQuery.query isBlank)) return null + + List( + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX), TITLE, + new InputTextMessageContent( + TelegramUserInformation informationOutputHTML event.inlineQuery.from + ).parseMode(ParseMode HTML) + )).isPersonal(true).cacheTime(10) + ) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/RawText.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/RawText.scala new file mode 100644 index 0000000..2d19149 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/RawText.scala @@ -0,0 +1,27 @@ +package cc.sukazyo.cono.morny.bot.query +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTextMessageContent} + +import scala.language.postfixOps + +object RawText extends ITelegramQuery { + + private val ID_PREFIX = "[morny/r/text]" + private val TITLE = "Raw Text" + + override def query (event: Update): List[InlineQueryUnit[_]] | Null = { + + if (event.inlineQuery.query == null || (event.inlineQuery.query isBlank)) return null + + List( + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX, event.inlineQuery.query), TITLE, + InputTextMessageContent(event.inlineQuery.query) + )) + ) + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.scala new file mode 100644 index 0000000..90288e2 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolBilibili.scala @@ -0,0 +1,77 @@ +package cc.sukazyo.cono.morny.bot.query + +import cc.sukazyo.cono.morny.Log.logger +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import cc.sukazyo.cono.morny.util.BiliTool +import cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTextMessageContent, ParseMode} + +import scala.language.postfixOps +import scala.util.matching.Regex + +object ShareToolBilibili extends ITelegramQuery { + + private val TITLE_BILI_AV = "[bilibili] Share video / av" + private val TITLE_BILI_BV = "[bilibili] Share video / BV" + private val ID_PREFIX_BILI_AV = "[morny/share/bili/av]" + private val ID_PREFIX_BILI_BV = "[morny/share/bili/bv]" + private val LINK_PREFIX = "https://bilibili.com/video/" + private val REGEX_BILI_VIDEO: Regex = "^(?:(?:https?://)?(?:www\\.)?bilibili\\.com(?:/s)?/video/((?:av|AV)(\\d{1,12})|(?:bv|BV)([A-HJ-NP-Za-km-z1-9]{10}))/?(\\?(?:p=(\\d+))?.*)?|(?:av|AV)(\\d{1,12})|(?:bv|BV)([A-HJ-NP-Za-km-z1-9]{10}))$"r + private val SHARE_FORMAT_HTML = "%s" + + override def query (event: Update): List[InlineQueryUnit[_]] | Null = { + + if (event.inlineQuery.query == null) return null + + event.inlineQuery.query match + case REGEX_BILI_VIDEO(_1, _2, _3, _4, _5, _6, _7) => + + logger debug + s"""====== Share Tool Bilibili Catch ok + |1: ${_1} + |2: ${_2} + |3: ${_3} + |4: ${_4} + |5: ${_5} + |6: ${_6} + |7: ${_7}""" + .stripMargin + + var av = if (_2 != null) _2 else if (_6 != null) _6 else null + var bv = if (_3!=null) _3 else if (_7!=null) _7 else null + logger trace s"catch id av[$av] bv[$bv]" + val part: Int|Null = if (_5!=null) _5 toInt else null + logger trace s"catch video part[$part]" + + if (av == null) { + assert (bv != null) + av = BiliTool.toAv(bv) toString; + logger trace s"converted bv[$av] to av[$av]" + } else { + bv = BiliTool.toBv(av toLong) + logger trace s"converted av[$av] to bv[$bv]" + } + + val id_av = s"av$av" + val id_bv = s"BV$bv" + val linkParams = if (part!=null) s"?p=$part" else "" + val link_av = LINK_PREFIX + id_av + linkParams + val link_bv = LINK_PREFIX + id_bv + linkParams + + List( + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX_BILI_AV+av), TITLE_BILI_AV+av, + InputTextMessageContent(SHARE_FORMAT_HTML.format(link_av, id_av)).parseMode(ParseMode HTML) + )), + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX_BILI_BV + bv), TITLE_BILI_BV + bv, + InputTextMessageContent(SHARE_FORMAT_HTML.format(link_bv, id_bv)).parseMode(ParseMode HTML) + )) + ) + + case _ => null + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala new file mode 100644 index 0000000..9427dca --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala @@ -0,0 +1,42 @@ +package cc.sukazyo.cono.morny.bot.query + +import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit +import com.pengrad.telegrambot.model.Update +import com.pengrad.telegrambot.model.request.InlineQueryResultArticle + +import cc.sukazyo.cono.morny.util.tgapi.formatting.NamedUtils.inlineIds + +import scala.language.postfixOps +import scala.util.matching.Regex + +object ShareToolTwitter extends ITelegramQuery { + + val TITLE_VX = "[tweet] Share as VxTwitter" + val TITLE_VX_COMBINED = "[tweet] Share as VxTwitter(combination)" + val ID_PREFIX_VX = "[morny/share/twitter/vxtwi]" + val ID_PREFIX_VX_COMBINED = "[morny/share/twitter/vxtwi_combine]" + val REGEX_TWEET_LINK: Regex = "^(?:https?://)?((?:(?:c\\.)?vx|fx|www\\.)?twitter\\.com)/((\\w+)/status/(\\d+)(?:/photo/(\\d+))?)/?(\\?[\\w&=-]+)?$"r + + override def query (event: Update): List[InlineQueryUnit[_]] | Null = { + + if (event.inlineQuery.query == null) return null + + event.inlineQuery.query match + + case REGEX_TWEET_LINK(_1, _2, _) => + List( + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX_VX+event.inlineQuery.query), TITLE_VX, + s"https://vxtwitter.com/$_2" + )), + InlineQueryUnit(InlineQueryResultArticle( + inlineIds(ID_PREFIX_VX_COMBINED+event.inlineQuery.query), TITLE_VX_COMBINED, + s"https://c.vxtwitter.com/$_2" + )) + ) + + case _ => null + + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.scala b/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.scala new file mode 100644 index 0000000..65abaca --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.scala @@ -0,0 +1,41 @@ +package cc.sukazyo.cono.morny.data.ip186 + +import okhttp3.{OkHttpClient, Request} + +import java.io.IOException +import scala.language.postfixOps +import scala.util.Using + +object IP186QueryHandler { + + private val SITE_URL = "https://ip.186526.xyz/" + private val QUERY_PARAM_IP = "type=json&format=true" + private val QUERY_PARAM_WHOIS = "type=plain" + + private val httpClient = OkHttpClient() + + @throws[IOException] + def query_ip (ip: String): IP186Response = + commonQuery(SITE_URL + ip, QUERY_PARAM_IP) + + @throws[IOException] + def query_whois (domain: String): IP186Response = + commonQuery(SITE_URL+"whois/"+domain, QUERY_PARAM_WHOIS) + + @throws[IOException] + def query_whoisPretty (domain: String): IP186Response = + val raw = query_whois(domain) + IP186Response(raw.url, raw.body substring(0, (raw.body indexOf "<<<")+3)) + + @throws[IOException] + private def commonQuery (requestUrl: String, queryParam: String): IP186Response = { + val request = Request.Builder().url(requestUrl + "?" + queryParam).build + var _body_string: String|Null = null + Using ((httpClient newCall request) execute) { response => + if response.body ne null then _body_string = response.body.string + } + if _body_string eq null then throw IOException("Response of ip186: body is empty!") + IP186Response(requestUrl, _body_string) + } + +} diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186Response.scala b/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186Response.scala new file mode 100644 index 0000000..6fcad79 --- /dev/null +++ b/src/main/scala/cc/sukazyo/cono/morny/data/ip186/IP186Response.scala @@ -0,0 +1,3 @@ +package cc.sukazyo.cono.morny.data.ip186 + +case class IP186Response (url: String, body: String)