mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-23 03:27:39 +08:00
Merge tag '0.2.0@mvn(c3)' into release
This commit is contained in:
commit
7dee5a9d40
34
build.gradle
34
build.gradle
@ -1,9 +1,18 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.github.jengelman.gradle.plugins:shadow:5.0.0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'cc.sukazyo'
|
group 'cc.sukazyo'
|
||||||
version '0.1.2'
|
version '0.2.0'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -21,3 +30,26 @@ dependencies {
|
|||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Javadoc) {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
options.docEncoding = 'UTF-8'
|
||||||
|
options.charSet = 'UTF-8'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
apply plugin: 'application'
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
mainClassName = 'cc.sukazyo.cono.morny.MornyCoeur'
|
||||||
|
archiveBaseName.set("Morny_Coeur")
|
||||||
|
archiveVersion.set(version)
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ package cc.sukazyo.cono.morny;
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.bot.api.OnUpdate;
|
import cc.sukazyo.cono.morny.bot.api.OnUpdate;
|
||||||
import cc.sukazyo.cono.morny.bot.event.EventListeners;
|
import cc.sukazyo.cono.morny.bot.event.EventListeners;
|
||||||
import cc.sukazyo.cono.morny.data.MornyHello;
|
import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager;
|
||||||
import com.pengrad.telegrambot.TelegramBot;
|
import com.pengrad.telegrambot.TelegramBot;
|
||||||
import com.pengrad.telegrambot.request.GetMe;
|
import com.pengrad.telegrambot.request.GetMe;
|
||||||
|
|
||||||
@ -11,19 +11,23 @@ import static cc.sukazyo.cono.morny.Logger.logger;
|
|||||||
public class MornyCoeur {
|
public class MornyCoeur {
|
||||||
|
|
||||||
private static TelegramBot account;
|
private static TelegramBot account;
|
||||||
|
public static final String USERNAME = "morny_cono_annie_bot";
|
||||||
|
|
||||||
public static void main (String[] args) {
|
public static void main (String[] args) {
|
||||||
|
|
||||||
logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII);
|
logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII);
|
||||||
logger.info("System Starting");
|
logger.info("System Starting");
|
||||||
|
|
||||||
|
configureSafeExit();
|
||||||
|
|
||||||
logger.info("args key:\n " + args[0]);
|
logger.info("args key:\n " + args[0]);
|
||||||
|
|
||||||
try { account = login(args[0]); }
|
try { account = login(args[0]); }
|
||||||
catch (Exception e) { logger.error("Cannot login to bot/api."); System.exit(-1); }
|
catch (Exception e) { logger.error("Cannot login to bot/api. :\n " + e.getMessage()); System.exit(-1); }
|
||||||
|
|
||||||
logger.info("Bot login succeed.");
|
logger.info("Bot login succeed.");
|
||||||
|
|
||||||
|
TrackerDataManager.init();
|
||||||
EventListeners.registerAllListeners();
|
EventListeners.registerAllListeners();
|
||||||
account.setUpdatesListener(OnUpdate::onNormalUpdate);
|
account.setUpdatesListener(OnUpdate::onNormalUpdate);
|
||||||
|
|
||||||
@ -31,13 +35,25 @@ public class MornyCoeur {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void exitCleanup () {
|
||||||
|
TrackerDataManager.DAEMON.interrupt();
|
||||||
|
TrackerDataManager.trackingLock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void configureSafeExit () {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(MornyCoeur::exitCleanup));
|
||||||
|
}
|
||||||
|
|
||||||
public static TelegramBot login (String key) {
|
public static TelegramBot login (String key) {
|
||||||
TelegramBot account = new TelegramBot(key);
|
TelegramBot account = new TelegramBot(key);
|
||||||
logger.info("Trying to login...");
|
logger.info("Trying to login...");
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 4; i++) {
|
||||||
if (i != 1) logger.info("retrying...");
|
if (i != 1) logger.info("retrying...");
|
||||||
try {
|
try {
|
||||||
logger.info("Succeed login to @" + account.execute(new GetMe()).user().username());
|
String username = account.execute(new GetMe()).user().username();
|
||||||
|
if (!USERNAME.equals(username))
|
||||||
|
throw new RuntimeException("Required the bot @"+USERNAME + " but @"+username + "logged in!");
|
||||||
|
logger.info("Succeed login to @" + username);
|
||||||
return account;
|
return account;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(System.out);
|
e.printStackTrace(System.out);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cc.sukazyo.cono.morny.data;
|
package cc.sukazyo.cono.morny;
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public class MornyHello {
|
public class MornyHello {
|
@ -25,9 +25,13 @@ public class EventListenerManager {
|
|||||||
@Override
|
@Override
|
||||||
public void run () {
|
public void run () {
|
||||||
for (EventListener x : listeners) {
|
for (EventListener x : listeners) {
|
||||||
if (exec.apply(x)) return;
|
try {
|
||||||
|
if (exec.apply(x)) return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Event Error!");
|
||||||
|
e.printStackTrace(System.out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
logger.info("event exited undone");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,11 @@ import cc.sukazyo.cono.morny.bot.api.EventListenerManager;
|
|||||||
public class EventListeners {
|
public class EventListeners {
|
||||||
|
|
||||||
public static final OnCommandExecute COMMANDS_LISTENER = new OnCommandExecute();
|
public static final OnCommandExecute COMMANDS_LISTENER = new OnCommandExecute();
|
||||||
|
public static final OnActivityRecord ACTIVITY_RECORDER = new OnActivityRecord();
|
||||||
|
|
||||||
public static void registerAllListeners () {
|
public static void registerAllListeners () {
|
||||||
EventListenerManager.addListener(
|
EventListenerManager.addListener(
|
||||||
|
ACTIVITY_RECORDER,
|
||||||
COMMANDS_LISTENER
|
COMMANDS_LISTENER
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package cc.sukazyo.cono.morny.bot.event;
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.bot.api.EventListener;
|
||||||
|
import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager;
|
||||||
|
import com.pengrad.telegrambot.model.Chat;
|
||||||
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
|
||||||
|
public class OnActivityRecord extends EventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMessage (Update update) {
|
||||||
|
if (
|
||||||
|
update.message().chat().type() == Chat.Type.supergroup ||
|
||||||
|
update.message().chat().type() == Chat.Type.group
|
||||||
|
) {
|
||||||
|
TrackerDataManager.record(
|
||||||
|
update.message().chat().id(),
|
||||||
|
update.message().from().id(),
|
||||||
|
(long)update.message().date() * 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return super.onMessage(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,13 +22,17 @@ public class OnCommandExecute extends EventListener {
|
|||||||
}
|
}
|
||||||
switch (event.message().text()) {
|
switch (event.message().text()) {
|
||||||
case "/o":
|
case "/o":
|
||||||
|
case "/o@" + MornyCoeur.USERNAME:
|
||||||
onCommandOnExec(event);
|
onCommandOnExec(event);
|
||||||
break;
|
break;
|
||||||
case "/hi":
|
case "/hi":
|
||||||
|
case "/hi@" + MornyCoeur.USERNAME:
|
||||||
case "/hello":
|
case "/hello":
|
||||||
|
case "/hello@" + MornyCoeur.USERNAME:
|
||||||
onCommandHelloExec(event);
|
onCommandHelloExec(event);
|
||||||
break;
|
break;
|
||||||
case "/exit":
|
case "/exit":
|
||||||
|
case "/exit@" + MornyCoeur.USERNAME:
|
||||||
onCommandExitExec(event);
|
onCommandExitExec(event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
package cc.sukazyo.cono.morny.data.tracker;
|
||||||
|
|
||||||
|
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.util.HashMap;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import static cc.sukazyo.cono.morny.Logger.logger;
|
||||||
|
|
||||||
|
public class TrackerDataManager {
|
||||||
|
|
||||||
|
public static final ReentrantLock trackingLock = new ReentrantLock();
|
||||||
|
|
||||||
|
private static final ReentrantLock recordLock = new ReentrantLock();
|
||||||
|
private static HashMap<Long, HashMap<Long, TreeSet<Long>>> record = new HashMap<>();
|
||||||
|
|
||||||
|
public static final TrackerDaemon DAEMON = new TrackerDaemon();
|
||||||
|
public static class TrackerDaemon extends Thread {
|
||||||
|
|
||||||
|
public TrackerDaemon () { this.setName("TRACKER"); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run () {
|
||||||
|
trackingLock.lock();
|
||||||
|
long lastWaitTimestamp = System.currentTimeMillis();
|
||||||
|
boolean postProcess = false;
|
||||||
|
do {
|
||||||
|
lastWaitTimestamp += 10 * 60 * 1000;
|
||||||
|
long sleeping = lastWaitTimestamp - System.currentTimeMillis();
|
||||||
|
if (sleeping > 0) {
|
||||||
|
try { Thread.sleep(sleeping); } catch (InterruptedException e) { interrupt(); }
|
||||||
|
} else {
|
||||||
|
logger.warn("Tracker may be too busy to process data!!");
|
||||||
|
lastWaitTimestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
if (interrupted()) {
|
||||||
|
postProcess = true;
|
||||||
|
logger.warn("last tracker write in this processor!");
|
||||||
|
}
|
||||||
|
if (record.size() != 0) {
|
||||||
|
logger.info("start writing tracker data.");
|
||||||
|
save(reset());
|
||||||
|
logger.info("done writing tracker data.");
|
||||||
|
}
|
||||||
|
else logger.info("nothing to do yet");
|
||||||
|
} while (!postProcess);
|
||||||
|
trackingLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void record (long chat, long user, long timestamp) {
|
||||||
|
recordLock.lock();
|
||||||
|
if (!record.containsKey(chat)) record.put(chat, new HashMap<>());
|
||||||
|
HashMap<Long, TreeSet<Long>> chatUsers = record.get(chat);
|
||||||
|
if (!chatUsers.containsKey(user)) chatUsers.put(user, new TreeSet<>());
|
||||||
|
TreeSet<Long> userRecords = chatUsers.get(user);
|
||||||
|
userRecords.add(timestamp);
|
||||||
|
recordLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init () {
|
||||||
|
DAEMON.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashMap<Long, HashMap<Long, TreeSet<Long>>> reset () {
|
||||||
|
recordLock.lock();
|
||||||
|
HashMap<Long, HashMap<Long, TreeSet<Long>>> recordOld = record;
|
||||||
|
record = new HashMap<>();
|
||||||
|
recordLock.unlock();
|
||||||
|
return recordOld;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void save (HashMap<Long, HashMap<Long, TreeSet<Long>>> record) {
|
||||||
|
|
||||||
|
{
|
||||||
|
if (!record.containsKey(0L)) record.put(0L, new HashMap<>());
|
||||||
|
HashMap<Long, TreeSet<Long>> chatUsers = record.get(0L);
|
||||||
|
if (!chatUsers.containsKey(0L)) chatUsers.put(0L, new TreeSet<>());
|
||||||
|
TreeSet<Long> userRecords = chatUsers.get(0L);
|
||||||
|
userRecords.add(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
record.forEach((chat, chatUsers) -> chatUsers.forEach((user, userRecords) -> {
|
||||||
|
|
||||||
|
long dayCurrent = -1;
|
||||||
|
FileChannel channelCurrent = null;
|
||||||
|
|
||||||
|
for (long timestamp : userRecords) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
long day = timestamp / (24 * 60 * 60 * 1000);
|
||||||
|
if (dayCurrent != day) {
|
||||||
|
if (channelCurrent != null) channelCurrent.close();
|
||||||
|
channelCurrent = openFile(chat, user, day);
|
||||||
|
dayCurrent = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert channelCurrent != null;
|
||||||
|
channelCurrent.write(ByteBuffer.wrap(
|
||||||
|
String.format("%d\n", timestamp).getBytes(StandardCharsets.UTF_8)
|
||||||
|
));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(String.format("exception in write tracker data: %d/%d/%d", chat, user, timestamp));
|
||||||
|
e.printStackTrace(System.out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FileChannel openFile (long chat, long user, long day) throws IOException {
|
||||||
|
File data = new File(String.format("./data/tracker/%d/%d", chat, user));
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user