HollyCorn commited on
Commit
8af90b2
·
verified ·
1 Parent(s): 0d8ae5d

Upload 2 files

Browse files
Files changed (2) hide show
  1. main.py +63 -23
  2. prompts.py +2 -2
main.py CHANGED
@@ -28,6 +28,7 @@ YOOMONEY_WALLET = "4100118637309832"
28
  GROUP_ID = 171587553
29
  ADMIN_ID = 139711548
30
  BUCKET_NAME = "photos"
 
31
 
32
  # Инициализация бота
33
  bot = Bot(token=TOKEN)
@@ -72,12 +73,18 @@ async def download_file(url):
72
  return None
73
 
74
 
75
- def get_user(user_id):
76
  res = supabase.table("users").select("*").eq("id", user_id).execute()
77
  if not res.data:
 
 
 
 
 
78
  new_user = {
79
  "id": user_id, "balance": 0, "free_used": False, "status": "main",
80
- "gender": None, "primary_photo": None, "last_style": None
 
81
  }
82
  supabase.table("users").insert(new_user).execute()
83
  return new_user
@@ -98,12 +105,12 @@ async def is_subscribed(user_id):
98
  def get_main_menu(free_used=False):
99
  kb = Keyboard(one_time=False)
100
  if not free_used:
101
- kb.add(Text("Одна фотография в подарок"), color=KeyboardButtonColor.POSITIVE).row()
102
 
103
- kb.add(Text("Стили фото"), color=KeyboardButtonColor.PRIMARY).row()
104
- kb.add(Text("Творческий режим"), color=KeyboardButtonColor.PRIMARY).row()
105
- kb.add(Text("Замена фото"), color=KeyboardButtonColor.PRIMARY).row()
106
- kb.add(Text("Кошелек"), color=KeyboardButtonColor.PRIMARY).row()
107
  kb.add(Text("🆘 Поддержка"), color=KeyboardButtonColor.PRIMARY)
108
  return kb.get_json()
109
 
@@ -121,6 +128,8 @@ def get_fast_packs_menu():
121
  packs = supabase.table("settings").select("*").eq("is_premium", False).order("price").execute().data
122
  for pack in packs:
123
  kb.add(Text(f"📸 {pack['name']} - {int(pack['price'])} р"), color=KeyboardButtonColor.PRIMARY).row()
 
 
124
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
125
  return kb.get_json()
126
 
@@ -133,33 +142,27 @@ def get_gender_menu():
133
 
134
 
135
  def get_styles_menu(gender, page=1):
136
- # Используем inline=True. Лимит 6 строк и 10 кнопок.
137
  kb = Keyboard(inline=True)
138
  g = gender if gender else "female"
139
 
140
  if g in prompts.FACE_SWAP_STYLES:
141
- all_styles = [s for s in prompts.FACE_SWAP_STYLES[g].keys() if s != "Одна фотография в подарок"]
142
-
143
- # Пагинация: по 6 стилей на страницу
144
  per_page = 6
145
  start = (page - 1) * per_page
146
  end = start + per_page
147
  current_styles = all_styles[start:end]
148
 
149
- # Размещаем по 2 кнопки в ряд
150
  for i in range(0, len(current_styles), 2):
151
  kb.add(Text(current_styles[i]), color=KeyboardButtonColor.PRIMARY)
152
  if i + 1 < len(current_styles):
153
  kb.add(Text(current_styles[i + 1]), color=KeyboardButtonColor.PRIMARY)
154
  kb.row()
155
 
156
- # Кнопки навигации между страницами
157
  if page == 1 and len(all_styles) > per_page:
158
  kb.add(Text("Ещё стили ➡️"), color=KeyboardButtonColor.PRIMARY).row()
159
  elif page > 1:
160
  kb.add(Text("⬅️ Назад к стилям"), color=KeyboardButtonColor.PRIMARY).row()
161
 
