mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-25 12:37:39 +08:00
scala port stage1 (not tested)
This commit is contained in:
parent
213798dab7
commit
aafdcc1fb2
@ -10,6 +10,8 @@
|
|||||||
#build
|
#build
|
||||||
/build/
|
/build/
|
||||||
/bin/
|
/bin/
|
||||||
|
.metals/
|
||||||
|
.bloop/
|
||||||
.project
|
.project
|
||||||
lcoal.properties
|
lcoal.properties
|
||||||
|
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,6 +10,8 @@
|
|||||||
#build
|
#build
|
||||||
/build/
|
/build/
|
||||||
/bin/
|
/bin/
|
||||||
|
.metals/
|
||||||
|
.bloop/
|
||||||
.project
|
.project
|
||||||
lcoal.properties
|
lcoal.properties
|
||||||
|
|
||||||
|
56
build.gradle
56
build.gradle
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'scala'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'maven-publish'
|
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 JavaVersion proj_java = JavaVersion.VERSION_17
|
||||||
final Charset proj_file_encoding = StandardCharsets.UTF_8
|
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_local_url = null
|
||||||
String publish_remote_url = null
|
String publish_remote_url = null
|
||||||
String publish_remote_username = null
|
String publish_remote_username = null
|
||||||
@ -72,6 +74,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
|
api "org.scala-lang:scala3-library_3:${proj_scala_lib}"
|
||||||
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}"
|
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}"
|
||||||
|
|
||||||
implementation "cc.sukazyo:messiva:${lib_messiva_v}"
|
implementation "cc.sukazyo:messiva:${lib_messiva_v}"
|
||||||
@ -86,8 +89,30 @@ dependencies {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
sourceSets {
|
||||||
mainClass = proj_application_main
|
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 {
|
test {
|
||||||
@ -97,27 +122,8 @@ test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
application {
|
||||||
|
mainClass = proj_application_main
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildConfig {
|
buildConfig {
|
||||||
|
@ -7,8 +7,8 @@ MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
|
|||||||
|
|
||||||
VERSION = 1.0.0-RC4
|
VERSION = 1.0.0-RC4
|
||||||
|
|
||||||
USE_DELTA = false
|
USE_DELTA = true
|
||||||
VERSION_DELTA =
|
VERSION_DELTA = scalaport1
|
||||||
|
|
||||||
CODENAME = beiping
|
CODENAME = beiping
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 程序启动入口<br>
|
|
||||||
* <br>
|
|
||||||
* 会处理程序传入的参数和选项等数据,并执行对应的启动方式<br>
|
|
||||||
*
|
|
||||||
* @since 0.4.0.0
|
|
||||||
*/
|
|
||||||
public class ServerMain {
|
|
||||||
|
|
||||||
public static final long systemStartupTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
private static final String THREAD_MORNY_INIT = "morny-init";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 程序入口,也是参数处理器<br>
|
|
||||||
* <br>
|
|
||||||
* 以 {@code -} 开头的参数会被解析为选项<br>
|
|
||||||
* <br>
|
|
||||||
* 支持以下选项
|
|
||||||
* <ul>
|
|
||||||
* <li>
|
|
||||||
* {@code --version} 只输出版本信息,不运行主程序。此参数会导致其它所有参数失效(优先级最高)
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --only-hello} 只输出欢迎字符画({@link MornyAbout#MORNY_PREVIEW_IMAGE_ASCII}),不运行主程序。
|
|
||||||
* 不要同时使用 {@code --no-hello},原因见下。
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --token} <b>主程序模式的必选项</b><br>
|
|
||||||
* 用于 bot 启动的 telegram bot api token
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --username} {@link MornyCoeur#getUsername() bot 的 username} 预定义
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --api} 设定 {@link MornyCoeur#getAccount() bot client} 使用的 telegram bot api server。
|
|
||||||
* 需要注意的是如果带有后缀 {@code /bot} 则会单独设定 api server
|
|
||||||
* 而不会适应性的同时为 {@code --api-files} 设定值。
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --api-files} 单独设定 {@link MornyCoeur#getAccount() bot client} 使用的 telegram bot file api server
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --report-to} 设定 {@link cc.sukazyo.cono.morny.daemon.MornyReport} 的运行报告要发送到的 telegram 频道
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --no-hello} 不在主程序启动时输出用于欢迎消息的字符画。
|
|
||||||
* 与 {@code --only-hello} 参数不兼容 —— 会导致程序完全没有任何输出
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --outdated-block} 会使得 {@link MornyConfig#eventIgnoreOutdated}
|
|
||||||
* 赋值为程序启动的时间,从而造成阻挡程序启动之前的消息事件处理效果。
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --auto-cmd} (下面两个)选项 {@code --auto-cmd-list} 和 {@code --auto-cmd-remove} 的合并版本
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --auto-cmd-list} 使 morny 在启动时自动依据程序本体更新登录 bot 的命令列表
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* {@code --auto-cmd-remove} 使 morny 在关闭时自动依据程序本体删除 bot 的命令列表
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
* <s>除去选项之外,第一个参数会被赋值为 bot 的 telegram bot api token,</s>
|
|
||||||
* <s>第二个参数会被赋值为 bot 的 username 限定名。其余的参数会被认定为无法理解。</s><br>
|
|
||||||
* <b>自 {@code 0.4.2.3},token 和 username 的赋值已被选项组支持</b><br>
|
|
||||||
* <b>自 {@code 0.5.0.4},旧的直接通过参数为 bot token & username 赋值的方式已被删除</b>
|
|
||||||
* 使用参数所进行取值的 token 和 username 已被转移至 {@code --token} 和 {@code --username} 参数<br>
|
|
||||||
*
|
|
||||||
* @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<String> 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
|
|
||||||
)) : "<non-git-build>",
|
|
||||||
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 <token> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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(), """
|
|
||||||
<b><u>base64</u></b>, b64
|
|
||||||
<b><u>base64url</u></b>, base64u, b64u
|
|
||||||
<b><u>base64decode</u></b>, base64d, b64d
|
|
||||||
<b><u>base64url-decode</u></b>, base64ud, b64ud
|
|
||||||
<b><u>sha1</u></b>
|
|
||||||
<b><u>sha256</u></b>
|
|
||||||
<b><u>sha512</u></b>
|
|
||||||
<b><u>md5</u></b>
|
|
||||||
---
|
|
||||||
<b><i>uppercase</i></b>, upper, u <i>(sha1/sha256/sha512/md5 only)</i>
|
|
||||||
"""
|
|
||||||
).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(),
|
|
||||||
"<i><u>null</u></i>"
|
|
||||||
).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(),
|
|
||||||
"<pre><code>" + MsgEscape.escapeHtml(resultString) + "</code></pre>"
|
|
||||||
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
|
|
||||||
} else {
|
|
||||||
MornyCoeur.extra().exec(new SendDocument(
|
|
||||||
event.message().chat().id(),
|
|
||||||
result
|
|
||||||
).fileName(resultName).replyToMessageId(event.message().messageId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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} 的命令行前端<br>
|
|
||||||
* <br>
|
|
||||||
* 实现了通过命令行进行 EventHack 功能。<br>
|
|
||||||
* 支持三种模式,默认为 {@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())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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(),
|
|
||||||
"<code>$__channel_identify</code>"
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MornyCoeur.extra().exec(new SendMessage(
|
|
||||||
event.message().chat().id(),
|
|
||||||
TelegramUserInformation.informationOutputHTML(user)
|
|
||||||
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<code>" + escapeHtml(response.body()) + "</code>"
|
|
||||||
).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
MornyCoeur.extra().exec(new SendMessage(
|
|
||||||
event.message().chat().id(),
|
|
||||||
"[Exception] in query:\n<code>" + escapeHtml(e.getMessage()) + "</code>"
|
|
||||||
).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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("""
|
|
||||||
欢迎使用 <b>Morny Cono</b>,<i>来自安妮的侍从小鼠</i>。
|
|
||||||
Morny 具有各种各样的功能。
|
|
||||||
|
|
||||||
————————————————
|
|
||||||
%s
|
|
||||||
————————————————
|
|
||||||
|
|
||||||
(你可以随时通过 /info 重新获得这些信息)""".formatted(MornyInformation.getMornyAboutLinksHTML())
|
|
||||||
).parseMode(ParseMode.HTML));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 <u>/info</u> without params.
|
|
||||||
*
|
|
||||||
* @since 1.0.0-RC4
|
|
||||||
*/
|
|
||||||
public void echoInfo (long chatId, int replayToMessage) {
|
|
||||||
MornyCoeur.extra().exec(new SendPhoto(
|
|
||||||
chatId,
|
|
||||||
getAboutPic()
|
|
||||||
).caption("""
|
|
||||||
<b>Morny Cono</b>
|
|
||||||
来自安妮的侍从小鼠。
|
|
||||||
————————————————
|
|
||||||
%s""".formatted(getMornyAboutLinksHTML())
|
|
||||||
).parseMode(ParseMode.HTML).replyToMessageId(replayToMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* subcommand <u>/info stickers</u>
|
|
||||||
*
|
|
||||||
* @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 <u>/info runtime</u>.
|
|
||||||
*
|
|
||||||
* @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:
|
|
||||||
- <code>%s</code>
|
|
||||||
- <code>%s</code> (<code>%s</code>) <code>%s</code>
|
|
||||||
java runtime:
|
|
||||||
- <code>%s</code>
|
|
||||||
- <code>%s</code>
|
|
||||||
vm memory:
|
|
||||||
- <code>%d</code> / <code>%d</code> MB
|
|
||||||
- <code>%d</code> cores
|
|
||||||
coeur version:
|
|
||||||
- %s
|
|
||||||
- <code>%s</code>
|
|
||||||
- <code>%s [UTC]</code>
|
|
||||||
- [<code>%d</code>]
|
|
||||||
continuous:
|
|
||||||
- <code>%s</code>
|
|
||||||
- [<code>%d</code>]
|
|
||||||
- <code>%s [UTC]</code>
|
|
||||||
- [<code>%d</code>]""",
|
|
||||||
// system
|
|
||||||
escapeHtml(getRuntimeHostName()==null ? "<unknown-host>" : 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 <u>/info version</u> or <u>/info v</u>.
|
|
||||||
*
|
|
||||||
* @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 <code>%s</code>
|
|
||||||
- <code>%s</code>%s%s
|
|
||||||
core md5_hash:
|
|
||||||
- <code>%s</code>
|
|
||||||
coding timestamp:
|
|
||||||
- <code>%d</code>
|
|
||||||
- <code>%s [UTC]</code>""",
|
|
||||||
escapeHtml(MornySystem.CODENAME.toUpperCase()),
|
|
||||||
escapeHtml(MornySystem.VERSION_BASE),
|
|
||||||
MornySystem.isUseDelta() ? String.format("-δ<code>%s</code>", 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 格式类似于 <u>{@code 28e8c82a.δ}</u> 的以 HTML 方式格式化的版本号组件。
|
|
||||||
* 其中 {@code .δ} 对应着 {@link MornySystem#isCleanBuild};
|
|
||||||
* commit tag 字段如果支援 {@link MornySystem#currentCodePath} 则会以链接形式解析,否则则为 code 格式
|
|
||||||
* <small>为了对 telegram api html 格式兼容所以不支援嵌套链接与code标签</small>。
|
|
||||||
* 如果 {@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("<code>%s</code>", BuildConfig.COMMIT.substring(0, 8)));
|
|
||||||
else g.append(String.format("<a href='%s'>%s</a>", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8)));
|
|
||||||
if (!MornySystem.isCleanBuild()) g.append(".<code>δ</code>");
|
|
||||||
return g.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取得完整 Morny 版本的 HTML 格式化标签.
|
|
||||||
* <p>
|
|
||||||
* 相比于 {@link MornySystem#VERSION_FULL},这个版本号还包含了 {@link MornySystem#CODENAME 版本 codename}。
|
|
||||||
* 各个部分也被以 HTML 的格式进行了格式化以可以更好的在富文本中插入使用.
|
|
||||||
* @return 基于 HTML 标签进行了格式化了的类似于
|
|
||||||
* <u><code>{@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}</code></u>
|
|
||||||
* 的版本号。
|
|
||||||
* @since 1.0.0-beta2
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static String getVersionAllFullTagHtml () {
|
|
||||||
final StringBuilder v = new StringBuilder();
|
|
||||||
v.append("<code>").append(MornySystem.VERSION_BASE).append("</code>");
|
|
||||||
if (MornySystem.isUseDelta()) v.append("-δ<code>").append(MornySystem.VERSION_DELTA).append("</code>");
|
|
||||||
if (MornySystem.isGitBuild()) v.append("+git.").append(getVersionGitTagHtml());
|
|
||||||
v.append("*<code>").append(MornySystem.CODENAME.toUpperCase()).append("</code>");
|
|
||||||
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.
|
|
||||||
* <p>
|
|
||||||
* With the Telegram HTML formatting, used in <u>/info</u> and <u>/start</u>.
|
|
||||||
* Provided the end user the links that can find resources about Morny.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static String getMornyAboutLinksHTML () {
|
|
||||||
return """
|
|
||||||
<a href='%s'>source code</a> | <a href='%s'>backup</a>
|
|
||||||
<a href='%s'>反馈 / issue tracker</a>
|
|
||||||
<a href='%s'>使用说明书 / user guide & docs</a>""".formatted(
|
|
||||||
MornyAbout.MORNY_SOURCECODE_LINK, MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK,
|
|
||||||
MornyAbout.MORNY_ISSUE_TRACKER_LINK,
|
|
||||||
MornyAbout.MORNY_USER_GUIDE_LINK
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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("<a href=\"https://lab.magiconch.com/nbnhhsh/\">## Result of nbnhhsh query :</a>");
|
|
||||||
|
|
||||||
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<b>[[ ").append(escapeHtml(word.name)).append(" ]]</b>");
|
|
||||||
if (word.trans != null) for (String trans : word.trans) {
|
|
||||||
message.append("\n* <i>").append(escapeHtml(trans)).append("</i>");
|
|
||||||
}
|
|
||||||
if (word.inputting != null) {
|
|
||||||
if (word.trans != null) message.append("\n");
|
|
||||||
message.append(" maybe:");
|
|
||||||
for (String trans : word.inputting) {
|
|
||||||
message.append("\n` <i>").append(escapeHtml(trans)).append("</i>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<code>" + escapeHtml(e.getMessage()) + "</code>"
|
|
||||||
).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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(),
|
|
||||||
"<b>Just</b> a TEST command."
|
|
||||||
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>WARNING</b> that {@link cc.sukazyo.cono.morny.bot.event.OnTelegramCommand}
|
|
||||||
* 并不能够处理非 english word 字符之外的命令.
|
|
||||||
* <p>
|
|
||||||
* 出于这个限制,以下几个命令目前都无法使用
|
|
||||||
* @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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<br>
|
|
||||||
* 跟随 {@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 事件基础返回值,是否已完成处理事件:<br>
|
|
||||||
* 如果匹配到呼叫,则返回{@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 呼叫<br>
|
|
||||||
* 将会向 {@link #ME} 发送
|
|
||||||
*
|
|
||||||
* @param event 执行呼叫的tg事件
|
|
||||||
*/
|
|
||||||
private static void requestSteamJoin (Update event) {
|
|
||||||
MornyCoeur.extra().exec(new SendMessage(
|
|
||||||
ME, String.format(
|
|
||||||
"""
|
|
||||||
request <b>STEAM LIBRARY</b>
|
|
||||||
from %s""",
|
|
||||||
TGToString.as(event.message().from()).fullnameRefHtml()
|
|
||||||
)
|
|
||||||
).parseMode(ParseMode.HTML));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行花宫呼叫<br>
|
|
||||||
* 将会向 {@link #ME} 发送
|
|
||||||
*
|
|
||||||
* @param event 执行呼叫的tg事件
|
|
||||||
*/
|
|
||||||
private static void requestHanaParesuJoin (Update event) {
|
|
||||||
MornyCoeur.extra().exec(new SendMessage(
|
|
||||||
ME, String.format(
|
|
||||||
"""
|
|
||||||
request <b>Hana Paresu</b>
|
|
||||||
from %s""",
|
|
||||||
TGToString.as(event.message().from()).fullnameRefHtml()
|
|
||||||
)
|
|
||||||
).parseMode(ParseMode.HTML));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对访问最近一次的饭局的请求进行回复<br>
|
|
||||||
*
|
|
||||||
* @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("<i>on</i> <code>%s [UTC+8]</code>\n- <code>%s</code> <i>before</i>",
|
|
||||||
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 <b>Last Annie Dinner</b>
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行自定义呼叫<br>
|
|
||||||
* 将会向 {@link #ME} 发送一个 request 数据消息和转发的原始请求消息<br>
|
|
||||||
* <br>
|
|
||||||
* <u>known issue</u><ul>
|
|
||||||
* <li>无法处理与转发带有媒体的消息</li>
|
|
||||||
* </ul>
|
|
||||||
* <br>
|
|
||||||
* 现在你可以通过这个 bot 来呼叫主人(sukazyo)任何事情了 ——
|
|
||||||
* <s>但是直接私聊sukazyo不好吗</s>
|
|
||||||
*
|
|
||||||
* @param event 执行呼叫的tg事件
|
|
||||||
* @since 0.4.2.2
|
|
||||||
*/
|
|
||||||
private static void requestCustomCall (Update event) {
|
|
||||||
MornyCoeur.extra().exec(new SendMessage(
|
|
||||||
ME, String.format(
|
|
||||||
"""
|
|
||||||
request <u>[???]</u>
|
|
||||||
from %s""",
|
|
||||||
TGToString.as(event.message().from()).fullnameRefHtml()
|
|
||||||
)
|
|
||||||
).parseMode(ParseMode.HTML));
|
|
||||||
MornyCoeur.extra().exec(new ForwardMessage(
|
|
||||||
ME,
|
|
||||||
event.message().chat().id(),
|
|
||||||
event.message().messageId()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<InlineQueryUnit<?>> 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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 ?
|
|
||||||
"<a href='tg://user?id="+TGToString.as(target).getSenderId()+"'>自己</a>" :
|
|
||||||
TGToString.as(target).getSenderFirstNameRefHtml(),
|
|
||||||
escapeHtml(hasObject ? object+" " : "")
|
|
||||||
)
|
|
||||||
).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId()));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<InlineQueryUnit<?>> query (Update event);
|
|
||||||
|
|
||||||
}
|
|
@ -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<ITelegramQuery> queryInstances = new ArrayList<>();
|
|
||||||
|
|
||||||
public MornyQueries () {
|
|
||||||
queryInstances.add(new RawText());
|
|
||||||
queryInstances.add(new MyInformation());
|
|
||||||
queryInstances.add(new ShareToolTwitter());
|
|
||||||
queryInstances.add(new ShareToolBilibili());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public List<InlineQueryUnit<?>> query (@Nonnull Update event) {
|
|
||||||
final List<InlineQueryUnit<?>> results = new ArrayList<>();
|
|
||||||
for (ITelegramQuery instance : queryInstances) {
|
|
||||||
final List<InlineQueryUnit<?>> r = instance.query(event);
|
|
||||||
if (r!=null) results.addAll(r);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<InlineQueryUnit<?>> 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<InlineQueryUnit<?>> 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())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 = "<a href='%s'>%s</a>";
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public List<InlineQueryUnit<?>> 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<InlineQueryUnit<?>> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<InlineQueryUnit<?>> 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<InlineQueryUnit<?>> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 参数.<br>
|
|
||||||
* 目的使 API 直接返回原始数据
|
|
||||||
*/
|
|
||||||
private static final String QUERY_IP_PARAM = "type=json&format=true";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 进行 {@link #queryWhois whois 查询}时所使用的 API 参数.<br>
|
|
||||||
* 目的使 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)} 的结果进行裁剪.
|
|
||||||
* <br>
|
|
||||||
* 将会删除返回内容中 {@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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package cc.sukazyo.cono.morny.data.ip186;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link IP186QueryHandler} 的请求结果数据的通用封装类.
|
|
||||||
*
|
|
||||||
* @since 0.4.2.10
|
|
||||||
* @param url 请求数据的<u>人类可读的</u>来源链接,<b>并非api链接</b>
|
|
||||||
* @param body API 传回的数据内容
|
|
||||||
*/
|
|
||||||
public record IP186QueryResponse(String url, String body) {
|
|
||||||
}
|
|
@ -58,7 +58,7 @@ public class MornyCoeur {
|
|||||||
* morny 主程序启动时间<br>
|
* morny 主程序启动时间<br>
|
||||||
* 用于统计数据
|
* 用于统计数据
|
||||||
*/
|
*/
|
||||||
public static final long coeurStartTimestamp = ServerMain.systemStartupTime;
|
public static final long coeurStartTimestamp = ServerMain.systemStartupTime();
|
||||||
|
|
||||||
private Object whileExitReason = null;
|
private Object whileExitReason = null;
|
||||||
|
|
@ -55,15 +55,15 @@ public class MornyCommands {
|
|||||||
register(
|
register(
|
||||||
new ON(),
|
new ON(),
|
||||||
new Hello(), /* new {@link HelloOnStart}, */
|
new Hello(), /* new {@link HelloOnStart}, */
|
||||||
new MornyInfoOnHello(),
|
MornyInformation$.MODULE$,
|
||||||
new GetUsernameAndId(),
|
GetUsernameAndId$.MODULE$,
|
||||||
new EventHack(),
|
EventHack$.MODULE$,
|
||||||
new Nbnhhsh(),
|
Nbnhhsh$.MODULE$,
|
||||||
new Ip186Query.Ip(),
|
IP186Query.IP$.MODULE$,
|
||||||
new Ip186Query.Whois(),
|
IP186Query.Whois$.MODULE$,
|
||||||
new Encryptor(),
|
Encryptor$.MODULE$,
|
||||||
new SaveData(),
|
new SaveData(),
|
||||||
new MornyInformation(),
|
MornyInfoOnHello$.MODULE$,
|
||||||
new Version(),
|
new Version(),
|
||||||
new MornyRuntime(),
|
new MornyRuntime(),
|
||||||
new Jrrp(),
|
new Jrrp(),
|
||||||
@ -72,21 +72,21 @@ public class MornyCommands {
|
|||||||
|
|
||||||
// 特殊的命令
|
// 特殊的命令
|
||||||
register(
|
register(
|
||||||
new Testing(),
|
Testing$.MODULE$,
|
||||||
new DirectMsgClear()
|
DirectMsgClear$.MODULE$
|
||||||
);
|
);
|
||||||
|
|
||||||
// 统一注册这些奇怪的东西&.&
|
// 统一注册这些奇怪的东西&.&
|
||||||
register(
|
register(
|
||||||
new 私わね(),
|
私わね$.MODULE$,
|
||||||
new 喵呜.Progynova()
|
喵呜.Progynova$.MODULE$
|
||||||
);
|
);
|
||||||
// special: 注册出于兼容使用的特别 event 的数据
|
// special: 注册出于兼容使用的特别 event 的数据
|
||||||
OnUniMeowTrigger.register(
|
OnUniMeowTrigger.register(
|
||||||
new 喵呜.抱抱(),
|
喵呜.抱抱$.MODULE$,
|
||||||
new 喵呜.揉揉(),
|
喵呜.揉揉$.MODULE$,
|
||||||
new 喵呜.蹭蹭(),
|
喵呜.蹭蹭$.MODULE$,
|
||||||
new 喵呜.贴贴()
|
喵呜.贴贴$.MODULE$
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
@ -1,18 +1,15 @@
|
|||||||
package cc.sukazyo.cono.morny.bot.event;
|
package cc.sukazyo.cono.morny.bot.event;
|
||||||
|
|
||||||
import cc.sukazyo.cono.morny.bot.api.EventListenerManager;
|
import cc.sukazyo.cono.morny.bot.api.EventListenerManager;
|
||||||
|
import cc.sukazyo.cono.morny.bot.api.InlineQueryUnit;
|
||||||
|
|
||||||
public class EventListeners {
|
public class EventListeners {
|
||||||
|
|
||||||
public static final OnTelegramCommand COMMANDS_LISTENER = new OnTelegramCommand();
|
public static final OnTelegramCommand COMMANDS_LISTENER = new OnTelegramCommand();
|
||||||
// public static final OnActivityRecord ACTIVITY_RECORDER = new OnActivityRecord();
|
// 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 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();
|
public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle();
|
||||||
// static final OnKuohuanhuanNeedSleep KUOHUANHUAN_NEED_SLEEP = new OnKuohuanhuanNeedSleep();
|
// 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 OnCallMsgSend CALL_MSG_SEND = new OnCallMsgSend();
|
||||||
public static final OnMedicationNotifyApply MEDICATION_NOTIFY_APPLY = new OnMedicationNotifyApply();
|
public static final OnMedicationNotifyApply MEDICATION_NOTIFY_APPLY = new OnMedicationNotifyApply();
|
||||||
public static final OnRandomlyTriggered RANDOMLY_TRIGGERED = new OnRandomlyTriggered();
|
public static final OnRandomlyTriggered RANDOMLY_TRIGGERED = new OnRandomlyTriggered();
|
||||||
@ -28,11 +25,11 @@ public class EventListeners {
|
|||||||
COMMANDS_LISTENER,
|
COMMANDS_LISTENER,
|
||||||
UNI_MEOW_TRIGGER,
|
UNI_MEOW_TRIGGER,
|
||||||
RANDOMLY_TRIGGERED,
|
RANDOMLY_TRIGGERED,
|
||||||
USER_RANDOMS,
|
OnUserRandom$.MODULE$,
|
||||||
QUESTION_MARK_REPLY,
|
QUESTION_MARK_REPLY,
|
||||||
USER_SLASH_ACTION,
|
OnUserSlashAction$.MODULE$,
|
||||||
INLINE_QUERY,
|
OnInlineQuery$.MODULE$,
|
||||||
CALL_ME,
|
OnCallMe$.MODULE$,
|
||||||
CALL_MSG_SEND,
|
CALL_MSG_SEND,
|
||||||
MEDICATION_NOTIFY_APPLY,
|
MEDICATION_NOTIFY_APPLY,
|
||||||
EVENT_HACK_HANDLE
|
EVENT_HACK_HANDLE
|
@ -88,7 +88,7 @@ public class MornyReport {
|
|||||||
as config fields:
|
as config fields:
|
||||||
%s
|
%s
|
||||||
""",
|
""",
|
||||||
MornyInformation.getVersionAllFullTagHtml(),
|
MornyInformation.getVersionAllFullTagHTML(),
|
||||||
MornyCoeur.getUsername(),
|
MornyCoeur.getUsername(),
|
||||||
sectionConfigFields(MornyCoeur.config())
|
sectionConfigFields(MornyCoeur.config())
|
||||||
)
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
package cc.sukazyo.cono.morny.util.tgapi;
|
||||||
|
|
||||||
|
public class Standardize {
|
||||||
|
|
||||||
|
public static final int CHANNEL_SPEAKER_MAGIC_ID = 136817688;
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.util.tgapi.formatting;
|
package cc.sukazyo.cono.morny.util.tgapi.formatting;
|
||||||
|
|
||||||
import com.pengrad.telegrambot.model.Chat;
|
import com.pengrad.telegrambot.model.Chat;
|
||||||
|
import com.pengrad.telegrambot.model.Message;
|
||||||
|
|
||||||
public class TGToStringFromChat {
|
public class TGToStringFromChat {
|
||||||
|
|
156
src/main/scala/cc/sukazyo/cono/morny/ServerMain.scala
Normal file
156
src/main/scala/cc/sukazyo/cono/morny/ServerMain.scala
Normal file
@ -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 " <non-git-build>"}
|
||||||
|
|- 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 <token> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
178
src/main/scala/cc/sukazyo/cono/morny/bot/command/Encryptor.scala
Normal file
178
src/main/scala/cc/sukazyo/cono/morny/bot/command/Encryptor.scala
Normal file
@ -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,
|
||||||
|
"<i><u>null</u></i>"
|
||||||
|
).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"<pre><code>${h(_text.text)}</code></pre>"
|
||||||
|
).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private def echoHelp(chat: Long, replyTo: Int): Unit =
|
||||||
|
MornyCoeur.extra exec SendMessage(
|
||||||
|
chat,
|
||||||
|
s"""<b><u>base64</u></b>, b64
|
||||||
|
|<b><u>base64url</u></b>, base64u, b64u
|
||||||
|
|<b><u>base64decode</u></b>, base64d, b64d
|
||||||
|
|<b><u>base64url-decode</u></b>, base64ud, b64ud
|
||||||
|
|<b><u>sha1</u></b>
|
||||||
|
|<b><u>sha256</u></b>
|
||||||
|
|<b><u>sha512</u></b>
|
||||||
|
|<b><u>md5</u></b>
|
||||||
|
|---
|
||||||
|
|<b><i>uppercase</i></b>, upper, u <i>(sha1/sha256/sha512/md5 only)</i>"""
|
||||||
|
.stripMargin
|
||||||
|
).replyToMessageId(replyTo).parseMode(ParseMode HTML)
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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,
|
||||||
|
"<code>$__channel_identify</code>"
|
||||||
|
).replyToMessageId(event.message.messageId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MornyCoeur.extra exec SendMessage(
|
||||||
|
event.message.chat.id,
|
||||||
|
TelegramUserInformation informationOutputHTML user
|
||||||
|
).replyToMessageId(event.message.messageId()).parseMode(ParseMode HTML)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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)}
|
||||||
|
|<code>${h(response.body)}</code>"""
|
||||||
|
.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:
|
||||||
|
|<code>${h(e.getMessage)}</code>"""
|
||||||
|
.stripMargin
|
||||||
|
).parseMode(ParseMode.HTML).replyToMessageId(event.message().messageId()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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"""欢迎使用 <b>Morny Cono</b>,<i>来自安妮的侍从小鼠</i>。
|
||||||
|
|Morny 具有各种各样的功能。
|
||||||
|
|
|
||||||
|
|————————————————
|
||||||
|
|${MornyInformation.getMornyAboutLinksHTML}
|
||||||
|
|————————————————
|
||||||
|
|
|
||||||
|
|(你可以随时通过 /info 重新获得这些信息)"""
|
||||||
|
.stripMargin
|
||||||
|
).parseMode(ParseMode HTML)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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"<code>$cm</code>"
|
||||||
|
else g++= s"<a href='$cp'>$cm</a>"
|
||||||
|
if (!MornySystem.isCleanBuild) g++= ".<code>δ</code>"
|
||||||
|
g toString
|
||||||
|
}
|
||||||
|
|
||||||
|
def getVersionAllFullTagHTML: String = {
|
||||||
|
val v = StringBuilder()
|
||||||
|
v ++= s"<code>${MornySystem VERSION_BASE}</code>"
|
||||||
|
if (MornySystem isUseDelta) v++=s"-δ<code>${MornySystem VERSION_DELTA}</code>"
|
||||||
|
if (MornySystem isGitBuild) v++="+"++=getVersionGitTagHTML
|
||||||
|
v ++= s"*<code>${MornySystem.CODENAME toUpperCase}</code>"
|
||||||
|
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"""<a href='${MornyAbout MORNY_SOURCECODE_LINK}'>source code</a> | <a href='${MornyAbout MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK}'>backup</a>
|
||||||
|
|<a href='${MornyAbout MORNY_ISSUE_TRACKER_LINK}'>反馈 / issue tracker</a>
|
||||||
|
|<a href='${MornyAbout MORNY_USER_GUIDE_LINK}'>使用说明书 / user guide & docs</a>"""
|
||||||
|
.stripMargin
|
||||||
|
|
||||||
|
private def echoInfo (chatId: Long, replyTo: Int): Unit = {
|
||||||
|
MornyCoeur.extra exec new SendPhoto(
|
||||||
|
chatId,
|
||||||
|
getAboutPic
|
||||||
|
).caption(
|
||||||
|
s"""<b>Morny Cono</b>
|
||||||
|
|来自安妮的侍从小鼠。
|
||||||
|
|————————————————
|
||||||
|
|$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"-δ<code>${h(MornySystem.VERSION_DELTA)}</code>" else ""
|
||||||
|
val versionGitHTML = if (MornySystem.isGitBuild) s"git $getVersionGitTagHTML" else ""
|
||||||
|
MornyCoeur.extra exec new SendMessage(
|
||||||
|
event.message.chat.id,
|
||||||
|
s"""version:
|
||||||
|
|- Morny <code>${h(MornySystem.CODENAME toUpperCase)}</code>
|
||||||
|
|- <code>${h(MornySystem.VERSION_BASE)}</code>$versionDeltaHTML${if (MornySystem.isGitBuild) "\n- " + versionGitHTML else ""}
|
||||||
|
|coeur md5_hash:
|
||||||
|
|- <code>${h(MornySystem.getJarMd5)}</code>
|
||||||
|
|coding timestamp:
|
||||||
|
|- <code>${BuildConfig.CODE_TIMESTAMP}</code>
|
||||||
|
|- <code>${h(formatDate(BuildConfig.CODE_TIMESTAMP, 0))} [UTC]</code>
|
||||||
|
|""".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 <code>${h(if (getRuntimeHostname == null) "<unknown-host>" else getRuntimeHostname)}</code>
|
||||||
|
|- <code>${h(sysprop("os.name"))}</code> <code>${h(sysprop("os.arch"))}</code> <code>${h(sysprop("os.version"))}</code>
|
||||||
|
|java runtime:
|
||||||
|
|- <code>${h(sysprop("java.vm.vendor"))}.${h(sysprop("java.vm.name"))}</code>
|
||||||
|
|- <code>${h(sysprop("java.vm.version"))}</code>
|
||||||
|
|vm memory:
|
||||||
|
|- <code>${Runtime.getRuntime.totalMemory/1024/1024}</code> / <code>${Runtime.getRuntime.maxMemory/1024/1024}</code>
|
||||||
|
|- <code>${Runtime.getRuntime.availableProcessors}</code> cores
|
||||||
|
|coeur version:
|
||||||
|
|- $getVersionAllFullTagHTML
|
||||||
|
|- <code>${h(MornySystem.getJarMd5)}</code>
|
||||||
|
|- <code>${h(formatDate(BuildConfig.CODE_TIMESTAMP, 0))} [UTC]</code>
|
||||||
|
|- [<code>${BuildConfig.CODE_TIMESTAMP}</code>]
|
||||||
|
|continuous:
|
||||||
|
|- <code>${h(formatDuration(System.currentTimeMillis - MornyCoeur.coeurStartTimestamp))}</code>
|
||||||
|
|- [<code>${System.currentTimeMillis - MornyCoeur.coeurStartTimestamp}</code>]
|
||||||
|
|- <code>${h(formatDate(MornyCoeur.coeurStartTimestamp, 0))}</code>
|
||||||
|
|- [<code>${MornyCoeur.coeurStartTimestamp}</code>]"""
|
||||||
|
.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)
|
||||||
|
|
||||||
|
}
|
@ -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 = "<a href=\"https://lab.magiconch.com/nbnhhsh/\">## Result of nbnhhsh query :</a>"
|
||||||
|
|
||||||
|
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<b>[[ ${h(_word.name)} ]]</b>"
|
||||||
|
logger debug s"**used [${_word.name}]"
|
||||||
|
if (_word.trans != null) for (_trans <- _word.trans)
|
||||||
|
message ++= s"\n* <i>${h(_trans)}</i>"
|
||||||
|
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` <i>${h(_inputting)}</i>"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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,
|
||||||
|
"<b>Just</b> a TEST command. num is:" + (a toString)
|
||||||
|
).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
src/main/scala/cc/sukazyo/cono/morny/bot/command/喵呜.scala
Normal file
67
src/main/scala/cc/sukazyo/cono/morny/bot/command/喵呜.scala
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main/scala/cc/sukazyo/cono/morny/bot/command/私わね.scala
Normal file
26
src/main/scala/cc/sukazyo/cono/morny/bot/command/私わね.scala
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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, "<b>STEAM LIBRARY</b>")
|
||||||
|
case "hana paresu" | "花宫" | "内群" =>
|
||||||
|
requestItem(update.message.from, "<b>Hana Paresu</b>")
|
||||||
|
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,
|
||||||
|
"<i>on</i> <code>%s [UTC+8]</code>\n- <code>%s</code> <i>before</i>".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, "<b>Last Annie Dinner</b>",
|
||||||
|
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, "<u>[???]</u>")
|
||||||
|
MornyCoeur.extra exec ForwardMessage(me, message.chat.id, message.messageId)
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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"<a href='tg://user?id=${(TGToString as target) getSenderId}'>自己</a>"
|
||||||
|
else (TGToString as target) getSenderFirstNameRefHtml,
|
||||||
|
if hasObject then h(v_object+" ") else ""
|
||||||
|
)
|
||||||
|
).parseMode(ParseMode HTML).replyToMessageId(update.message.messageId)
|
||||||
|
true
|
||||||
|
|
||||||
|
} else false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user