qwen-alpha 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-alpha",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "Telegram bot for Qwen Code integration — AI-powered code review, bug detection, and code generation",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -50,6 +50,8 @@ async function adminHandler(ctx) {
50
50
  **Управление пользователями:**
51
51
  /admin ban <user_id> — забанить
52
52
  /admin unban <user_id> — разбанить
53
+ /admin lock — заблокировать бота для всех кроме админов
54
+ /admin unlock — разблокировать бота
53
55
 
54
56
  **Сессии:**
55
57
  /admin sessions list — список сессий
@@ -128,7 +130,7 @@ async function adminHandler(ctx) {
128
130
  await ctx.reply('❌ Usage: /admin unban <user_id>');
129
131
  return;
130
132
  }
131
-
133
+
132
134
  const success = userService.unban(targetId);
133
135
  if (success) {
134
136
  await ctx.reply(`✅ Пользователь ${targetId} разбанен.`);
@@ -138,7 +140,31 @@ async function adminHandler(ctx) {
138
140
  }
139
141
  break;
140
142
  }
141
-
143
+
144
+ case 'lock': {
145
+ // Блокировка всех пользователей кроме админов
146
+ const settings = storeManager.get('settings');
147
+ const data = settings.getData();
148
+ data.locked = true;
149
+ settings.setData(data);
150
+
151
+ await ctx.reply('🔒 **Бот заблокирован для всех пользователей кроме админов.**\n\nИспользуйте /admin unlock для разблокировки.', { parse_mode: 'Markdown' });
152
+ logger.info({ userId }, 'Bot locked for all users except admins');
153
+ break;
154
+ }
155
+
156
+ case 'unlock': {
157
+ // Разблокировка бота
158
+ const settings = storeManager.get('settings');
159
+ const data = settings.getData();
160
+ data.locked = false;
161
+ settings.setData(data);
162
+
163
+ await ctx.reply('🔓 **Бот разблокирован.**\n\nВсе пользователи могут снова использовать бота.', { parse_mode: 'Markdown' });
164
+ logger.info({ userId }, 'Bot unlocked for all users');
165
+ break;
166
+ }
167
+
142
168
  case 'sessions': {
143
169
  const subCommand = args[2];
144
170
 
@@ -55,26 +55,22 @@ async function messageHandler(ctx) {
55
55
  let contextMessages = [];
56
56
  let session = ctx.state.session;
57
57
 
58
- // Если сессии нет в группе - создаём новую
59
- if (!session && !isPrivate) {
60
- session = sessionService.create({
61
- userId,
62
- chatId,
63
- rootMessageId: ctx.message.message_id,
64
- chatType: ctx.chat.type,
65
- chatTitle: ctx.chat.title,
66
- });
67
- ctx.state.session = session;
68
- statsService.incrementSessionCreated();
69
- }
70
-
71
58
  if (session) {
72
- // Если это reply на сообщение в сессии
59
+ // Если это reply на сообщение в сессии — получаем полную цепочку
73
60
  const replyToMessageId = ctx.message?.reply_to_message?.message_id;
74
61
 
75
62
  if (replyToMessageId && session.message_tree[replyToMessageId]) {
76
- // Получаем цепочку сообщений
77
63
  contextMessages = sessionService.getMessageChain(session, replyToMessageId);
64
+ } else {
65
+ // Если не reply, берём последние N сообщений из сессии
66
+ const allMessages = Object.values(session.message_tree)
67
+ .sort((a, b) => new Date(a.created_at) - new Date(b.created_at))
68
+ .slice(-10); // Последние 10 сообщений
69
+
70
+ contextMessages = allMessages.map(msg => ({
71
+ role: msg.user_id === 'bot' ? 'assistant' : 'user',
72
+ content: msg.text || '',
73
+ }));
78
74
  }
79
75
  }
80
76
 
@@ -1,5 +1,6 @@
1
1
  const userService = require('../../services/db/users');
2
2
  const adminService = require('../../services/db/admins');
3
+ const { storeManager } = require('../../services/db');
3
4
  const { logger } = require('../../utils/logger');
4
5
  const config = require('../../config');
5
6
 
@@ -51,7 +52,17 @@ async function authMiddleware(ctx, next) {
51
52
  await ctx.reply('⛔ Ваш аккаунт заблокирован.');
52
53
  return;
53
54
  }
55
+
56
+ // Проверка блокировки бота (lock mode)
57
+ const settings = storeManager.get('settings');
58
+ const settingsData = settings.getData();
54
59
 
60
+ if (settingsData.locked && !adminService.isAdmin(userId)) {
61
+ logger.warn({ userId }, 'User blocked by lock mode');
62
+ await ctx.reply('🔒 Бот временно заблокирован администратором. Попробуйте позже.');
63
+ return;
64
+ }
65
+
55
66
  // Регистрация супер-админа (первый пользователь)
56
67
  const isNewSuperAdmin = adminService.registerSuperAdmin(userId);
57
68
  if (isNewSuperAdmin) {
@@ -38,27 +38,32 @@ async function sessionMiddleware(ctx, next) {
38
38
  ctx.state.sessionKey = sessionKey;
39
39
  }
40
40
  } else {
41
- // Групповой чат - поиск сессии по reply или создание новой
42
- const replyToMessageId = ctx.message?.reply_to_message?.message_id;
43
-
44
- if (replyToMessageId) {
45
- // Поиск сессии по сообщению, на которое ответили
46
- const session = sessionService.findByMessage(chatId, replyToMessageId);
47
-
48
- if (session) {
49
- ctx.state.session = session;
50
- ctx.state.sessionKey = `chat:${chatId}`;
51
- ctx.state.replyToSession = true;
52
- }
41
+ // Групповой чат - всегда используем последнюю активную сессию
42
+ const chatSessions = sessionService.getChatSessions(chatId);
43
+ let activeSession = chatSessions.find(s => s.status === 'active');
44
+
45
+ // Если сессии нет - создаём новую
46
+ if (!activeSession) {
47
+ activeSession = sessionService.create({
48
+ userId,
49
+ chatId,
50
+ rootMessageId: ctx.message?.message_id || 1,
51
+ chatType: ctx.chat.type,
52
+ chatTitle: ctx.chat.title,
53
+ });
54
+ }
55
+
56
+ if (activeSession) {
57
+ ctx.state.session = activeSession;
58
+ ctx.state.sessionKey = `chat:${chatId}`;
53
59
  }
54
60
 
55
- // Если сессии нет, ищем последнюю активную сессию чата
56
- if (!ctx.state.session) {
57
- const chatSessions = sessionService.getChatSessions(chatId);
58
- const activeSession = chatSessions.find(s => s.status === 'active');
59
- if (activeSession) {
60
- ctx.state.session = activeSession;
61
- ctx.state.sessionKey = `chat:${chatId}`;
61
+ // Если есть reply, проверяем принадлежит ли оно этой сессии
62
+ const replyToMessageId = ctx.message?.reply_to_message?.message_id;
63
+ if (replyToMessageId && activeSession) {
64
+ // Проверяем есть ли сообщение в дереве сессии
65
+ if (activeSession.message_tree[replyToMessageId]) {
66
+ ctx.state.replyToSession = true;
62
67
  }
63
68
  }
64
69
  }