Rid3 commited on
Commit
a01d360
·
verified ·
1 Parent(s): bcc6cf2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -51
app.py CHANGED
@@ -3,10 +3,8 @@ import sys
3
  import random
4
  import asyncio
5
  import threading
6
- import requests
7
  from pyrogram import Client, filters, enums
8
  import google.generativeai as genai
9
- from google.api_core import exceptions
10
  from flask import Flask, redirect
11
 
12
  # === КОНФИГУРАЦИЯ ===
@@ -25,99 +23,161 @@ AI_CHAT_KEYS = [
25
  "AIzaSyBjNK3MbrXnggTk2uzV3X-NK2PkT_oYB3M"
26
  ]
27
 
28
- CREATOR = "rid3 (@rid3_yt)"
29
  DOCS_URL = "https://rid3-quiz.web.app/docs/g-bot.html"
30
 
31
  app = Client("google_bot", session_string=SESSION_STRING, api_id=API_ID, api_hash=API_HASH)
32
 
33
- # --- ФУНКЦИЯ УМНОГО ОТВЕТА (С РОТАЦИЕЙ КЛЮЧЕЙ) ---
34
- def get_ai_response(prompt, history_text):
35
- # Перемешиваем ключи, чтобы распределить нагрузку
36
  shuffled_keys = list(AI_CHAT_KEYS)
37
  random.shuffle(shuffled_keys)
38
 
 
39
  system_instruction = (
40
- f"Ты Google Bot. Модель: Gemini 2.5 Flash. Создатель: {CREATOR}. "
41
- "Ты можешь управлять чатом и генерировать фото/музыку. Используй историю для контекста."
 
42
  )
43
- full_prompt = f"{system_instruction}\n\nКОНТЕКСТ:\n{history_text}\n\nЗАПРОС: {prompt}"
44
 
45
  for key in shuffled_keys:
46
  try:
47
  genai.configure(api_key=key)
48
- # Используем 1.5-flash для стабильности, так как у 2.5 слишком малые лимиты (20/день)
49
  model = genai.GenerativeModel('gemini-2.5-flash')
50
- response = model.generate_content(full_prompt)
51
- return response.text
52
- except exceptions.ResourceExhausted:
53
- print(f"⚠️ Ключ {key[:10]}... исчерпал лимит. Пробую следующий...")
54
- continue
55
- except Exception as e:
56
- print(f"❌ Ошибка ключа: {e}")
57
- continue
58
 
59
- return "😴 Все мои API-ключи сейчас отдыхают (превышен лимит). Попробуй чуть позже!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
 
61
  async def fetch_history(chat_id):
62
  messages = []
63
  try:
64
- async for msg in app.get_chat_history(chat_id, limit=15):
65
- sender = msg.from_user.first_name if msg.from_user else "Система"
66
- content = msg.text or "[Медиа]"
67
  messages.append(f"{sender}: {content}")
68
- except: pass
 
69
  return "\n".join(reversed(messages))
70
 
71
  # --- КОМАНДЫ ---
72
  @app.on_message(filters.command("рестарт", prefixes=".") & filters.me)
73
  async def restart_bot(client, message):
74
- await message.edit("🔄 **Перезагрузка Google Bot 2.5...**")
75
  os.execl(sys.executable, sys.executable, *sys.argv)
76
 
77
  @app.on_message(filters.text & ~filters.me)
78
  async def handle_bot(client, message):
79
  text = message.text
80
- is_group = message.chat.type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]
 
 
 
 
81
 
82
- if is_group:
83
- if not text.lower().startswith("@g"): return
84
- user_query = text[2:].strip()
 
 
 
85
  else:
86
- user_query = text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
- if not user_query: return
 
 
89
 
90
  # Эффект печати
91
  await client.send_chat_action(message.chat.id, enums.ChatAction.TYPING)
92
 
 
93
  history = await fetch_history(message.chat.id)
94
- loop = asyncio.get_event_loop()
95
- ai_text = await loop.run_in_executor(None, get_ai_response, user_query, history)
96
-
97
- # Фото-генерация
98
- if any(word in user_query.lower() for word in ["нарисуй", "фото", "изображение"]):
99
- photo_url = f"https://image.pollinations.ai/prompt/{user_query.replace(' ', '%20')}?width=1024&height=1024&nologo=true"
100
- await message.reply_photo(photo_url, caption=f"🎨 **Nano Banana 2**\n\n{ai_text}\n\n👤 Создатель: {CREATOR}")
101
- return
102
-
103
- # Управление чатом
104
- if "закрепи" in user_query.lower():
 
 
105
  try:
