yeref 0.25.21__py3-none-any.whl → 0.25.23__py3-none-any.whl

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.
yeref/yeref.py CHANGED
@@ -606,9 +606,6 @@ html_template = """<!DOCTYPE html>
606
606
  result = "First, you need to connect a TON wallet"
607
607
  if (lang === "zh") {{ result = "首先,你需要连接一吨钱包"; }}
608
608
  else if (lang === "ar") {{ result = "أولا ، تحتاج إلى توصيل محفظة طن" }}
609
- else if (lang === "es") {{ result = "Primero debe conectar la billetera TON"; }}
610
- else if (lang === "ru") {{ result = "Сначала необходимо подключить TON-кошелек"; }}
611
- else if (lang === "fr") {{ result = "Vous devez d'abord connecter TON portefeuille"; }}
612
609
  return result;
613
610
  }}
614
611
  async function translateClick() {{
@@ -623,18 +620,6 @@ html_template = """<!DOCTYPE html>
623
620
  linkText = "انقر على"
624
621
  hintText = "و 1 شخص عشوائي في العالم سوف تصبح سعيدة"
625
622
  }}
626
- else if (lang === "es") {{
627
- linkText = "Haga clic en"
628
- hintText = "y 1 persona al azar en el mundo será feliz"
629
- }}
630
- else if (lang === "ru") {{
631
- linkText = "Жми на"
632
- hintText = "и 1 случайный человек в мире станет счастливым"
633
- }}
634
- else if (lang === "fr") {{
635
- linkText = "Cliquez sur"
636
- hintText = "et 1 personne au hasard dans le monde sera heureux"
637
- }}
638
623
  return [linkText, hintText];
639
624
  }}
640
625
 
@@ -1168,54 +1153,6 @@ html_donations = """<!DOCTYPE html>
1168
1153
  document.querySelector(".action-get-button").textContent = "أخرج";
1169
1154
  document.querySelector(".action-del-button").textContent = "إزالة";
1170
1155
  }}
1171
- else if (lang === 'es') {{
1172
- document.querySelector(".counter-before").textContent = "Hecho feliz";
1173
- document.querySelector(".counter-after").textContent = "personas";
1174
- document.querySelector(".invoice-before").textContent = "Hacer feliz:";
1175
- document.querySelector(".invoice-after").textContent = "personas";
1176
-
1177
- document.querySelector(".main-before").textContent = "Haga clic en el botón de contrato inteligente";
1178
- document.querySelector(".main-after").textContent = "y en algún lugar del mundo, 1 persona al azar será feliz";
1179
- document.querySelector(".comment-before-button").textContent = "Deseo:";
1180
- document.querySelector(".comment-after-button").textContent = "Generar";
1181
-
1182
- document.getElementById("link").textContent = "Ver transacción";
1183
- document.querySelector(".owner-text").textContent = "Usted ha iniciado sesión como propietario: puede retirar fondos al saldo de la billetera conectada o eliminar el contrato inteligente:";
1184
- document.querySelector(".action-get-button").textContent = "Retirar";
1185
- document.querySelector(".action-del-button").textContent = "Eliminar";
1186
- }}
1187
- else if (lang === 'ru') {{
1188
- document.querySelector(".counter-before").textContent = "Сделаны счастливыми";
1189
- document.querySelector(".counter-after").textContent = "человек";
1190
- document.querySelector(".invoice-before").textContent = "Сделать счастливыми:";
1191
- document.querySelector(".invoice-after").textContent = "человек";
1192
-
1193
- document.querySelector(".main-before").textContent = "Нажми на кнопку смарт-контракта";
1194
- document.querySelector(".main-after").textContent = "и где-то в мире 1 случайный человек станет счастливым";
1195
- document.querySelector(".comment-before-button").textContent = "Пожелание:";
1196
- document.querySelector(".comment-after-button").textContent = "Генерировать";
1197
-
1198
- document.getElementById("link").textContent = "Посмотреть транзакцию";
1199
- document.querySelector(".owner-text").textContent = "Вы зашли как владелец: можно вывести средства на баланс подключенного кошелька или удалить смарт-контракт:";
1200
- document.querySelector(".action-get-button").textContent = "Вывести";
1201
- document.querySelector(".action-del-button").textContent = "Удалить";
1202
- }}
1203
- else if (lang === 'fr') {{
1204
- document.querySelector(".counter-before").textContent = "Fait heureux";
1205
- document.querySelector(".counter-after").textContent = "personnes";
1206
- document.querySelector(".invoice-before").textContent = "Rendre heureux:";
1207
- document.querySelector(".invoice-after").textContent = "personnes";
1208
-
1209
- document.querySelector(".main-before").textContent = "Cliquez sur le bouton du contrat intelligent";
1210
- document.querySelector(".main-after").textContent = "et quelque part dans le monde, 1 personne au hasard deviendra heureuse";
1211
- document.querySelector(".comment-before-button").textContent = "Vœu:";
1212
- document.querySelector(".comment-after-button").textContent = "Générer";
1213
-
1214
- document.getElementById("link").textContent = "Voir la transaction";
1215
- document.querySelector(".owner-text").textContent = "Vous êtes connecté en tant que propriétaire: vous pouvez retirer des fonds sur le solde du portefeuille connecté ou supprimer le contrat intelligent:";
1216
- document.querySelector(".action-get-button").textContent = "Retirer";
1217
- document.querySelector(".action-del-button").textContent = "Supprimer";
1218
- }}
1219
1156
  else {{
1220
1157
  document.querySelector(".counter-before").textContent = "Made happy";
1221
1158
  document.querySelector(".counter-after").textContent = "people";
@@ -1353,15 +1290,6 @@ html_donations = """<!DOCTYPE html>
1353
1290
  else if (savedLang === "ar") {{
1354
1291
  result = "أولا ، تحتاج إلى توصيل محفظة طن"
1355
1292
  }}
1356
- else if (savedLang === "es") {{
1357
- result = "Primero debe conectar la billetera TON"
1358
- }}
1359
- else if (savedLang === "ru") {{
1360
- result = "Сначала необходимо подключить TON-кошелек"
1361
- }}
1362
- else if (savedLang === "fr") {{
1363
- result = "Vous devez d'abord connecter TON portefeuille"
1364
- }}
1365
1293
  return result;
1366
1294
  }}
1367
1295
 
