refactor(bot): centralize runtime state; support albums + safer vision handling

- make MessageStore.put() return StoredMessage and allow collectReplyChainText() to work with StoredMessage
- move muted users + answers loading into Environment (add Answers model + GEMINI_IMAGE_MODEL)
- extract message handling into processNewMessage() and add media-group (album) caching/downloading by unique_file_id
- for Ollama: check model capabilities before sending images; use replyToMessage helper consistently
- add /geminiGenImage command stub for Gemini image generation
This commit is contained in:
2026-01-29 20:01:30 +03:00
parent 5f4405c9ee
commit b74e0a0f3e
16 changed files with 312 additions and 148 deletions
+5 -47
View File
@@ -1,9 +1,7 @@
import * as fs from "fs";
import {Environment} from "../common/environment";
import {logError} from "../util/utils";
export let muted: Set<number> = new Set<number>();
import {Answers} from "../model/answers";
type DataJsonFile = {
admins: number[]
@@ -12,39 +10,6 @@ type DataJsonFile = {
export let jsonFile: DataJsonFile;
type AnswersJsonFile = {
test: string[]
prefix: string[]
better: string[]
who: string[]
kick: string[]
invite: string[]
day: number[]
}
export const testAnswers: string[] = [];
export const prefixAnswers: string[] = [];
export const betterAnswers: string[] = [];
export const whoAnswers: string[] = [];
export const kickAnswers: string[] = [];
export const inviteAnswers: string[] = [];
export const dayAnswers: number[] = [];
export async function addMute(id: number): Promise<boolean> {
if (muted.has(id)) return Promise.resolve(false);
muted.add(id);
await saveData();
return Promise.resolve(true);
}
export async function removeMute(id: number): Promise<boolean> {
if (!muted.has(id)) return Promise.resolve(false);
muted.delete(id);
await saveData();
return Promise.resolve(true);
}
export async function readData(): Promise<void> {
try {
jsonFile = JSON.parse(fs.readFileSync(`${Environment.DATA_PATH}/data.json`).toString());
@@ -53,8 +18,7 @@ export async function readData(): Promise<void> {
admins.unshift(Environment.CREATOR_ID);
Environment.setAdmins(new Set<number>(admins));
muted = new Set<number>(jsonFile.muted || []);
Environment.setMuted(new Set<number>(jsonFile.muted || []));
return Promise.resolve();
} catch (e) {
@@ -69,7 +33,7 @@ export async function saveData(): Promise<void> {
jsonFile.admins = adminIds;
const mutedList: number[] = [];
muted.forEach(id => mutedList.push(id));
Environment.MUTED_IDS.forEach(id => mutedList.push(id));
jsonFile.muted = mutedList;
try {
@@ -82,14 +46,8 @@ export async function saveData(): Promise<void> {
export async function retrieveAnswers(): Promise<void> {
try {
const json: AnswersJsonFile = JSON.parse(fs.readFileSync(`${Environment.DATA_PATH}/answers.json`).toString());
json.test.forEach(e => testAnswers.push(e));
json.prefix.forEach(e => prefixAnswers.push(e));
json.better.forEach(e => betterAnswers.push(e));
json.who.forEach(e => whoAnswers.push(e));
json.kick.forEach(e => kickAnswers.push(e));
json.invite.forEach(e => inviteAnswers.push(e));
json.day.forEach(e => dayAnswers.push(e));
const json: Answers = JSON.parse(fs.readFileSync(`${Environment.DATA_PATH}/answers.json`).toString());
Environment.setAnswers(json);
return Promise.resolve();
} catch (e) {
logError(e);