106
- target = message.reply_to_message.id if message.reply_to_message else message.id
107
- await client.pin_chat_message(message.chat.id, target)
108
- except: pass
109
-
110
- if "удали" in user_query.lower() and message.reply_to_message:
111
- try: await client.delete_messages(message.chat.id, message.reply_to_message.id)
112
- except: pass
 
113
 
114
 
115
- # === FLASK ===
116
  flask_app = Flask(__name__)
 
117
  @flask_app.route('/')
118
- def index(): return redirect(DOCS_URL)
119
- def run_flask(): flask_app.run(host="0.0.0.0", port=7860)
 
 
 
120
 
121
  if __name__ == "__main__":
122
  threading.Thread(target=run_flask, daemon=True).start()
 
123
  app.run()
 
3
  import random
4
  import asyncio
5
  import threading
 
6
  from pyrogram import Client, filters, enums
7
  import google.generativeai as genai
 
8
  from flask import Flask, redirect
9
 
10
  # === КОНФИГУРАЦИЯ ===
 
23
  "AIzaSyBjNK3MbrXnggTk2uzV3X-NK2PkT_oYB3M"
24
  ]
25
 
26
+ INFO_CHANNEL = "@g_bot_info" # Канал для уведомлений об исчерпании лимитов
27
  DOCS_URL = "https://rid3-quiz.web.app/docs/g-bot.html"
28
 
29
  app = Client("google_bot", session_string=SESSION_STRING, api_id=API_ID, api_hash=API_HASH)
30
 
31
+ # --- ФУНКЦИЯ УМНОГО ОТВЕТА (АСИНХРОННАЯ С РОТАЦИЕЙ КЛЮЧЕЙ) ---
32
+ async def get_ai_response(client, prompt, history_text):
 
33
  shuffled_keys = list(AI_CHAT_KEYS)
34
  random.shuffle(shuffled_keys)
35
 
36
+ # Делаем поведение ИИ более "человечным" и естественным
37
  system_instruction = (
38
+ "Ты умный и живой ИИ-собеседник в Telegram (модель Gemini 2.5 Flash). "
39
+ "Общайся естественно, лаконично, как человек. Без лишней воды, без странного форматирования "
40
+ "и без приветствий в каждом сообщении. Отвечай строго по сути вопроса или поддерживай беседу."
41
  )
42
+ full_prompt = f"ИНСТРУКЦИЯ:\n{system_instruction}\n\nКОНТЕКСТ ДИАЛОГА:\n{history_text}\n\nНОВОЕ СООБЩЕНИЕ:\n{prompt}"
43
 
44
  for key in shuffled_keys:
45
  try:
46
  genai.configure(api_key=key)
 
47
  model = genai.GenerativeModel('gemini-2.5-flash')
 
 
 
 
 
 
 
 
48
 
49
+ # Используем асинхронный вызов, чтобы бот не зависал для других пользователей
50
+ response = await model.generate_content_async(full_prompt)
51
+ return response.text.strip()
52
+
53
+ except Exception as e:
54
+ err_str = str(e).lower()
55
+ # Проверяем ошибки связанные с лимитами
56
+ if "429" in err_str or "quota" in err_str or "exhausted" in err_str:
57
+ print(f"⚠️ Ключ {key[:10]}... исчерпал лимит.")
58
+ continue
59
+ else:
60
+ print(f"❌ Ошибка API: {e}")
61
+ continue
62
+
63
+ # Если цикл закончился и мы здесь — значит все ключи не сработали (лимит)
64
+ try:
65
+ await client.send_message(INFO_CHANNEL, "⚠️ **Внимание!** Лимит всех API-ключей Google Bot на сегодня полностью исчерпан.")
66
+ except Exception as e:
67
+ print(f"Не удалось написать в канал: {e}")
68
+
69
+ return "Мои вычислительные ресурсы на сегодня исчерпаны (лимиты API). Я уже уведомил об этом в своем канале 😴"
70
 
71
+ # --- ПОЛУЧЕНИЕ ИСТОРИИ ---
72
  async def fetch_history(chat_id):
73
  messages = []
74
  try:
75
+ async for msg in app.get_chat_history(chat_id, limit=12):
76
+ sender = msg.from_user.first_name if msg.from_user else "Собеседник"
77
+ content = msg.text or msg.caption or "[Медиа/Стикер]"
78
  messages.append(f"{sender}: {content}")
