yeref 0.25.22__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/l_.py +11993 -11934
- yeref/yeref.py +94 -262
- {yeref-0.25.22.dist-info → yeref-0.25.23.dist-info}/METADATA +1 -1
- yeref-0.25.23.dist-info/RECORD +8 -0
- yeref-0.25.22.dist-info/RECORD +0 -8
- {yeref-0.25.22.dist-info → yeref-0.25.23.dist-info}/WHEEL +0 -0
- {yeref-0.25.22.dist-info → yeref-0.25.23.dist-info}/top_level.txt +0 -0
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("
|
5107
|
+
print("no job id")
|
5204
5108
|
return
|
5205
5109
|
|
5206
|
-
print(f"
|
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"
|
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"
|
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"
|
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
|
-
#
|
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"
|
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("
|
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]
|
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 -
|
5943
|
-
# onyx -
|
5944
|
-
# nova -
|
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", " ") #
|
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():
|
7437
|
-
for _ in keys:
|
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():
|
7641
|
-
for _ in keys:
|
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():
|
7812
|
-
for _ in keys:
|
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():
|
7940
|
-
for _ in keys:
|
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():
|
8012
|
-
for _ in keys:
|
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():
|
8091
|
-
for _ in keys:
|
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():
|
8169
|
-
for _ in keys:
|
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():
|
8258
|
-
for _ in keys:
|
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():
|
8333
|
-
for _ in keys:
|
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:
|
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"
|
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"
|
9435
|
+
logger.warning(f"no file: {path}")
|
9550
9436
|
|
9551
|
-
# 2) Если ни одного CSV не обнаружено, выходим
|
9552
9437
|
if not tables:
|
9553
|
-
logger.warning("
|
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"
|
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"
|
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"
|
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"
|
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"
|
9509
|
+
logger.info(f"Success = {total_cells}.")
|
9633
9510
|
except Exception as e:
|
9634
|
-
logger.error(f"
|
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
|
-
#
|
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"
|
12240
|
-
print(f"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
15476
|
+
print(f"Result: {output_path}")
|
15635
15477
|
else:
|
15636
|
-
print(f"
|
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"
|
15770
|
+
print(f"Result: {POST_FNAME_COPY}")
|
15933
15771
|
else:
|
15934
|
-
print(f"
|
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"
|
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_ =
|
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 =
|
18378
|
-
"«Добавление участников»"
|
18211
|
+
text = l_permissions_add_members['en']
|
18379
18212
|
await bot.send_message(chat_id, text)
|
18380
18213
|
else:
|
18381
|
-
text =
|
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 =
|
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,
|
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
|
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):
|