162
- # Кнопка возврата
163
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
164
  return kb.get_json()
165
 
@@ -168,7 +171,9 @@ def get_styles_menu(gender, page=1):
168
 
169
  @bot.on.message(text=["Начать", "начать", "Меню", "start", "⬅️ В главное меню"])
170
  async def start_handler(message: Message):
171
- user = get_user(message.from_id)
 
 
172
  supabase.table("users").update({"status": "main"}).eq("id", message.from_id).execute()
173
 
174
  if not user['free_used']:
@@ -188,12 +193,24 @@ async def support_handler(message: Message):
188
  await message.answer("Опишите вашу ситуацию прямо здесь, в чате. Я передам сообщение специалисту.")
189
 
190
 
191
- @bot.on.message(text="Замена фото")
192
  async def photo_change_main_handler(message: Message):
193
  await message.answer("Что вы хотите изменить?", keyboard=get_photo_change_menu())
194
 
195
 
196
- @bot.on.message(text=["Одна фотография в подарок", "✅ Я подписался"])
 
 
 
 
 
 
 
 
 
 
 
 
197
  async def free_trial_handler(message: Message):
198
  user = get_user(message.from_id)
199
 
@@ -232,7 +249,7 @@ async def free_trial_handler(message: Message):
232
  await message.answer("⏳ Генерирую фотографию... Подожди около 30 секунд")
233
 
234
  gender = user['gender']
235
- prompt = prompts.FACE_SWAP_STYLES[gender]["Одна фотография в подарок"]
236
 
237
  paths_to_clean = []
238
  bucket_path, temporary_url = await upload_to_bucket(user['primary_photo'], message.from_id, "src")
@@ -257,7 +274,7 @@ async def free_trial_handler(message: Message):
257
 
258
  promo_text = (
259
  "Теперь ты можешь выбрать один из 10 готовых стилей для фото ✨\n"
260
- "или создать собственный образ в режиме Творца.\n\n"
261
  "Выбирай, с чего начнём 👇"
262
  )
263
  await message.answer(promo_text, keyboard=get_main_menu(True))
@@ -274,7 +291,7 @@ async def free_trial_handler(message: Message):
274
  supabase.storage.from_(BUCKET_NAME).remove(paths_to_clean)
275
 
276
 
277
- @bot.on.message(text=["Кошелек"])
278
  async def balance_handler(message: Message):
279
  user = get_user(message.from_id)
280
  photo_st = "Есть" if user['primary_photo'] else "Нет"
@@ -287,6 +304,8 @@ async def balance_handler(message: Message):
287
 
288
  kb = Keyboard()
289
  kb.add(Text("🛒 Купить генерации"), color=KeyboardButtonColor.POSITIVE).row()
 
 
290
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
291
 