79
+ except:
80
+ pass
81
  return "\n".join(reversed(messages))
82
 
83
  # --- КОМАНДЫ ---
84
  @app.on_message(filters.command("рестарт", prefixes=".") & filters.me)
85
  async def restart_bot(client, message):
86
+ await message.edit("🔄 **Перезагрузка ИИ...**")
87
  os.execl(sys.executable, sys.executable, *sys.argv)
88
 
89
  @app.on_message(filters.text & ~filters.me)
90
  async def handle_bot(client, message):
91
  text = message.text
92
+ chat_type = message.chat.type
93
+ is_group = chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]
94
+
95
+ user_query = text
96
+ should_respond = False
97
 
98
+ # ТРИГГЕРЫ ДЛЯ ГРУПП
99
+ triggers = ["@g ", "гугл ", "google ", "бот ", "bot "]
100
+
101
+ if not is_group:
102
+ # В личных сообщениях отвечаем всегда
103
+ should_respond = True
104
  else:
105
+ # 1. Отвечаем, если обратились по триггеру
106
+ for t in triggers:
107
+ if text.lower().startswith(t):
108
+ should_respond = True
109
+ user_query = text[len(t):].strip()
110
+ break
111
+
112
+ # 2. Отвечаем, если пользователь сделал "Reply" на наше сообщение
113
+ if not should_respond and message.reply_to_message:
114
+ if message.reply_to_message.from_user and message.reply_to_message.from_user.is_self:
115
+ should_respond = True
116
+ user_query = text.strip()
117
+
118
+ if not should_respond or not user_query:
119
+ return
120
+
121
+ # --- УПРАВЛЕНИЕ ЧАТОМ ---
122
+ action_taken = False
123
+ lower_query = user_query.lower()
124
+
125
+ if "закрепи" in lower_query and message.reply_to_message:
126
+ try:
127
+ await client.pin_chat_message(message.chat.id, message.reply_to_message.id)
128
+ action_taken = True
129
+ except: pass
130
+
131
+ if "удали" in lower_query and message.reply_to_message:
132
+ try:
133
+ await client.delete_messages(message.chat.id, message.reply_to_message.id)
134
+ action_taken = True
135
+ except: pass
136
 
137
+ # Если это была просто короткая команда ("закрепи" или "удали"), не дергаем нейросеть
138
+ if action_taken and len(user_query.split()) <= 2:
139
+ return
140
 
141
  # Эффект печати
142
  await client.send_chat_action(message.chat.id, enums.ChatAction.TYPING)
143
 
144
+ # Получаем контекст и генерируем ответ
145
  history = await fetch_history(message.chat.id)
146
+ ai_text = await get_ai_response(client, user_query, history)
147
+
148
+ # --- ГЕНЕРАЦИЯ ФОТО ---
149
+ photo_triggers = ["нарисуй", "фото", "изображение", "сгенерируй"]
150
+ if any(word in lower_query for word in photo_triggers):
151
+ await client.send_chat_action(message.chat.id, enums.ChatAction.UPLOAD_PHOTO)
152
+
153
+ # Формируем URL. Убираем лишние слова из запроса для Pollinations
154
+ safe_query = user_query.replace(' ', '%20')
155
+ photo_url = f"https://image.pollinations.ai/prompt/{safe_query}?width=1024&height=1024&nologo=true"
156
+
157
+ # Telegram ограничивает подписи к фото (до 1024 символов)
158
+ caption = ai_text[:1000]
159
  try:
160
+ await message.reply_photo(photo_url, caption=caption)
161
+ return
162
+ except Exception:
163
+ # Если генерация фото не удалась, просто отправляем текст
164
+ pass
165
+
166
+ # --- О��ПРАВКА ОТВЕТА ---
167
+ await message.reply_text(ai_text)
168
 
169
 
170
+ # === FLASK ДЛЯ ПОДДЕРЖАНИЯ АКТИВНОСТИ (Replit, Render, HuggingFace) ===
171
  flask_app = Flask(__name__)
172
+
173
  @flask_app.route('/')
174
+ def index():
175
+ return redirect(DOCS_URL)
176
+
177
+ def run_flask():
178
+ flask_app.run(host="0.0.0.0", port=7860)
179
 
180
  if __name__ == "__main__":
181
  threading.Thread(target=run_flask, daemon=True).start()
182
+ print("🤖 Бот успешно запущен!")
183
  app.run()