mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-22 11:14:55 +08:00
added --dinner-chat
startup param, code quality optimization.
- added `--dinner-chat`/`-chd` startup param for setup dinner chat id - fixed some unclosed resource - TrackerDataManager changed method to get FileChannel (I don't know if it works) - MornyCLI scanner uses try-with-resources - declared directly used dependencies - okhttp: 4.11.0 - gson: 2.10.1 - some minor refactors - MornyCoeur.main rename to .init - added package `internal` and move @BuildConfigField to it - added new util class OkHttpPublic with MediaTypes in use - added javadoc for TrackerDataManager - and so on...
This commit is contained in:
parent
69a33933f5
commit
7589e8661d
18
build.gradle
18
build.gradle
@ -4,7 +4,7 @@ plugins {
|
||||
id 'application'
|
||||
id 'maven-publish'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||
id 'com.github.gmazzo.buildconfig' version '3.1.0'
|
||||
id 'com.github.gmazzo.buildconfig' version '4.1.2'
|
||||
id 'org.ajoberstar.grgit' version '5.2.0'
|
||||
}
|
||||
|
||||
@ -73,15 +73,16 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
|
||||
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${libSpotbugsVersion}"
|
||||
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}"
|
||||
|
||||
api "cc.sukazyo:messiva:${libMessivaVersion}"
|
||||
api "cc.sukazyo:messiva:${lib_messiva_v}"
|
||||
|
||||
implementation "com.github.pengrad:java-telegram-bot-api:${libJavaTelegramBotApiVersion}"
|
||||
implementation "com.github.pengrad:java-telegram-bot-api:${lib_javatelegramapi_v}"
|
||||
implementation "com.squareup.okhttp3:okhttp:${lib_okhttp_v}"
|
||||
implementation "com.google.code.gson:gson:${lib_gson_v}"
|
||||
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${libJunitVersion}"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:${libJunitVersion}"
|
||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${libJunitVersion}"
|
||||
testImplementation platform("org.junit:junit-bom:${lib_junit_v}")
|
||||
testImplementation "org.junit.jupiter:junit-jupiter"
|
||||
|
||||
}
|
||||
|
||||
@ -91,6 +92,9 @@ application {
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
|
@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur
|
||||
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
|
||||
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
|
||||
|
||||
VERSION = 1.0.0-RC3.8
|
||||
VERSION = 1.0.0-RC3.9
|
||||
|
||||
USE_DELTA = false
|
||||
VERSION_DELTA =
|
||||
@ -14,10 +14,13 @@ CODENAME = beiping
|
||||
|
||||
# dependencies
|
||||
|
||||
libSpotbugsVersion = 4.7.3
|
||||
lib_spotbugs_v = 4.7.3
|
||||
|
||||
libMessivaVersion = 0.1.1
|
||||
lib_messiva_v = 0.1.1
|
||||
|
||||
libJavaTelegramBotApiVersion = 6.2.0
|
||||
lib_javatelegramapi_v = 6.2.0
|
||||
|
||||
libJunitVersion = 5.9.0
|
||||
lib_okhttp_v = 4.11.0
|
||||
lib_gson_v = 2.10.1
|
||||
|
||||
lib_junit_v = 5.10.0
|
||||
|
@ -118,7 +118,7 @@ public class MornyCoeur {
|
||||
* @see #MornyCoeur 程序初始化方法
|
||||
* @param config morny 实例的配置选项数据
|
||||
*/
|
||||
public static void main (MornyConfig config) {
|
||||
public static void init (MornyConfig config) {
|
||||
if (INSTANCE == null) {
|
||||
|
||||
logger.info("Coeur Starting");
|
||||
|
@ -169,12 +169,12 @@ public class MornyConfig {
|
||||
public long eventOutdatedTimestamp = -1;
|
||||
public boolean commandLoginRefresh = false;
|
||||
public boolean commandLogoutClear = false;
|
||||
@Nonnull public Set<Long> dinnerTrustedReaders = new HashSet<>();
|
||||
@Nonnull public final Set<Long> dinnerTrustedReaders = new HashSet<>();
|
||||
public long dinnerChatId = -1001707106392L;
|
||||
public long reportToChat = -1001650050443L;
|
||||
public long medicationNotifyToChat = -1001729016815L;
|
||||
@Nonnull public ZoneOffset medicationTimerUseTimezone = ZoneOffset.UTC;
|
||||
@Nonnull public Set<Integer> medicationNotifyAt = new HashSet<>();
|
||||
@Nonnull public final Set<Integer> medicationNotifyAt = new HashSet<>();
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package cc.sukazyo.cono.morny;
|
||||
|
||||
import cc.sukazyo.cono.morny.daemon.MornyReport;
|
||||
import cc.sukazyo.cono.morny.util.BuildConfigField;
|
||||
import cc.sukazyo.cono.morny.internal.BuildConfigField;
|
||||
import cc.sukazyo.cono.morny.util.FileUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -79,7 +79,7 @@ public class ServerMain {
|
||||
* <b>自 {@code 0.5.0.4},旧的直接通过参数为 bot token & username 赋值的方式已被删除</b>
|
||||
* 使用参数所进行取值的 token 和 username 已被转移至 {@code --token} 和 {@code --username} 参数<br>
|
||||
*
|
||||
* @see MornyCoeur#main
|
||||
* @see MornyCoeur#init
|
||||
* @since 0.4.0.0
|
||||
* @param args 参数组
|
||||
*/
|
||||
@ -143,12 +143,17 @@ public class ServerMain {
|
||||
config.trustedChat = Long.parseLong(args[i]);
|
||||
continue;
|
||||
}
|
||||
//noinspection SpellCheckingInspection
|
||||
// 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;
|
||||
@ -278,7 +283,7 @@ public class ServerMain {
|
||||
|
||||
Thread.currentThread().setName(THREAD_MORNY_INIT);
|
||||
try {
|
||||
MornyCoeur.main(new MornyConfig(config));
|
||||
MornyCoeur.init(new MornyConfig(config));
|
||||
} catch (MornyConfig.CheckFailure.NullTelegramBotKey ignore) {
|
||||
logger.info("Parameter required has no value:\n --token.");
|
||||
} catch (MornyConfig.CheckFailure e) {
|
||||
|
@ -37,50 +37,57 @@ public class EventHack implements ITelegramCommand {
|
||||
@Override
|
||||
public void execute (@Nonnull InputCommand command, @Nonnull Update event) {
|
||||
|
||||
boolean isOk = false;
|
||||
enum Status {
|
||||
OK,
|
||||
FORBIDDEN_FOR_ANY
|
||||
}
|
||||
Status status;
|
||||
|
||||
String x_mode = "";
|
||||
if (command.hasArgs()) {
|
||||
x_mode = command.getArgs()[0];
|
||||
}
|
||||
|
||||
switch (x_mode) {
|
||||
case "any":
|
||||
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
|
||||
);isOk = true;
|
||||
);
|
||||
status = Status.OK;
|
||||
} else {
|
||||
status = Status.FORBIDDEN_FOR_ANY;
|
||||
}
|
||||
break;
|
||||
case "group":
|
||||
}
|
||||
case "group" -> {
|
||||
OnEventHackHandle.registerHack(
|
||||
event.message().messageId(),
|
||||
event.message().from().id(),
|
||||
event.message().chat().id(),
|
||||
OnEventHackHandle.HackType.GROUP
|
||||
);isOk = true;
|
||||
break;
|
||||
default:
|
||||
);
|
||||
status = Status.OK;
|
||||
}
|
||||
default -> {
|
||||
OnEventHackHandle.registerHack(
|
||||
event.message().messageId(),
|
||||
event.message().from().id(),
|
||||
event.message().chat().id(),
|
||||
OnEventHackHandle.HackType.USER
|
||||
);isOk = true;
|
||||
break;
|
||||
);
|
||||
status = Status.OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (isOk) {
|
||||
MornyCoeur.extra().exec(new SendSticker(
|
||||
switch (status) {
|
||||
case OK -> MornyCoeur.extra().exec(new SendSticker(
|
||||
event.message().chat().id(),
|
||||
TelegramStickers.ID_WAITING
|
||||
).replyToMessageId(event.message().messageId())
|
||||
);
|
||||
} else {
|
||||
MornyCoeur.extra().exec(new SendSticker(
|
||||
case FORBIDDEN_FOR_ANY -> MornyCoeur.extra().exec(new SendSticker(
|
||||
event.message().chat().id(),
|
||||
TelegramStickers.ID_403
|
||||
).replyToMessageId(event.message().messageId())
|
||||
|
@ -4,10 +4,10 @@ import cc.sukazyo.cono.morny.bot.api.EventListener;
|
||||
|
||||
public class OnRandomlyTriggered extends EventListener {
|
||||
|
||||
/**
|
||||
* function CODE_IK0XA1
|
||||
*/
|
||||
// @Override
|
||||
// /**
|
||||
// * function CODE_IK0XA1
|
||||
// */
|
||||
// // @Override
|
||||
// public boolean onMessage (@Nonnull Update update) {
|
||||
//
|
||||
// if (update.message().text() == null) return false;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package cc.sukazyo.cono.morny.daemon;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@ -15,9 +15,11 @@ import static cc.sukazyo.cono.morny.Log.logger;
|
||||
|
||||
public class TrackerDataManager {
|
||||
|
||||
/** {@link TrackerDaemon} 的锁。保证在程序中只有一个 TrackerDaemon 会运行。 */
|
||||
public static final ReentrantLock trackingLock = new ReentrantLock();
|
||||
|
||||
/** {@link #record Tracker 缓存}的锁 <p> 为保证对 Tracker 缓存的操作不会造成线程冲突,在操作缓存数据前应先取得此锁。 */
|
||||
private static final ReentrantLock recordLock = new ReentrantLock();
|
||||
/** Tracker 数据的内存缓存 <p> 进行数据操作前请先取得对应的{@link #recordLock 锁} */
|
||||
private static HashMap<Long, HashMap<Long, TreeSet<Long>>> record = new HashMap<>();
|
||||
|
||||
public static final TrackerDaemon DAEMON = new TrackerDaemon();
|
||||
@ -55,6 +57,15 @@ public class TrackerDataManager {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 向 Tracker 缓存写入一条 tracker 数据.
|
||||
* <p>
|
||||
* <font color=green>这个方法对于 Tracker 缓存是原子化的。</font>
|
||||
*
|
||||
* @param chat tracker 所属的 Telegram Chat ID
|
||||
* @param user tracker 所记录的 Telegram User ID
|
||||
* @param timestamp tracker 被生成时的 UTC 时间戳
|
||||
*/
|
||||
public static void record (long chat, long user, long timestamp) {
|
||||
recordLock.lock();
|
||||
if (!record.containsKey(chat)) record.put(chat, new HashMap<>());
|
||||
@ -65,16 +76,36 @@ public class TrackerDataManager {
|
||||
recordLock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启 {@link TrackerDaemon}.
|
||||
* <p>
|
||||
* <font color=orange>由于 Tracker 已废弃,这个方法已无作用。</font>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void init () {
|
||||
DAEMON.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行 Tracker 的保存逻辑.
|
||||
* @see #reset() 弹出 Tracker 缓存
|
||||
* @see #save(HashMap) 执行硬盘写入操作
|
||||
*/
|
||||
public static void save () {
|
||||
logger.info("start writing tracker data.");
|
||||
save(reset());
|
||||
logger.info("done writing tracker data.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Tracker 的缓存数据弹出.
|
||||
* <p>
|
||||
* 这个方法将返回现在 Tracker 的所有缓存数据,然后清除缓存。
|
||||
* <p>
|
||||
* <font color=green>这个方法对于 Tracker 缓存是原子化的。</font>
|
||||
*
|
||||
* @return 当前 Tracker 所包含的内容
|
||||
*/
|
||||
private static HashMap<Long, HashMap<Long, TreeSet<Long>>> reset () {
|
||||
recordLock.lock();
|
||||
HashMap<Long, HashMap<Long, TreeSet<Long>>> recordOld = record;
|
||||
@ -83,6 +114,11 @@ public class TrackerDataManager {
|
||||
return recordOld;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Tracker 数据写入到硬盘.
|
||||
*
|
||||
* @param record 需要保存的 Tracker 数据集
|
||||
*/
|
||||
private static void save (HashMap<Long, HashMap<Long, TreeSet<Long>>> record) {
|
||||
|
||||
{
|
||||
@ -109,10 +145,12 @@ public class TrackerDataManager {
|
||||
}
|
||||
|
||||
assert channelCurrent != null;
|
||||
channelCurrent.write(ByteBuffer.wrap(
|
||||
final int result = channelCurrent.write(ByteBuffer.wrap(
|
||||
String.format("%d\n", timestamp).getBytes(StandardCharsets.UTF_8)
|
||||
));
|
||||
|
||||
if (result == 0) logger.warn("writing tracker data %d/%d/%d: write only 0 bytes! is anything wrong?");
|
||||
|
||||
} catch (Exception e) {
|
||||
final String message = String.format("exception in write tracker data: %d/%d/%d", chat, user, timestamp);
|
||||
logger.error(message);
|
||||
@ -130,7 +168,7 @@ public class TrackerDataManager {
|
||||
if (!data.isDirectory()) if (!data.mkdirs()) throw new IOException("Cannot create file directory " + data.getPath());
|
||||
File file = new File(data, String.valueOf(day));
|
||||
if (!file.isFile()) if (!file.createNewFile()) throw new IOException("Cannot create file " + file.getPath());
|
||||
return new FileOutputStream(file, true).getChannel();
|
||||
return FileChannel.open(file.toPath(), StandardOpenOption.APPEND);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import java.io.IOException;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import cc.sukazyo.cono.morny.util.OkHttpPublic.MediaTypes;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
@ -23,21 +23,18 @@ public class NbnhhshQuery {
|
||||
public Word[] words;
|
||||
}
|
||||
|
||||
public record GuessReq (String text) {
|
||||
}
|
||||
public record GuessReq (String text) {}
|
||||
|
||||
public static final String API_URL = "https://lab.magiconch.com/api/nbnhhsh/";
|
||||
public static final String API_GUESS_METHOD = "guess/";
|
||||
public static final String API_GUESS_DATA_TEMPLATE = "{ \"text\": \"%s\" }";
|
||||
|
||||
private static final OkHttpClient httpClient = new OkHttpClient();
|
||||
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
||||
|
||||
public static GuessResult sendGuess (String text) throws IOException {
|
||||
final String reqJsonText = new Gson().toJson(new GuessReq(text));
|
||||
Request request = new Request.Builder()
|
||||
.url(API_URL + API_GUESS_METHOD)
|
||||
.post(RequestBody.create(JSON, reqJsonText))
|
||||
.post(RequestBody.create(reqJsonText, MediaTypes.JSON))
|
||||
.build();
|
||||
try (Response response = httpClient.newCall(request).execute()) {
|
||||
final ResponseBody body = response.body();
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cc.sukazyo.cono.morny.util;
|
||||
package cc.sukazyo.cono.morny.internal;
|
||||
|
||||
|
||||
import java.lang.annotation.Documented;
|
13
src/main/java/cc/sukazyo/cono/morny/util/OkHttpPublic.java
Normal file
13
src/main/java/cc/sukazyo/cono/morny/util/OkHttpPublic.java
Normal file
@ -0,0 +1,13 @@
|
||||
package cc.sukazyo.cono.morny.util;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
|
||||
public class OkHttpPublic {
|
||||
|
||||
public static class MediaTypes {
|
||||
|
||||
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -8,9 +8,9 @@ public class MornyCLI {
|
||||
|
||||
public static void main (String[] args) {
|
||||
|
||||
Scanner line = new Scanner(System.in);
|
||||
System.out.print("$ java -jar morny-coeur-"+MornySystem.VERSION_FULL+".jar " );
|
||||
String x = line.nextLine();
|
||||
String x;
|
||||
try (Scanner line = new Scanner(System.in)) { x = line.nextLine(); }
|
||||
ServerMain.main(UniversalCommand.format(x));
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
package cc.sukazyo.cono.morny.util;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import static cc.sukazyo.cono.morny.util.CommonConvert.byteArrayToHex;
|
||||
import static cc.sukazyo.cono.morny.util.CommonConvert.byteToHex;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
public class TestCommonConvert {
|
||||
|
||||
@ -30,21 +26,22 @@ public class TestCommonConvert {
|
||||
assertEquals(expected, byteToHex(source));
|
||||
}
|
||||
|
||||
public static Stream<Arguments> testByteArrayToHexProvider () {
|
||||
return Stream.of(
|
||||
arguments(new byte[]{0x00}, "00"),
|
||||
arguments(new byte[]{(byte)0xff}, "ff"),
|
||||
arguments(new byte[]{(byte)0xc3}, "c3"),
|
||||
arguments(new byte[]{}, ""),
|
||||
arguments(new byte[]{0x30,0x0a,0x00,0x04,(byte)0xb0,0x00}, "300a0004b000"),
|
||||
arguments(new byte[]{0x00,0x00,0x0a,(byte)0xff,(byte)0xfc,(byte)0xab,(byte)0x00,0x04}, "00000afffcab0004"),
|
||||
arguments(new byte[]{0x00,0x7c,0x11,0x28,(byte)0x88,(byte)0xa6,(byte)0xfc,0x30}, "007c112888a6fc30")
|
||||
);
|
||||
public enum TestByteArrayToHexSource {
|
||||
$1(new T(new byte[]{0x00}, "00")),
|
||||
$2(new T(new byte[]{(byte)0xff}, "ff")),
|
||||
$3(new T(new byte[]{(byte)0xc3}, "c3")),
|
||||
$4(new T(new byte[]{}, "")),
|
||||
$5(new T(new byte[]{0x30,0x0a,0x00,0x04,(byte)0xb0,0x00}, "300a0004b000")),
|
||||
$6(new T(new byte[]{0x00,0x00,0x0a,(byte)0xff,(byte)0xfc,(byte)0xab,(byte)0x00,0x04}, "00000afffcab0004")),
|
||||
$7(new T(new byte[]{0x00,0x7c,0x11,0x28,(byte)0x88,(byte)0xa6,(byte)0xfc,0x30}, "007c112888a6fc30"));
|
||||
public record T (byte[] raw, String expected) {}
|
||||
public final T value;
|
||||
TestByteArrayToHexSource (T value) { this.value = value; }
|
||||
}
|
||||
@ParameterizedTest
|
||||
@MethodSource("testByteArrayToHexProvider")
|
||||
void testByteArrayToHex (byte[] raw, String expected) {
|
||||
assertEquals(expected, byteArrayToHex(raw));
|
||||
@EnumSource
|
||||
void testByteArrayToHex (TestByteArrayToHexSource source) {
|
||||
assertEquals(source.value.expected, byteArrayToHex(source.value.raw));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user