@@ -1618,24 +1546,6 @@ html_cpay = """<!DOCTYPE html>
1618
1546
  </div>
1619
1547
  </div>
1620
1548
 
1621
- <div class="address-wallet">
1622
- <div class="address-wallet-text">Адрес коллекции монет:*</div>
1623
- <div class="address-wallet-input"><input type="text" id="address-wallet-input-id" minlength="48"
1624
- maxlength="48" placeholder="for other currencies">
1625
- </div>
1626
- </div>
1627
- <div class="address-collection">
1628
- <div class="address-collection-text">Адрес коллекции NFT:*</div>
1629
- <div class="address-collection-input"><input type="text" id="address-collection-input-id" minlength="48"
1630
- maxlength="48" placeholder="for NFT checking">
1631
- </div>
1632
- </div>
1633
- <div class="optional">*не обязательные поля</div>
1634
- <div class="sticker">
1635
- <tgs-player id="lottie" autoplay loop mode="normal"
1636
- src="https://raw.githubusercontent.com/fereysitnerya/ferey/main/AnimatedSticker.tgs">
1637
- </tgs-player>
1638
- </div>
1639
1549
  </div>
1640
1550
  <script>
1641
1551
  let tg = window.Telegram.WebApp
@@ -2563,15 +2473,13 @@ async def db_select(sql, param=None, db=None):
2563
2473
  await con.create_function("LOWER", 1, sqlite_lower)
2564
2474
  async with con.execute(sql, param or ()) as cur:
2565
2475
  result = await cur.fetchall()
2566
- break # Успешное выполнение, выходим из цикла
2476
+ break
2567
2477
  except Exception as e:
2568
2478
  logger.info(log_ % str(e))
2569
- # Прекратить попытки при критической ошибке
2570
2479
  if 'no such column' in str(e) or 'unable to open database' in str(e) or 'no such table' in str(e):
2571
2480
  return result
2572
2481
  await asyncio.sleep(round(random.uniform(1, 2), 2))
2573
2482
  retry -= 1
2574
- # Выполняем VACUUM только при оставшихся попытках
2575
2483
  if retry > 0:
2576
2484
  async with aiosqlite.connect(db) as con:
2577
2485
  await con.execute("VACUUM")
@@ -2599,8 +2507,7 @@ async def db_change(sql, param=None, db=None):
2599
2507
  e) or 'no such table' in str(e):
2600
2508
  return
2601
2509
  await asyncio.sleep(round(random.uniform(1, 2), 2))
2602
- retry -= 1 # Уменьшить количество попыток
2603
- # Только после уменьшения `retry` вызвать VACUUM
2510
+ retry -= 1
2604
2511
  if retry > 0:
2605
2512
  print(f'start VACUUM, {db=}, {sql=}, {param=}')
2606
2513
  async with aiosqlite.connect(db) as con:
@@ -4366,7 +4273,6 @@ async def pst_gen_ent2(bot, chat_id, lc, lz, page, POST_TID, POST_TYPE, POST_MED
4366
4273
  async with aiofiles.open(dst, "wb") as f:
4367
4274
  await f.write(base64.b64decode(lst[0]['answer']))
4368
4275
  else:
4369
- print(f"получается мы тут {lst[0]['answer']=}")
4370
4276
  async with aiohttp.ClientSession() as session:
4371
4277
  async with session.get(lst[0]['answer']) as response:
4372
4278
  res = await response.read()
@@ -4484,7 +4390,6 @@ async def pst_gen_ent2(bot, chat_id, lc, lz, page, POST_TID, POST_TYPE, POST_MED
4484
4390
  if os.path.exists(dst_new): os.remove(dst_new)
4485
4391
  else:
4486
4392
  if BOT_TOKEN:
4487
- print(f"заходим сюда")
4488
4393
  extra_bot = Bot(token=BOT_TOKEN)
4489
4394
  res = await extra_bot.send_photo(chat_id=chat_id, photo=types.FSInputFile(dst))
4490
4395
  await extra_bot.delete_message(chat_id, res.message_id)
@@ -4796,7 +4701,7 @@ async def g4f_chat_completion(result_txt):
4796
4701
  # client = Client()
4797
4702
  # response = client.chat.completions.create(
4798
4703
  # model="gpt-4o-mini",
4799
- # # messages=[{"role": "user", "content": "Как много ног у кота?"}],
4704
+ # # messages=[{"role": "user", "content": "How many legs does a cat have?"}],
4800
4705
  # messages=result_txt,
4801
4706
  # web_search=False
4802
4707
  # )
@@ -5195,15 +5100,14 @@ async def outsource_generate(lst, path='link_path'):
5195
5100
  }
5196
5101
 
5197
5102
  async with aiohttp.ClientSession() as session:
5198
- print("Отправка запроса на генерацию изображения...")
5199
5103
  async with session.post(url, json=payload, headers=headers) as response:
5200
5104
  res = await response.json()
5201
5105
  job_id = res.get("id")
5202
5106
  if not job_id:
5203
- print("Ошибка: Job ID не получен")
5107
+ print("no job id")
5204
5108
  return
5205
5109
 
5206
- print(f"Задача принята, Job ID: {job_id}")
5110
+ print(f"Job ID: {job_id}")
5207
5111
 
5208
5112
  attempts = 7
5209
5113
  status_url = f'https://stablehorde.net/api/v2/generate/status/{job_id}'
@@ -5212,27 +5116,26 @@ async def outsource_generate(lst, path='link_path'):
5212
5116
  while attempts > 0:
5213
5117
  async with session.get(status_url, headers=headers) as response:
5214
5118
  res = await response.json()
5215
- print(f"Статус задачи: {res}")
5119
+ print(f"Staus: {res}")
5216
5120
 
5217
- queue_position = res.get("queue_position", "неизвестно")
5218
- wait_time = res.get("wait_time", "неизвестно")
5219
- print(
5220
- f"Позиция в очереди: {queue_position}, ожидаемое время: {wait_time} сек.")
5121
+ queue_position = res.get("queue_position", "unknown")
5122
+ wait_time = res.get("wait_time", "unknown")
5123
+ print(f"Queue {queue_position=}: {wait_time=} sec.")
5221
5124
 
5222
5125
  if "generations" in res and res["generations"]:
5223
5126
  r_img = res["generations"][0]["img"]
5224
5127
  if str(r_img).endswith('.png'):
5225
5128
  r_img = f"{r_img}.png"
5226
5129
 
5227
- print(f"Изображение готово: {r_img}")
5130
+ print(f"ready{r_img}")
5228
5131
  result.append({'type': item['type'], 'answer': r_img})
5229
5132
  return
5230
5133
 
5231
5134
  attempts -= 1
5232
- print(f"Попытка {7 - attempts} не удалась, ждем 4 секунды...")
5135
+ print(f"Try {7 - attempts} fail, waiit 4 sec...")
5233
5136
  await asyncio.sleep(4)
5234
5137
 
5235
- print("Все попытки исчерпаны, изображение не было получено.")
5138
+ print("err")
5236
5139
  elif provider_name == 'fusionbrain':
5237
5140
  # continue
5238
5141
  api_key = provider_keys[0]["API_KEY"]
@@ -5244,11 +5147,11 @@ async def outsource_generate(lst, path='link_path'):
5244
5147
  'X-Secret': f'Secret {secret_key}',
5245
5148
  }
5246
5149
 
5247
- # модели res=[{'id': 4, 'name': 'Kandinsky', 'version': 3.1,}]
5150
+ # models res=[{'id': 4, 'name': 'Kandinsky', 'version': 3.1,}]
5248
5151
  # async with aiohttp.ClientSession() as session:
5249
5152
  # async with session.get(url + 'models', headers=headers) as response:
5250
5153
  # res = await response.json()
5251
- # print(f"модели {res=}")
5154
+ # print(f"models {res=}")
5252
5155
  # model_id = res[0]['id']
5253
5156
 
5254
5157
  model_id = 4
@@ -5269,11 +5172,10 @@ async def outsource_generate(lst, path='link_path'):
5269
5172
  async with session.post(u_, headers=headers, data=data) as response:
5270
5173
  res = await response.json()
5271
5174
  if 'uuid' not in res:
5272
- print("Ошибка: в ответе нет 'uuid'", res)
5175
+ print("no'uuid'", res)
5273
5176
  return
5274
5177
  job_id = res['uuid']
5275
5178
 
5276
- # Проверяем статус генерации
5277
5179
  attempts = 15
5278
5180
  status_url = url_ + f'text2image/status/{job_id}'
5279
5181
  await asyncio.sleep(10)
@@ -5283,7 +5185,7 @@ async def outsource_generate(lst, path='link_path'):
5283
5185
  async with session.get(status_url, headers=headers) as response:
5284
5186
  res = await response.json()
5285
5187
  if res['status'].lower() == 'done':
5286
- base64_img = res['images'][0] # Получаем base64 картинку
5188
+ base64_img = res['images'][0]
5287
5189
  result.append({'type': item['type'], 'answer': base64_img})
5288
5190
  return
5289
5191
  attempts -= 1
@@ -5937,12 +5839,12 @@ async def outsource_handle_old(lst, path='link_path'):
5937
5839
  try:
5938
5840
  if not api_key: break
5939
5841
  client = AsyncOpenAI(api_key=api_key)
5940
- # alloy - между мужчиной и женщиной
5941
- # echo - дурацкий русский
5942
- # fable - среднее между alloy и echo
5943
- # onyx - низкий голос (неплохой)
5944
- # nova - такая 32 летняя девушка
5945
- # shimmer - между мужчиной и женщиной
5842
+ # alloy - between male and female
5843
+ # echo - stupid rus
5844
+ # fable - between alloy and echo
5845
+ # onyx - lowe voice (not bad)
5846
+ # nova - 32 years old girl
5847
+ # shimmer - between male and female
5946
5848
  input_ = str(item['prompt'].replace('```py\n', ''))
5947
5849
  print(f"{input_=}")
5948
5850
  response = await client.audio.speech.create(model='tts-1',
@@ -6448,7 +6350,6 @@ async def resize_to_max_side(input_image_path, target_max_side, mem_type='regula
6448
6350
  target_max_side = int(target_max_side)
6449
6351
 
6450
6352
  if mem_type == 'custom_emoji':
6451
- # Для custom_emoji масштабируем изображение, сохраняя пропорции
6452
6353
  if width > height:
6453
6354
  new_width = 100
6454
6355
  new_height = int((100 / width) * height)
@@ -6459,20 +6360,16 @@ async def resize_to_max_side(input_image_path, target_max_side, mem_type='regula
6459
6360
  resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
6460
6361
  resized_img = resized_img.convert("RGBA")
6461
6362
 
6462
- # Создаем прозрачный фон 100x100 (RGBA с прозрачностью)
6463
6363
  final_img = Image.new("RGBA", (100, 100), (0, 0, 0, 0))
6464
6364
 
6465
- # Вставляем изображение по центру прозрачного фона
6466
6365
  x_offset = (100 - new_width) // 2
6467
6366
  y_offset = (100 - new_height) // 2
6468
6367
  final_img.paste(resized_img, (x_offset, y_offset), resized_img)
6469
6368
 
6470
- # Сохраняем итоговое изображение с прозрачным фоном
6471
6369
  final_img.save(input_image_path)
6472
6370
 
6473
6371
  result_width, result_height = 100, 100
6474
6372
  else:
6475
- # Обычное поведение для других mem_type
6476
6373
  if width > height:
6477
6374
  new_width = target_max_side
6478
6375
  new_height = int((target_max_side / width) * height)
@@ -6488,15 +6385,12 @@ async def resize_to_max_side(input_image_path, target_max_side, mem_type='regula
6488
6385
  if resized_width != target_max_side and resized_height != target_max_side or black_frame:
6489
6386
  final_img = Image.new("RGBA", (target_max_side, target_max_side), (0, 0, 0, 0))
6490
6387
 
6491
- # Вставляем изменённое изображение по центру
6492
6388
  x_offset = (target_max_side - resized_width) // 2
6493
6389
  y_offset = (target_max_side - resized_height) // 2
6494
6390
  final_img.paste(resized_img, (x_offset, y_offset), resized_img)
6495
6391
 
6496
- # Сохраняем изображение с чёрным фоном
6497
6392
  final_img.save(input_image_path)
6498
6393
  else:
6499
- # Сохраняем изображение без фона, если одна из сторон равна target_max_side
6500
6394
  resized_img.save(input_image_path)
6501
6395
 
6502
6396
  result_width, result_height = resized_width, resized_height
@@ -7325,7 +7219,7 @@ async def get_link_for_media(bot, chat_id, file_path, KEYS_JSON, is_del=True):
7325
7219
  # base_name = str(os.path.basename(file_path).replace(' ', '').replace('!', ''))
7326
7220
  base_name = str(os.path.basename(file_path))
7327
7221
  base_name = base_name.replace("\xa0", "").encode("ascii", "ignore").decode("ascii")
7328
- # base_name = base_name.replace("\xa0", " ") # Заменяем \xa0 на обычный пробел
7222
+ # base_name = base_name.replace("\xa0", " ") # replace \xa0 to usual space
7329
7223
  base_name = base_name.encode("utf-8", "ignore").decode("utf-8")
7330
7224
  base_name = re.sub(r"[^\w\-.]", "", base_name)
7331
7225
  random_suffix = datetime.now(timezone.utc).strftime('%f')
@@ -7433,8 +7327,8 @@ async def get_smc_info(address, KEYS_JSON, is_test_only=False):
7433
7327
  # items = [item1, item2, item3]
7434
7328
 
7435
7329
  items = []
7436
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
7437
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7330
+ for provider, keys in data["ton"].items():
7331
+ for _ in keys:
7438
7332
  if provider == "tonapi":
7439
7333
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
7440
7334
  if key:
@@ -7523,7 +7417,7 @@ async def get_wallet_address(address, master, KEYS_JSON, is_test_only=False, is_
7523
7417
  # {'accept': 'application/json',
7524
7418
  # 'Authorization': 'Bearer AFPJTKEBPOX3AIYAAAAKA2HWOTRNJP5MUCV5DMDCZAAOCPSAYEYS3CILNQVLF2HWKED6USY'}]
7525
7419
  # items = [item1, item2, item3]
7526
- # items = [item2] этой фукнции
7420
+ # items = [item2]
7527
7421
 
7528
7422
  print(f"1, {is_TON=}, {address=}, {master=}, {KEYS_JSON=}, ")
7529
7423
  items = []
@@ -7637,8 +7531,8 @@ async def get_nft_data(address, KEYS_JSON, is_test_only=False, help_link=None):
7637
7531
  # items = [item2]
7638
7532
 
7639
7533
  items = []
7640
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
7641
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7534
+ for provider, keys in data["ton"].items():
7535
+ for _ in keys:
7642
7536
  if provider == "tonapi":
7643
7537
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
7644
7538
  if key:
@@ -7808,8 +7702,8 @@ async def get_collection_data(address, KEYS_JSON, is_test_only=False):
7808
7702
  # # items = [item2]
7809
7703
 
7810
7704
  items = []
7811
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
7812
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7705
+ for provider, keys in data["ton"].items():
7706
+ for _ in keys:
7813
7707
  if provider == "tonapi":
7814
7708
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
7815
7709
  if key:
@@ -7936,8 +7830,8 @@ async def get_nft_in_account(address, collection, KEYS_JSON, is_test_only=False,
7936
7830
  # # items = [item2]
7937
7831
 
7938
7832
  items = []
7939
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
7940
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7833
+ for provider, keys in data["ton"].items():
7834
+ for _ in keys:
7941
7835
  if provider == "tonapi":
7942
7836
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
7943
7837
  if key:
@@ -8008,8 +7902,8 @@ async def get_any_activity(address, KEYS_JSON, is_test_only=False):
8008
7902
  data = json.loads(await f.read())
8009
7903
 
8010
7904
  items = []
8011
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
8012
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7905
+ for provider, keys in data["ton"].items():
7906
+ for _ in keys:
8013
7907
  if provider == "tonapi":
8014
7908
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
8015
7909
  if key:
@@ -8087,8 +7981,8 @@ async def get_any_nfts(address, KEYS_JSON, is_test_only=False):
8087
7981
  data = json.loads(await f.read())
8088
7982
 
8089
7983
  items = []
8090
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
8091
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
7984
+ for provider, keys in data["ton"].items():
7985
+ for _ in keys:
8092
7986
  if provider == "tonapi":
8093
7987
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
8094
7988
  if key:
@@ -8165,8 +8059,8 @@ async def get_any_jettons(address, KEYS_JSON, is_test_only=False):
8165
8059
  data = json.loads(await f.read())
8166
8060
 
8167
8061
  items = []
8168
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
8169
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
8062
+ for provider, keys in data["ton"].items():
8063
+ for _ in keys:
8170
8064
  if provider == "tonapi":
8171
8065
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
8172
8066
  if key:
@@ -8254,8 +8148,8 @@ async def calculate_wallet_address(owner, master, KEYS_JSON, is_test_only=False)
8254
8148
  data = json.loads(await f.read())
8255
8149
 
8256
8150
  items = []
8257
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
8258
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
8151
+ for provider, keys in data["ton"].items():
8152
+ for _ in keys:
8259
8153
  if provider == "tonapi": # continue
8260
8154
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
8261
8155
 
@@ -8329,8 +8223,8 @@ async def get_method_data(address, KEYS_JSON, is_test_only=False, method_name='g
8329
8223
  data = json.loads(await f.read())
8330
8224
 
8331
8225
  items = []
8332
- for provider, keys in data["ton"].items(): # provider = "tonapi" или "toncenter"
8333
- for _ in keys: # it = {"all": "..."} или {"testnet": "..."}
8226
+ for provider, keys in data["ton"].items():
8227
+ for _ in keys:
8334
8228
  if provider == "tonapi":
8335
8229
  key = random.choice([it['all'] for it in keys if 'all' in it]) if keys else None
8336
8230
  if key:
@@ -8456,7 +8350,6 @@ async def check_webapp_hash(init_data, TOKEN_BOT, BOT_TOKEN_MAIN=None, extra=Non
8456
8350
  # print(f'seconds {(datetime.now() - auth_date).seconds}', init_data)
8457
8351
  # if (datetime.now() - auth_date).seconds > 2000 or "hash" not in parsed_data: return
8458
8352
  if (datetime.now() - auth_date).seconds > 20000 or "hash" not in parsed_data: return
8459
- # какой смысл не делать с BOT_TOKEN_MAIN, если он используется в srv_bot_add и srv_app_upd
8460
8353
 
8461
8354
  hash_ = parsed_data.pop("hash")
8462
8355
  data_check_string = "\n".join(f"{k}={v}" for k, v in sorted(parsed_data.items(), key=itemgetter(0)))
@@ -9466,7 +9359,6 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9466
9359
  months = ["2025-06", "2025-07", "2025-08", "2025-09"]
9467
9360
  data_users = []
9468
9361
  for _ in range(30):
9469
- # дата входа
9470
9362
  entry_month = random.choice(months)
9471
9363
  entry_day = random.randint(1, 28)
9472
9364
  entry_date = f"{entry_month}-{entry_day:02}"
@@ -9474,7 +9366,6 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9474
9366
  entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
9475
9367
  utm = random.choice(["/start", "/startapp"])
9476
9368
 
9477
- # месяцы от входа и дальше
9478
9369
  valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
9479
9370
  if not valid_months:
9480
9371
  valid_months = [entry_month]
@@ -9483,7 +9374,6 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9483
9374
  user_dau_dates = set()
9484
9375
  txs, payments = [], []
9485
9376
 
9486
- # платеж
9487
9377
  if user_mau:
9488
9378
  pay_month = random.choice(user_mau)
9489
9379
  pay_day = random.randint(1, 28)
@@ -9497,7 +9387,6 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9497
9387
  }]
9498
9388
  user_dau_dates.add(pay_date)
9499
9389
 
9500
- # вход в приложение
9501
9390
  user_dau_dates.add(entry_date)
9502
9391
  for m in user_mau:
9503
9392
  day = random.randint(1, 28)
@@ -9506,9 +9395,8 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9506
9395
  if dt_visit >= entry_dt_obj and random.random() < 0.7:
9507
9396
  user_dau_dates.add(visit)
9508
9397
 
9509
- # статусы (отток) с низкой вероятностью
9510
9398
  USER_STATUSES = []
9511
- if random.random() < 0.2: # 10% шанс оттока
9399
+ if random.random() < 0.2:
9512
9400
  churn_month = random.choice(valid_months)
9513
9401
  churn_day = random.randint(1, 28)
9514
9402
  churn_date = f"{churn_month}-{churn_day:02}"
@@ -9532,44 +9420,38 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9532
9420
  r4 = await return_retention_metrics(bot, data_users, EXTRA_D)
9533
9421
  r5 = await return_profit_and_loss_metrics(bot, data_users, EXTRA_D)
9534
9422
 
9535
- # --- Начинаем сразу с объединённого цикла по всем метрикам r1–r5 ---
9536
9423
  metrics_paths = [r1, r2, r3, r4, r5]
9537
9424
  tables = []
9538
9425
 
9539
- # 1) Собираем существующие CSV-файлы
9540
9426
  for path in metrics_paths:
9541
9427
  if path and os.path.isfile(path):
9542
9428
  basename = os.path.basename(path)
9543
9429
  with open(path, newline='', encoding='utf-8') as csvfile:
9544
9430
  reader = csv.reader(csvfile)
9545
9431
  rows = list(reader)
9546
- logger.info(f"Найден файл '{basename}', строк = {len(rows)}.")
9432
+ logger.info(f"File found: '{basename}', lines = {len(rows)}.")
9547
9433
  tables.append({'name': basename, 'rows': rows})
9548
9434
  else:
9549
- logger.warning(f"Файл не найден или не существует: {path}")
9435
+ logger.warning(f"no file: {path}")
9550
9436
 
9551
- # 2) Если ни одного CSV не обнаружено, выходим
9552
9437
  if not tables:
9553
- logger.warning("Ни один CSV-файл не найден. Прерываем запись.")
9438
+ logger.warning("no csv")
9554
9439
  else:
9555
- # 3) Авторизация в Google Sheets
9556
9440
  scopes = r_conf('scopes', CONF_P)
9557
9441
  credential_path = os.path.join(EXTRA_D, (r_conf('credential_file', CONF_P))[0])
9558
9442
  credentials = ServiceAccountCredentials.from_json_keyfile_name(credential_path, scopes)
9559
9443
  http_auth = credentials.authorize(httplib2.Http())
9560
9444
  sheets_service = build('sheets', 'v4', http=http_auth, cache_discovery=False)
9561
9445
 
9562
- # 4) Получаем metadata, ищем лист с названием PROJECT_USERNAME
9563
9446
  spreadsheet = sheets_service.spreadsheets().get(spreadsheetId=dataroom_folder_id).execute()
9564
9447
  sheet_id_target = None
9565
9448
  for sheet in spreadsheet.get('sheets', []):
9566
9449
  props = sheet.get('properties', {})
9567
9450
  if props.get('title') == PROJECT_USERNAME:
9568
9451
  sheet_id_target = props.get('sheetId')
9569
- logger.info(f"Найден существующий лист '{PROJECT_USERNAME}', sheetId={sheet_id_target}")
9452
+ logger.info(f"Already exists '{PROJECT_USERNAME}', sheetId={sheet_id_target}")
9570
9453
  break
9571
9454
 
9572
- # 5) Если листа нет — создаём новый лист с названием PROJECT_USERNAME
9573
9455
  if sheet_id_target is None:
9574
9456
  add_request = {
9575
9457
  'requests': [
@@ -9587,38 +9469,33 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9587
9469
  body=add_request
9588
9470
  ).execute()
9589
9471
  sheet_id_target = response['replies'][0]['addSheet']['properties']['sheetId']
9590
- logger.info(f"Создан новый лист '{PROJECT_USERNAME}', sheetId={sheet_id_target}")
9472
+ logger.info(f"Done new sheet '{PROJECT_USERNAME}', sheetId={sheet_id_target}")
9591
9473
 
9592
- # 6) Готовим запросы для записи всех таблиц одна за другой с промежутком
9593
9474
  safe_title = PROJECT_USERNAME.replace("'", "\\'")
9594
- offset = 1 # первая строка, с которой начнём писать
9475
+ offset = 1
9595
9476
  data_requests = []
9596
9477
 
9597
9478
  for tbl in tables:
9598
- # 6.1) Заголовок: имя CSV-файла
9599
9479
  header_range = f"'{safe_title}'!A{offset}"
9600
9480
  data_requests.append({
9601
9481
  'range': header_range,
9602
9482
  'majorDimension': 'ROWS',
9603
9483
  'values': [[tbl['name']]]
9604
9484
  })
9605
- logger.info(f"Добавлен заголовок '{tbl['name']}' → A{offset}")
9485
+ logger.info(f"Added '{tbl['name']}' → A{offset}")
9606
9486
  offset += 1
9607
9487
 
9608
- # 6.2) Содержимое CSV: все строки сразу под заголовком
9609
9488
  data_range = f"'{safe_title}'!A{offset}"
9610
9489
  data_requests.append({
9611
9490
  'range': data_range,
9612
9491
  'majorDimension': 'ROWS',
9613
9492
  'values': tbl['rows']
9614
9493
  })
9615
- logger.info(f"Добавлены {len(tbl['rows'])} строк из '{tbl['name']}' → A{offset}")
9494
+ logger.info(f"Added {len(tbl['rows'])} lines from '{tbl['name']}' → A{offset}")
9616
9495
  offset += len(tbl['rows'])
9617
9496
 
9618
- # 6.3) Оставляем минимум 2 пустые строки перед следующей таблицей
9619
9497
  offset += 2
9620
9498
 
9621
- # 7) Выполняем единый batchUpdate для всех data_requests
9622
9499
  write_body = {
9623
9500
  'valueInputOption': 'USER_ENTERED',
9624
9501
  'data': data_requests
@@ -9629,9 +9506,9 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
9629
9506
  body=write_body
9630
9507
  ).execute()
9631
9508
  total_cells = response.get('totalUpdatedCells', 0)
9632
- logger.info(f"Успешно записано в Google Sheets: всего обновлено ячеек = {total_cells}.")
9509
+ logger.info(f"Success = {total_cells}.")
9633
9510
  except Exception as e:
9634
- logger.error(f"Ошибка при записи всех таблиц в Google Sheets: {e}")
9511
+ logger.error(f"Err Google Sheets: {e}")
9635
9512
  except Exception as e:
9636
9513
  logger.info(log_ % str(e))
9637
9514
  await asyncio.sleep(round(random.uniform(0, 1), 2))
@@ -9898,15 +9775,13 @@ async def return_cohort_metrics(bot, data_users, EXTRA_D):
9898
9775
  cohort_months = sorted(cohorts.keys())
9899
9776
  num_months = len(cohort_months)
9900
9777
 
9901
- # Собираем таблицу посменно по календарным месяцам
9902
9778
  table = []
9903
- header = ["Месяц/Когорта"]
9779
+ header = ["Mo/Cohort"]
9904
9780
  for mo in cohort_months:
9905
9781
  header.append(f"{mo} ({len(cohorts[mo])})")
9906
9782
  header.append("∑")
9907
9783
  table.append(header)
9908
9784
 
9909
- # Матрица для подсчёта retention (counts[i][j] = активных из когорты j в календарном месяце i)
9910
9785
  counts = [[0] * num_months for _ in range(num_months)]
9911
9786
  for i in range(num_months):
9912
9787
  calendar_mo = cohort_months[i]
@@ -9920,10 +9795,8 @@ async def return_cohort_metrics(bot, data_users, EXTRA_D):
9920
9795
 
9921
9796
  cohort_mo = cohort_months[j]
9922
9797
  if i == j:
9923
- # первый месяц когорты
9924
9798
  val = len(cohorts[cohort_mo])
9925
9799
  else:
9926
- # считаем, сколько из когорты j активны в календарном месяце i
9927
9800
  val = sum(1 for uid in cohorts[cohort_mo] if calendar_mo in activity_months.get(uid, set()))
9928
9801
 
9929
9802
  counts[i][j] = val
@@ -9936,7 +9809,6 @@ async def return_cohort_metrics(bot, data_users, EXTRA_D):
9936
9809
  row.append(str(row_sum))
9937
9810
  table.append(row)
9938
9811
 
9939
- # Считаем средний ежемесячный churn
9940
9812
  total_lost = 0
9941
9813
  total_start = 0
9942
9814
  for j in range(num_months):
@@ -9998,7 +9870,6 @@ async def return_retention_metrics(bot, data_users, EXTRA_D):
9998
9870
  if not cohort_months:
9999
9871
  return
10000
9872
 
10001
- # Функция прибавления месяцев
10002
9873
  def add_months(mo_str, n):
10003
9874
  y, m = map(int, mo_str.split("-"))
10004
9875
  total = m + n
@@ -10012,7 +9883,7 @@ async def return_retention_metrics(bot, data_users, EXTRA_D):
10012
9883
  f_name = os.path.join(EXTRA_D, "4_retention_metrics.csv")
10013
9884
  with open(f_name, "w", newline="", encoding="utf-8") as f:
10014
9885
  writer = csv.writer(f)
10015
- header = ["Месяц/Когорта"] + [
9886
+ header = ["Mo/Cohort"] + [
10016
9887
  f"{c} ({len(cohort_users[c])})" for c in cohort_months
10017
9888
  ] + ["∑"]
10018
9889
  writer.writerow(header)
@@ -10065,7 +9936,6 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
10065
9936
  try:
10066
9937
  metrics = defaultdict(lambda: {"sum_amount": 0.0})
10067
9938
 
10068
- # Собираем данные по месяцам
10069
9939
  for USER_TID, USER_VARS, USER_LSTS in data_users:
10070
9940
  USER_LSTS = json.loads(USER_LSTS or "{}")
10071
9941
  USER_PAYMENTS = USER_LSTS.get("USER_PAYMENTS", [])
@@ -10076,11 +9946,9 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
10076
9946
  amt = float(pay.get("AMOUNT", 0)) * 0.013
10077
9947
  metrics[mo_p]["sum_amount"] += amt
10078
9948
 
10079
- # Функция форматирования с запятой
10080
9949
  def fmt(x):
10081
9950
  return f"{x:.2f}".rstrip("0").rstrip(".").replace(".", ",") if x is not None else ""
10082
9951
 
10083
- # Сортируем месяцы
10084
9952
  months_sorted = sorted(metrics.keys())
10085
9953
  results = []
10086
9954
  np_values = []
@@ -10092,7 +9960,7 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
10092
9960
  OPEX = 4.5
10093
9961
  OP = GP - OPEX
10094
9962
 
10095
- # комиссия 30% и обмен 1%
9963
+ # commision 30%, exchange 1%
10096
9964
  after_comm = OP * 0.70
10097
9965
  after_fiat = after_comm * 0.99
10098
9966
  COMM = OP - after_comm
@@ -10112,24 +9980,19 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
10112
9980
  ])
10113
9981
  np_values.append(NP)
10114
9982
 
10115
- # Вычисляем средний NP (если есть хотя бы одно значение)
10116
9983
  avg_np = sum(np_values) / len(np_values) if np_values else 0.0
10117
9984
  avg_np_str = fmt(avg_np)
10118
9985
 
10119
9986
  f_name = os.path.join(EXTRA_D, "5_profit_and_loss_metrics.csv")
10120
9987
  with open(f_name, "w", newline="", encoding="utf-8") as f:
10121
9988
  writer = csv.writer(f)
10122
- # Заголовок
10123
9989
  writer.writerow([
10124
9990
  "Mo", "MRR", "COGS", "Gross Profit",
10125
9991
  "OPEX", "Operating Profit", "Comission (30%)", "Fiat (1%)", "Net Profit"
10126
9992
  ])
10127
- # Строки по месяцам
10128
9993
  for row in results:
10129
9994
  writer.writerow(row)
10130
- # Пустая строка перед средним
10131
9995
  writer.writerow([])
10132
- # Строка со средним Net Profit
10133
9996
  writer.writerow([f"Average Net Profit: {avg_np_str}"])
10134
9997
 
10135
9998
  result = f_name
@@ -11228,7 +11091,6 @@ async def get_ent_rm(chat_id, reply_markup, ENT_TID, POST_USERTUN, POST_TID, POS
11228
11091
  print(f"===============================")
11229
11092
  print(f"===============================")
11230
11093
  print(f"{button=}")
11231
- # выключить инлайн режим и проверить без него
11232
11094
  btn = types.InlineKeyboardButton(text=button['lbl'],
11233
11095
  switch_inline_query=f"{ENT_TID} {str(POST_TID)} ~")
11234
11096
  rows[row_index].append(btn)
@@ -12236,43 +12098,40 @@ async def ch_games(USER_GAMES, game, condition, balls=-1):
12236
12098
  dt = datetime.now(timezone.utc)
12237
12099
  dt_ = dt.strftime('%d-%m-%Y_%H-%M-%S')
12238
12100
 
12239
- print(f"Текущее время: {dt_}")
12240
- print(f"Игровые данные: {USER_GAMES}")
12241
- print(f"Игра: {game}, Условие: {condition}, Баллы: {balls}")
12101
+ print(f"Games: {USER_GAMES}")
12102
+ print(f"Game: {game}, condition: {condition}, balls: {balls}")
12242
12103
 
12243
12104
  if condition:
12244
12105
  # if game not in USER_GAMES:
12245
12106
  # USER_GAMES[game] = {'date': datetime.now(timezone.utc)}
12246
12107
  # dt_game = USER_GAMES[game].get('date')
12247
- # print(f"Дата игры: {dt_game}")
12248
12108
 
12249
12109
  if game not in USER_GAMES or not USER_GAMES[game].get('date', None):
12250
- print("Нет даты, устанавливаем новую")
12110
+ print("there is no dt")
12251
12111
  USER_GAMES[game] = {'date': dt_, 'balls': balls}
12252
- print(f"Добавлена новая игра: {USER_GAMES[game]}")
12112
+ print(f"Added: {USER_GAMES[game]}")
12253
12113
  else:
12254
12114
  dt_game = USER_GAMES[game].get('date')
12255
12115
  dt_game = datetime.strptime(dt_game, "%d-%m-%Y_%H-%M-%S").replace(tzinfo=timezone.utc)
12256
- print(f"Дата игры в datetime: {dt_game}")
12116
+ print(f"Set datetime: {dt_game}")
12257
12117
 
12258
12118
  if (dt - dt_game).days >= 1 or balls == -1:
12259
- print("Прошел день, обновляем данные")
12119
+ print("Day pass - lets to update")
12260
12120
  USER_GAMES[game]['date'] = dt_
12261
12121
  USER_GAMES[game]['balls'] = balls
12262
12122
  else:
12263
- print("День не прошел, данные не меняем")
12123
+ print("No day - no updates in data")
12264
12124
  else:
12265
- print("Условие не выполнено, обнуляем баллы")
12125
+ print("No condition success - balls to zero")
12266
12126
  if isinstance(USER_GAMES.get(game), dict):
12267
12127
  USER_GAMES[game]['balls'] = 0
12268
12128
  else:
12269
12129
  USER_GAMES[game] = {'date': dt_, 'balls': 0}
12270
12130
  except Exception as e:
12271
12131
  logger.info(log_ % str(e))
12272
- print(f"Ошибка: {e}")
12273
12132
  await asyncio.sleep(round(random.uniform(0, 1), 2))
12274
12133
  finally:
12275
- print(f"Финальные данные: {USER_GAMES}")
12134
+ print(f"Final: {USER_GAMES}")
12276
12135
  return USER_GAMES
12277
12136
  # endregion
12278
12137
 
@@ -14027,7 +13886,7 @@ async def getgems_set(bot, message, EXTRA_D):
14027
13886
  if f_n:
14028
13887
  file_dir, file_name = os.path.split(f_n)
14029
13888
  current_date = datetime.now(timezone.utc).strftime('%d-%m-%Y')
14030
- print(f"{current_date=} (он уже сущ)")
13889
+ print(f"{current_date=} (already exists)")
14031
13890
  new_file_path = os.path.join(file_dir, f'{current_date}.getgems')
14032
13891
  os.rename(f_n, new_file_path)
14033
13892
  else:
@@ -14133,7 +13992,6 @@ async def extract_links(text):
14133
13992
  async def is_member_in_channel(bot, chat_id, lz):
14134
13993
  result = False
14135
13994
  try:
14136
- # бот дб добавлен в канал предварительно
14137
13995
  channel_id = ferey_channel_en
14138
13996
  if lz == 'ru':
14139
13997
  channel_id = ferey_channel_europe
@@ -14855,9 +14713,6 @@ async def template_sender(CONF_P, EXTRA_D, MEDIA_D):
14855
14713
  post_txt = f'''
14856
14714
  🍃 Через 1 час в 20:00 я проведу прямой эфир!
14857
14715
 
14858
- Подключайся и смотри все самые интересные моменты!
14859
-
14860
- 🍂 Не пропусти возможность!
14861
14716
  Переходи по моей ссылке, встроенной в кнопку.
14862
14717
  '''
14863
14718
  post_btn = '🎥 Прямой эфир в instagram'
@@ -15441,16 +15296,6 @@ async def get_proxy(identifier, EXTRA_D, CONF_P, server=None):
15441
15296
  return result
15442
15297
 
15443
15298
 
15444
- def is_names(phrase):
15445
- # (?s)\bhello\b.*?\b
15446
- keywords = ['names', 'сотка', 'скорость', 'like', 'концентрат', 'aяз', 'чит-код', "сборная", 'ск-', 'капитан',
15447
- 'лагерь']
15448
- for keyword in keywords:
15449
- if keyword.lower() in phrase.lower():
15450
- return True
15451
- return False
15452
-
15453
-
15454
15299
  async def haversine(lon1, lat1, lon2, lat2):
15455
15300
  result = None
15456
15301
  try:
@@ -15539,7 +15384,7 @@ async def convert_to_vinyl(bot, chat_id, ENT_TID, POST_TID, MEDIA_D, EXTRA_D, PO
15539
15384
  print(f"{full_file_name=} dl ok..")
15540
15385
 
15541
15386
  vinyl_file = os.path.join(EXTRA_D, 'vinyl.mp4')
15542
- print(f"Итоговый путь для нового видео с заменённым звуком {file_name_video=}")
15387
+ print(f"Result path {file_name_video=}")
15543
15388
 
15544
15389
  audio_clip = AudioFileClip(full_file_name)
15545
15390
  if audio_clip.duration > 59: audio_clip = audio_clip.subclipped(0, 59)
@@ -15572,15 +15417,13 @@ async def convert_to_vinyl(bot, chat_id, ENT_TID, POST_TID, MEDIA_D, EXTRA_D, PO
15572
15417
  async def convert_tgs_to_json(tgs_path, output_path=None):
15573
15418
  result = None
15574
15419
  try:
15575
- print(f"Начало конвертации {tgs_path} в JSON.")
15420
+ print(f"convert_tgs_to_json {tgs_path} to JSON.")
15576
15421
  output_path = output_path or tgs_path.replace(".tgs", ".json")
15577
15422
 
15578
15423
  with gzip.open(tgs_path, 'rb') as f:
15579
15424
  json_data = json.loads(f.read().decode('utf-8'))
15580
15425
  async with aiofiles.open(output_path, 'w', encoding='utf-8') as json_file:
15581
15426
  await json_file.write(json.dumps(json_data, ensure_ascii=False, separators=(',', ':')))
15582
-
15583
- print(f"Конвертация завершена. JSON файл сохранен по адресу: {output_path}")
15584
15427
  result = output_path
15585
15428
  except Exception as e:
15586
15429
  logger.info(log_ % str(e))
@@ -15592,7 +15435,7 @@ async def convert_tgs_to_json(tgs_path, output_path=None):
15592
15435
  async def convert_json_to_tgs(json_path, output_path=None):
15593
15436
  result = None
15594
15437
  try:
15595
- print(f"Начало конвертации {json_path} в TGS.")
15438
+ print(f"convert_json_to_tgs {json_path} to TGS.")
15596
15439
  output_path = output_path or json_path.replace(".json", ".tgs")
15597
15440
 
15598
15441
  async with aiofiles.open(json_path, 'r', encoding='utf-8') as json_file:
@@ -15601,7 +15444,6 @@ async def convert_json_to_tgs(json_path, output_path=None):
15601
15444
  with gzip.open(output_path, 'wb') as tgs_file:
15602
15445
  tgs_file.write(json_data.encode('utf-8'))
15603
15446
 
15604
- print(f"Конвертация завершена. TGS файл сохранен по адресу: {output_path}")
15605
15447
  result = output_path
15606
15448
  except Exception as e:
15607
15449
  logger.info(log_ % str(e))
@@ -15617,10 +15459,10 @@ async def convert_webm_to_mp4(webm_path, MEDIA_D, ENT_TID):
15617
15459
  output_path = os.path.join(MEDIA_D, str(ENT_TID), f"{os.path.basename(file_begin)}_copy.mp4")
15618
15460
 
15619
15461
  cmd = [
15620
- "ffmpeg", "-y", "-i", webm_path, # Входной файл
15621
- "-c:v", "libx264", "-preset", "fast", "-crf", "23", # Настройки кодирования
15622
- "-c:a", "aac", "-b:a", "128k", # Кодек для аудио
15623
- output_path # Выходной файл
15462
+ "ffmpeg", "-y", "-i", webm_path,
15463
+ "-c:v", "libx264", "-preset", "fast", "-crf", "23",
15464
+ "-c:a", "aac", "-b:a", "128k",
15465
+ output_path
15624
15466
  ]
15625
15467
 
15626
15468
  process = await asyncio.create_subprocess_exec(
@@ -15631,11 +15473,10 @@ async def convert_webm_to_mp4(webm_path, MEDIA_D, ENT_TID):
15631
15473
  stdout, stderr = await process.communicate()
15632
15474
 
15633
15475
  if process.returncode == 0:
15634
- print(f"Конвертация завершена: {output_path}")
15476
+ print(f"Result: {output_path}")
15635
15477
  else:
15636
- print(f"Ошибка: {stderr.decode()}")
15478
+ print(f"Err: {stderr.decode()}")
15637
15479
 
15638
- print(f"Конвертация завершена. mp4 файл сохранен по адресу: {output_path}")
15639
15480
  result = output_path
15640
15481
  except Exception as e:
15641
15482
  logger.info(log_ % str(e))
@@ -15837,7 +15678,6 @@ async def return_file_id(bot, BOT_TID, FILE_NAME, MSG_TYPE, IS_LINK, BASE_D, EXT
15837
15678
  OWNER_TID, MEDIA, FILE_NAME, EXTRA_D)
15838
15679
  if file_name_video:
15839
15680
  if os.path.exists(FILE_NAME): os.remove(FILE_NAME)
15840
- print(f'del {FILE_NAME=}, остался {file_name_video=}')
15841
15681
  FILE_NAME = file_name_video
15842
15682
 
15843
15683
  file_type = 'audio'
@@ -15860,13 +15700,11 @@ async def return_file_id(bot, BOT_TID, FILE_NAME, MSG_TYPE, IS_LINK, BASE_D, EXT
15860
15700
  FILE_NAME, EXTRA_D)
15861
15701
  if file_name_video:
15862
15702
  if os.path.exists(FILE_NAME): os.remove(FILE_NAME)
15863
- print(f'del {FILE_NAME=}, остался {file_name_video=}')
15864
15703
  FILE_NAME = file_name_video
15865
15704
 
15866
15705
  if F_NAME != FILE_NAME and os.path.exists(F_NAME): os.remove(F_NAME)
15867
15706
  elif MSG_TYPE == 'sticker':
15868
15707
  F_NAME = FILE_NAME
15869
- print(f"1 проверяем FILE_NAME {os.path.exists(FILE_NAME)=}")
15870
15708
  print(f"{IS_LINK=}, {FILE_NAME=}")
15871
15709
  if IS_LINK:
15872
15710
  F_NAME = await download_file_my(MEDIA, BOT_TID, FILE_NAME.split(".")[-1], MEDIA_D)
@@ -15915,10 +15753,10 @@ async def return_file_id(bot, BOT_TID, FILE_NAME, MSG_TYPE, IS_LINK, BASE_D, EXT
15915
15753
  f"{os.path.basename(POST_FNAME1)}_copy.mp4")
15916
15754
 
15917
15755
  cmd = [
15918
- "ffmpeg", "-y", "-i", F_NAME, # Входной файл
15919
- "-c:v", "libx264", "-preset", "fast", "-crf", "23", # Настройки кодирования
15920
- "-c:a", "aac", "-b:a", "128k", # Кодек для аудио
15921
- POST_FNAME_COPY # Выходной файл
15756
+ "ffmpeg", "-y", "-i", F_NAME,
15757
+ "-c:v", "libx264", "-preset", "fast", "-crf", "23",
15758
+ "-c:a", "aac", "-b:a", "128k",
15759
+ POST_FNAME_COPY
15922
15760
  ]
15923
15761
 
15924
15762
  process = await asyncio.create_subprocess_exec(
@@ -15929,14 +15767,14 @@ async def return_file_id(bot, BOT_TID, FILE_NAME, MSG_TYPE, IS_LINK, BASE_D, EXT
15929
15767
  stdout, stderr = await process.communicate()
15930
15768
 
15931
15769
  if process.returncode == 0:
15932
- print(f"Конвертация завершена: {POST_FNAME_COPY}")
15770
+ print(f"Result: {POST_FNAME_COPY}")
15933
15771
  else:
15934
- print(f"Ошибка: {stderr.decode()}")
15772
+ print(f"Err: {stderr.decode()}")
15935
15773
  os.remove(FILE_NAME)
15936
15774
  FILE_NAME = POST_FNAME_COPY
15937
15775
 
15938
15776
  print(f"{file_type=}, {file_id=}")
15939
- print(f"првоеряем FILE_NAME {os.path.exists(FILE_NAME)=}")
15777
+ print(f"check FILE_NAME {os.path.exists(FILE_NAME)=}")
15940
15778
  if F_NAME != FILE_NAME and os.path.exists(F_NAME): os.remove(F_NAME)
15941
15779
  else:
15942
15780
  F_NAME = FILE_NAME
@@ -17025,7 +16863,7 @@ async def format_text_md(txt, is_web=False):
17025
16863
  map(lambda c: c.isascii() and not c.isalnum(), word))):
17026
16864
  # print(f'italic: {word}')
17027
16865
  # result = result.replace(word, f"_{word}_")
17028
- word_pattern = re.escape(word) # Экранируем специальные символы в слове
16866
+ word_pattern = re.escape(word)
17029
16867
  result = re.sub(rf'\b{word_pattern}\b', f"_{word}_", result)
17030
16868
  break
17031
16869
 
@@ -17040,7 +16878,7 @@ async def format_text_md(txt, is_web=False):
17040
16878
  map(lambda c: c.isascii() and not c.isalnum(), word))):
17041
16879
  # print(f'spoiler: {word}')
17042
16880
  # result = result.replace(word, f"||{word}||")
17043
- word_pattern = re.escape(word) # Экранируем специальные символы в слове
16881
+ word_pattern = re.escape(word)
17044
16882
  result = re.sub(rf'\b{word_pattern}\b', f"||{word}||", result)
17045
16883
  break
17046
16884
 
@@ -17487,10 +17325,8 @@ def upper_register_sync(txt):
17487
17325
  async def convert_tgmd_to_html(markdown_text):
17488
17326
  result = markdown_text
17489
17327
  try:
17490
- # markdown_text = "👩🏽‍💻 Lorem _начало_, ыусщте df d d\n_Это_ *пример* [link](https://t.me) текста с *жирным* и _курсивом_\n\n[Ссылка на Google](https://www.google.com)\n\n#Хэштег #markdown #HTML\n\n$Кэштег $python $coding\n\n~Этот текст будет перечеркнут~\n\n__Этот текст будет подчеркнут__\n\n`Это кодовый фрагмент`\n\n```Это тоже кодовый фрагмент```"
17491
17328
  markdown_text = markdown_text.replace('\n', '<br>')
17492
17329
 
17493
- # Заменяем * на <b> (жирный) только если он окружен пробелами или не имеет соседей с символами букв и цифр
17494
17330
  html_text = re.sub(r'(?<![\w*])\*(?!\*)\s*(.*?)\s*\*(?!\*)(?![\w*])', r'<b>\1</b>', markdown_text)
17495
17331
  html_text = re.sub(r'__(.*?)__', r'<u>\1</u>', html_text)
17496
17332
  html_text = re.sub(r'\|\|(.*?)\|\|', r'<code>\1</code>', html_text)
@@ -17952,8 +17788,7 @@ async def get_content_part(ctx, content_all, width_, original_width):
17952
17788
  if not space_found:
17953
17789
  break
17954
17790
 
17955
- # Пересчитаем ширину с учетом коэффициента
17956
- width_ = int(original_width - original_width * padding_coefficient) # Используем исходную ширину
17791
+ width_ = int(original_width - original_width * padding_coefficient)
17957
17792
  print(f"2 {width_=}")
17958
17793
  else:
17959
17794
  break
@@ -17965,9 +17800,8 @@ async def get_content_part(ctx, content_all, width_, original_width):
17965
17800
 
17966
17801
  content_all = content_all.strip().replace(content_part, '', 1).strip()
17967
17802
 
17968
- # Пересчитаем ширину после изменений
17969
17803
  bearing, ybearing, content_width, _, _, _ = ctx.text_extents(content_all)
17970
- width_ = int(original_width - original_width * padding_coefficient) # Используем исходную ширину
17804
+ width_ = int(original_width - original_width * padding_coefficient)
17971
17805
  print(f"3 {width_=}")
17972
17806
  except Exception as e:
17973
17807
  logger.info(log_ % str(e))
@@ -18299,7 +18133,7 @@ async def is_my_chat(bot, chat_id, link, SESSIONS_D, EXTRA_D, CONF_P, BASE_S, BA
18299
18133
  if r is None:
18300
18134
  logger.info(log_ % f"{link} is None")
18301
18135
  return
18302
- txt_ = f"👩🏽‍💻 Администратор закрытой группы не принял заявки на вступление"
18136
+ txt_ = l_admin_closed_group_reject['en']
18303
18137
  if r == -1:
18304
18138
  await bot.send_message(chat_id, txt_)
18305
18139
  return
@@ -18371,14 +18205,13 @@ async def is_invite_chat(bot, chat_id, link, SESSIONS_D, EXTRA_D, CONF_P, BASE_S
18371
18205
  logger.info(log_ % f"{SESSION_TID} get_chat {r.id}")
18372
18206
 
18373
18207
  if not (r.type.value in ['group', 'supergroup']):
18374
- text = "🚶 Вставь ссылку на группу, а не канал"
18208
+ text = l_insert_group_link['en']
18375
18209
  await bot.send_message(chat_id, text)
18376
18210
  elif hasattr(r.permissions, 'can_invite_users') and not r.permissions.can_invite_users:
18377
- text = "🚶 Зайди в «Разрешения» группы и включи <i>участникам группы</i> возможность: " \
18378
- "«Добавление участников»"
18211
+ text = l_permissions_add_members['en']
18379
18212
  await bot.send_message(chat_id, text)
18380
18213
  else:
18381
- text = "🚶 Начинаем проверку группы..\n#длительность 2мин"
18214
+ text = l_start_group_check['en']
18382
18215
  await bot.send_message(chat_id, text)
18383
18216
  # await asyncio.sleep(r_conf('AWAIT_JOIN'))
18384
18217
 
@@ -18493,11 +18326,12 @@ async def get_chat_members(bot, chat_id, link, SESSIONS_D, EXTRA_D, CONF_P, BASE
18493
18326
  result = []
18494
18327
  r = None
18495
18328
  try:
18496
- text = f"🚶 Проверяем участников группы..\n#длительность 1мин"
18329
+ text = l_check_group_members['en']
18497
18330
  await bot.send_message(chat_id, text)
18498
18331
  sql = "SELECT SESSION_TID,SESSION_STATUS FROM SESSION WHERE SESSION_SPAM IS NOT '*'"
18499
18332
  data = await db_select_pg(sql, (), BASE_S)
18500
18333
  random.shuffle(data)
18334
+
18501
18335
  for item in data:
18502
18336
  tmp_members = []
18503
18337
  SESSION_TID, SESSION_STATUS = item
@@ -18526,7 +18360,7 @@ async def get_chat_members(bot, chat_id, link, SESSIONS_D, EXTRA_D, CONF_P, BASE
18526
18360
  tmp_members.append(member.user.username)
18527
18361
  except ChatAdminRequired as e:
18528
18362
  logger.info(log_ % str(e))
18529
- await bot.send_message(chat_id, f"🔺 Требуются права админа")
18363
+ await bot.send_message(chat_id, l_admin_rights_required['en'])
18530
18364
  return
18531
18365
  except Exception as e:
18532
18366
  logger.info(log_ % str(e))
@@ -18857,13 +18691,11 @@ async def api_read_cells(sheets_service, range_many, spreadsheet_id, sheet_id='S
18857
18691
 
18858
18692
  def get_random_color():
18859
18693
  """
18860
- Создаю случайный цвет с альфа каном
18861
18694
  https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#Color
18862
18695
  :return:
18863
18696
  """
18864
18697
  return {"red": randrange(0, 255) / 255, "green": randrange(0, 255) / 255, "blue": randrange(0, 255) / 255,
18865
- "alpha": randrange(0, 10) / 10 # 0.0 - прозрачный
18866
- }
18698
+ "alpha": randrange(0, 10) / 10}
18867
18699
 
18868
18700
 
18869
18701
  def api_create_file_or_folder(drive_service, mime_type, name, parent_id):