292
  await message.answer(
@@ -302,7 +321,7 @@ async def shop_handler(message: Message):
302
  await message.answer("Выберите количество генераций:", keyboard=get_fast_packs_menu())
303
 
304
 
305
- @bot.on.message(text="Стили фото")
306
  async def styles_handler(message: Message):
307
  user = get_user(message.from_id)
308
  if not user['gender']: return await message.answer("Сначала выберите пол:", keyboard=get_gender_menu())
@@ -327,7 +346,7 @@ async def styles_page_1_back_handler(message: Message):
327
  await message.answer("Первая страница стилей 👇", keyboard=get_styles_menu(user['gender'], page=1))
328
 
329
 
330
- @bot.on.message(text="Творческий режим")
331
  async def creator_mode(message: Message):
332
  user = get_user(message.from_id)
333
  if user['balance'] <= 0:
@@ -423,7 +442,7 @@ async def main_handler(message: Message):
423
 
424
  if text in styles_dict or user['status'] == "wait_custom_prompt":
425
  if user['balance'] <= 0 and user['status'] != "wait_custom_prompt":
426
- if not (text in styles_dict and not user['free_used'] and text == "Одна фотография в подарок"):
427
  return await message.answer("В твоем кошельке 0 генераций. Пополни баланс:",
428
  keyboard=get_fast_packs_menu())
429
 
@@ -492,7 +511,28 @@ def yoomoney_webhook():
492
  packs = supabase.table("settings").select("*").execute().data
493
  for pack in packs:
494
  if abs(received_amount - float(pack['price'])) / float(pack['price']) < 0.05:
 
495
  supabase.rpc("increment_balance", {"user_id": u_id, "amount": pack['amount']}).execute()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  if loop:
497
  asyncio.run_coroutine_threadsafe(bot.api.messages.send(peer_id=u_id, random_id=0,
498
  message=f"✅ Спасибо! Оплата прошла успешно! Теперь выбирай стиль фото в меню"),
 
28
  GROUP_ID = 171587553
29
  ADMIN_ID = 139711548
30
  BUCKET_NAME = "photos"
31
+ REFERRAL_BONUS = 2 # Бонус за первую покупку друга
32
 
33
  # Инициализация бота
34
  bot = Bot(token=TOKEN)
 
73
  return None
74
 
75
 
76
+ def get_user(user_id, ref_id=None):
77
  res = supabase.table("users").select("*").eq("id", user_id).execute()
78
  if not res.data:
79
+ # Логика определения пригласителя
80
+ inviter = None
81
+ if ref_id and str(ref_id).isdigit() and int(ref_id) != user_id:
82
+ inviter = int(ref_id)
83
+
84
  new_user = {
85
  "id": user_id, "balance": 0, "free_used": False, "status": "main",
86
+ "gender": None, "primary_photo": None, "last_style": None,
87
+ "invited_by": inviter, "ref_bonus_done": False
88
  }
89
  supabase.table("users").insert(new_user).execute()
90
  return new_user
 
105
  def get_main_menu(free_used=False):
106
  kb = Keyboard(one_time=False)
107
  if not free_used:
108
+ kb.add(Text("🎁 Одна фотография в подарок"), color=KeyboardButtonColor.POSITIVE).row()
109
 
110
+ kb.add(Text("🖤 Стили фото"), color=KeyboardButtonColor.PRIMARY).row()
111
+ kb.add(Text("Творческий режим"), color=KeyboardButtonColor.PRIMARY).row()
112
+ kb.add(Text("🔄 Замена фото"), color=KeyboardButtonColor.PRIMARY).row()
113
+ kb.add(Text("💰 Кошелек"), color=KeyboardButtonColor.PRIMARY).row()
114
  kb.add(Text("🆘 Поддержка"), color=KeyboardButtonColor.PRIMARY)
115
  return kb.get_json()
116
 
 
128
  packs = supabase.table("settings").select("*").eq("is_premium", False).order("price").execute().data
129
  for pack in packs:
130
  kb.add(Text(f"📸 {pack['name']} - {int(pack['price'])} р"), color=KeyboardButtonColor.PRIMARY).row()
131
+ # Добавляем кнопку бесплатных генераций в самый низ списка пакетов
132
+ kb.add(Text("🎁 Бесплатные генерации"), color=KeyboardButtonColor.PRIMARY).row()
133
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
134
  return kb.get_json()
135
 
 
142
 
143
 
144
  def get_styles_menu(gender, page=1):
 
145
  kb = Keyboard(inline=True)
146
  g = gender if gender else "female"
147
 
148
  if g in prompts.FACE_SWAP_STYLES:
149
+ all_styles = [s for s in prompts.FACE_SWAP_STYLES[g].keys() if s != "🎁 Одна фотография в подарок"]
 
 
150
  per_page = 6
151
  start = (page - 1) * per_page
152
  end = start + per_page
153
  current_styles = all_styles[start:end]
154
 
 
155
  for i in range(0, len(current_styles), 2):
156
  kb.add(Text(current_styles[i]), color=KeyboardButtonColor.PRIMARY)
157
  if i + 1 < len(current_styles):
158
  kb.add(Text(current_styles[i + 1]), color=KeyboardButtonColor.PRIMARY)
159
  kb.row()
160
 
 
161
  if page == 1 and len(all_styles) > per_page:
162
  kb.add(Text("Ещё стили ➡️"), color=KeyboardButtonColor.PRIMARY).row()
163
  elif page > 1:
164
  kb.add(Text("⬅️ Назад к стилям"), color=KeyboardButtonColor.PRIMARY).row()
165
 
 
166
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
167
  return kb.get_json()
168
 
 
171
 
172
  @bot.on.message(text=["Начать", "начать", "Меню", "start", "⬅️ В главное меню"])
173
  async def start_handler(message: Message):
174
+ # Ловим ref_id из сообщения (параметр в ссылке vk.me/bot?ref=ID)
175
+ ref_id = message.ref
176
+ user = get_user(message.from_id, ref_id)
177
  supabase.table("users").update({"status": "main"}).eq("id", message.from_id).execute()
178
 
179
  if not user['free_used']:
 
193
  await message.answer("Опишите вашу ситуацию прямо здесь, в чате. Я передам сообщение специалисту.")
194
 
195
 
196
+ @bot.on.message(text="🔄 Замена фото")
197
  async def photo_change_main_handler(message: Message):
198
  await message.answer("Что вы хотите изменить?", keyboard=get_photo_change_menu())
199
 
200
 
201
+ @bot.on.message(text="🎁 Бесплатные генерации")
202
+ async def free_gens_handler(message: Message):
203
+ link = f"https://vk.me/club{GROUP_ID}?ref={message.from_id}"
204
+ msg = (f"🎁 Получай бесплатные генерации за друзей!\n\n"
205
+ f"Твоя личная ссылка: {link}\n\n"
206
+ f"Как это работает?\n"
207
+ f"1. Отправь эту ссылку другу\n"
208
+ f"2. Когда он совершит свою первую оплату, ты мгновенно получишь +{REFERRAL_BONUS} генерации на свой баланс!\n\n"
209
+ f"Количество друзей не ограничено. Больше друзей — больше фото! ✨")
210
+ await message.answer(msg)
211
+
212
+
213
+ @bot.on.message(text=["🎁 Одна фотография в подарок", "✅ Я подписался"])
214
  async def free_trial_handler(message: Message):
215
  user = get_user(message.from_id)
216
 
 
249
  await message.answer("⏳ Генерирую фотографию... Подожди около 30 секунд")
250
 
251
  gender = user['gender']
252
+ prompt = prompts.FACE_SWAP_STYLES[gender]["🎁 Одна фотография в подарок"]
253
 
254
  paths_to_clean = []
255
  bucket_path, temporary_url = await upload_to_bucket(user['primary_photo'], message.from_id, "src")
 
274
 
275
  promo_text = (
276
  "Теперь ты можешь выбрать один из 10 готовых стилей для фото ✨\n"
277
+ "или создать собственный образ в Творческом режиме.\n\n"
278
  "Выбирай, с чего начнём 👇"
279
  )
280
  await message.answer(promo_text, keyboard=get_main_menu(True))
 
291
  supabase.storage.from_(BUCKET_NAME).remove(paths_to_clean)
292
 
293
 
294
+ @bot.on.message(text=["💰 Кошелек"])
295
  async def balance_handler(message: Message):
296
  user = get_user(message.from_id)
297
  photo_st = "Есть" if user['primary_photo'] else "Нет"
 
304
 
305
  kb = Keyboard()
306
  kb.add(Text("🛒 Купить генерации"), color=KeyboardButtonColor.POSITIVE).row()
307
+ # Кнопка бесплатные генерации в кошелек
308
+ kb.add(Text("🎁 Бесплатные генерации"), color=KeyboardButtonColor.PRIMARY).row()
309
  kb.add(Text("⬅️ В главное меню"), color=KeyboardButtonColor.PRIMARY)
310
 
311
  await message.answer(
 
321
  await message.answer("Выберите количество генераций:", keyboard=get_fast_packs_menu())
322
 
323
 
324
+ @bot.on.message(text="🖤 Стили фото")
325
  async def styles_handler(message: Message):
326
  user = get_user(message.from_id)
327
  if not user['gender']: return await message.answer("Сначала выберите пол:", keyboard=get_gender_menu())
 
346
  await message.answer("Первая страница стилей 👇", keyboard=get_styles_menu(user['gender'], page=1))
347
 
348
 
349
+ @bot.on.message(text="Творческий режим")
350
  async def creator_mode(message: Message):
351
  user = get_user(message.from_id)
352
  if user['balance'] <= 0:
 
442
 
443
  if text in styles_dict or user['status'] == "wait_custom_prompt":
444
  if user['balance'] <= 0 and user['status'] != "wait_custom_prompt":
445
+ if not (text in styles_dict and not user['free_used'] and text == "🎁 Одна фотография в подарок"):
446
  return await message.answer("В твоем кошельке 0 генераций. Пополни баланс:",
447
  keyboard=get_fast_packs_menu())
448
 
 
511
  packs = supabase.table("settings").select("*").execute().data
512
  for pack in packs:
513
  if abs(received_amount - float(pack['price'])) / float(pack['price']) < 0.05:
514
+ # 1. Начисляем баланс самому пользователю
515
  supabase.rpc("increment_balance", {"user_id": u_id, "amount": pack['amount']}).execute()
516
+
517
+ # 2. Логика реферального бонуса
518
+ u_data_res = supabase.table("users").select("invited_by", "ref_bonus_done").eq("id", u_id).execute()
519
+ if u_data_res.data:
520
+ u_data = u_data_res.data[0]
521
+ if u_data['invited_by'] and not u_data['ref_bonus_done']:
522
+ inviter_id = u_data['invited_by']
523
+ # Начисляем бонус тому, кто пригласил
524
+ supabase.rpc("increment_balance",
525
+ {"user_id": inviter_id, "amount": REFERRAL_BONUS}).execute()
526
+ # Помечаем, что бонус за этого реферала выдан
527
+ supabase.table("users").update({"ref_bonus_done": True}).eq("id", u_id).execute()
528
+
529
+ if loop:
530
+ asyncio.run_coroutine_threadsafe(
531
+ bot.api.messages.send(peer_id=inviter_id, random_id=0,
532
+ message=f"🎁 Твой друг совершил первую оплату! Тебе начислено +{REFERRAL_BONUS} бонусных генераций."),
533
+ loop
534
+ )
535
+
536
  if loop:
537
  asyncio.run_coroutine_threadsafe(bot.api.messages.send(peer_id=u_id, random_id=0,
538
  message=f"✅ Спасибо! Оплата прошла успешно! Теперь выбирай стиль фото в меню"),
prompts.py CHANGED
@@ -3,7 +3,7 @@
3
  # Единая база стилей для всех режимов
4
  FACE_SWAP_STYLES = {
5
  "female": {
6
- "Одна фотография в подарок": (
7
  ""
8
  ),
9
  "Портрет": [
@@ -89,7 +89,7 @@ FACE_SWAP_STYLES = {
89
  ]
90
  },
91
  "male": {
92
- "Одна фотография в подарок": (
93
  ""
94
  ),
95
  "Деловой": [
 
3
  # Единая база стилей для всех режимов
4
  FACE_SWAP_STYLES = {
5
  "female": {
6
+ "🎁 Одна фотография в подарок": (
7
  ""
8
  ),
9
  "Портрет": [
 
89
  ]
90
  },
91
  "male": {
92
+ "🎁 Одна фотография в подарок": (
93
  ""
94
  ),
95
  "Деловой": [