Dink0 commited on
Commit
a10e2b3
·
verified ·
1 Parent(s): 31bd2b5

Delete аааapp.py

Browse files
Files changed (1) hide show
  1. аааapp.py +0 -352
аааapp.py DELETED
@@ -1,352 +0,0 @@
1
- import streamlit as st
2
- import asyncio
3
- import nest_asyncio
4
- nest_asyncio.apply() # Позволяет переиспользовать один event loop
5
-
6
- import re
7
- import os
8
- import requests
9
- from telethon import TelegramClient
10
- from telethon.sessions import StringSession
11
- import streamlit.components.v1 as components
12
-
13
- # ----------- Настройки Telegram -----------
14
- TELEGRAM_API_ID = 23646321
15
- TELEGRAM_API_HASH = "102edf31d404cb72d17ee4831d4e8c7b"
16
- # Строка сессии (сгенерируйте заранее, если нужно)
17
- TELEGRAM_STRING_SESSION = "1ApWapzMBu8a9o9Wu1GexPdkO7Jsr6po1xym67EcfAxkEbVx1oxw6wW7LINb9Xf0VYcyEAP-b-D0RQ_4x0RDAW8Di_0P2r4bj7xNeV9xO3wBMcaeq7FJux3UMq5buq89gqG8JarZG04tIyWoVnH__dq1_6G2Zkr0GF4WJCS2UN7mmwBacIIUEjUryEA97tXYC8jD14J-1MDgFsNNZTJ6uurD5RzH2DIhphChebxOkDBdXmpLGlanEzYzVOlx4p6Mo2zYorRG968o64CxKEh-WiJaPSNrS3IEfIVWFVd_tHKWzQSPD1zHHhcw0v2_ZjCKbZnTMcT3uMYuyLwA55_dckzcw0wZgAZQ="
18
-
19
- # ----------- Настройки ВКонтакте -----------
20
- # Инициализация токенов в session_state
21
- if "VK_ACCESS_TOKEN" not in st.session_state:
22
- st.session_state["VK_ACCESS_TOKEN"] = os.environ.get("VK_ACCESS_TOKEN", "")
23
- if "VK_REFRESH_TOKEN" not in st.session_state:
24
- st.session_state["VK_REFRESH_TOKEN"] = os.environ.get("VK_REFRESH_TOKEN", "")
25
- if "VK_DEVICE_ID" not in st.session_state:
26
- st.session_state["VK_DEVICE_ID"] = os.environ.get("VK_DEVICE_ID", "")
27
-
28
- # Остальные настройки ВКонтакте
29
- VK_CLIENT_ID = os.environ.get("VK_CLIENT_ID", "")
30
- VK_CLIENT_SECRET = os.environ.get("VK_CLIENT_SECRET", "")
31
- VK_API_VERSION = "5.131"
32
-
33
- if not st.session_state["VK_ACCESS_TOKEN"]:
34
- st.warning("Не найден VK_ACCESS_TOKEN. Добавьте его в Secrets или переменные окружения!")
35
- if not st.session_state["VK_REFRESH_TOKEN"]:
36
- st.warning("Не найден VK_REFRESH_TOKEN. Без него не сможем обновлять токен!")
37
- if not VK_CLIENT_ID or not VK_CLIENT_SECRET:
38
- st.warning("Не найдены VK_CLIENT_ID / VK_CLIENT_SECRET. Без них не сможем обновлять токен!")
39
-
40
- # --- Инициализация Telethon-клиента (Telegram) ---
41
- def init_telethon():
42
- loop = asyncio.new_event_loop()
43
- asyncio.set_event_loop(loop)
44
- client = TelegramClient(StringSession(TELEGRAM_STRING_SESSION), TELEGRAM_API_ID, TELEGRAM_API_HASH)
45
- loop.run_until_complete(client.connect())
46
- if not loop.run_until_complete(client.is_user_authorized()):
47
- st.error("Telegram-сессия не авторизована. Проверьте StringSession или выполните login_telethon.py.")
48
- st.stop()
49
- return client, loop
50
-
51
- if "telethon_client" not in st.session_state:
52
- st.session_state["telethon_client"], st.session_state["telethon_loop"] = init_telethon()
53
-
54
- tg_client = st.session_state["telethon_client"]
55
- tg_loop = st.session_state["telethon_loop"]
56
-
57
- def human_format_views(num: int) -> str:
58
- if num < 1000:
59
- return f"{num / 1000:.1f}K"
60
- elif num < 10_000:
61
- return f"{num / 1000:.1f}K"
62
- elif num < 1_000_000:
63
- return f"{int(num / 1000)}K"
64
- else:
65
- return f"{num / 1_000_000:.1f}M"
66
-
67
- # ---------- Функция обновления токена через refresh_token ----------
68
- def refresh_vk_token() -> bool:
69
- """
70
- Отправляем запрос на обновление токена через refresh_token.
71
- По новой схеме VK ID:
72
- grant_type=refresh_token, endpoint может быть https://id.vk.com/oauth2/auth (или другой, согласно документации).
73
- """
74
- st.write("Пытаемся обновить токен...") # Отладочное сообщение
75
-
76
- # Берём текущие значения из session_state
77
- current_refresh = st.session_state["VK_REFRESH_TOKEN"]
78
- device_id = st.session_state.get("VK_DEVICE_ID", "") # Получаем device_id
79
-
80
- st.write(f"Текущий refresh_token: {current_refresh}") # Отладочное сообщение
81
- st.write(f"Текущий device_id: {device_id}") # Отладочное сообщение
82
-
83
- if not current_refresh or not VK_CLIENT_ID or not VK_CLIENT_SECRET or not device_id:
84
- st.error("Невозможно обновить токен: нет refresh_token, client_id, client_secret или device_id.")
85
- return False
86
-
87
- url = "https://id.vk.com/oauth2/auth" # Endpoint для обновления токена
88
- data = {
89
- "grant_type": "refresh_token",
90
- "client_id": VK_CLIENT_ID,
91
- "client_secret": VK_CLIENT_SECRET,
92
- "refresh_token": current_refresh,
93
- "device_id": device_id # Передаем device_id
94
- }
95
-
96
- # Указываем заголовки для запроса
97
- headers = {
98
- "Content-Type": "application/x-www-form-urlencoded"
99
- }
100
-
101
- st.write(f"Отправляем запрос на обновление ток��на: {url}") # Отладочное сообщение
102
- st.write(f"Данные запроса: {data}") # Отладочное сообщение
103
-
104
- # Отправляем POST-запрос с данными в теле (body)
105
- resp = requests.post(url, data=data, headers=headers)
106
- st.write(f"Статус ответа: {resp.status_code}") # Отладочное сообщение
107
- st.write(f"Текст ответа: {resp.text}") # Отладочное сообщение
108
-
109
- if resp.status_code != 200:
110
- st.error(f"Ошибка обновления токена (HTTP {resp.status_code}): {resp.text}")
111
- return False
112
-
113
- try:
114
- result = resp.json()
115
- st.write(f"Ответ от VK API: {result}") # Отладочное сообщение
116
- except Exception as e:
117
- st.error(f"Не удалось распарсить ответ при обновлении токена: {e}")
118
- return False
119
-
120
- if "access_token" not in result:
121
- err_desc = result.get("error_description", result)
122
- st.error(f"Не удалось получить новый access_token: {err_desc}")
123
- return False
124
-
125
- # Сохраняем новые значения
126
- new_access = result["access_token"]
127
- st.session_state["VK_ACCESS_TOKEN"] = new_access
128
-
129
- # Сохраняем новый refresh_token, если он есть в ответе
130
- if "refresh_token" in result:
131
- new_refresh = result["refresh_token"]
132
- st.session_state["VK_REFRESH_TOKEN"] = new_refresh
133
- st.write(f"Новый refresh_token: {new_refresh}") # Отладочное сообщение
134
- else:
135
- st.warning("Новый refresh_token не был получен. Убедитесь, что это ожидаемо.")
136
-
137
- st.success("VK-токен обновлён успешно!")
138
- st.write(f"Новый access_token: {new_access}") # Отладочное сообщение
139
-
140
- return True
141
-
142
- # ------ Автоматическое обновление токена при запуске ------
143
- if st.session_state.get("VK_REFRESH_TOKEN"):
144
- try:
145
- st.write("Обновление токена...")
146
- refresh_vk_token() # <-- Теперь функция определена выше, ошибки не будет
147
- except Exception as e:
148
- st.error(f"Ошибка: {e}")
149
- else:
150
- st.warning("Не найден refresh_token. Авторизуйтесь через workingtoken.py.")
151
-
152
- # ------------- Парсер Telegram -------------
153
- def process_telegram_link(link: str) -> tuple[str, int]:
154
- link = link.strip()
155
- if not link:
156
- return "", 0
157
-
158
- match = re.match(r'https?://(?:t(?:elegram)?\.me)/([^/]+)/(\d+)', link, re.IGNORECASE)
159
- if not match:
160
- return f"**Ошибка (TG)**: не распознал ссылку — {link}", 0
161
-
162
- channel_username = match.group(1)
163
- message_id = int(match.group(2))
164
-
165
- try:
166
- msg = tg_loop.run_until_complete(tg_client.get_messages(channel_username, ids=message_id))
167
- if msg is None:
168
- return f"**Ошибка (TG)**: сообщение не найдено — {link}", 0
169
-
170
- channel_entity = tg_loop.run_until_complete(tg_client.get_entity(channel_username))
171
- channel_title = channel_entity.title
172
- views = msg.views or 0
173
- result = f"- [{channel_title}]({link}) — {human_format_views(views)}"
174
- return result, views
175
- except Exception as e:
176
- return f"**Ошибка (TG)** при обработке [{link}]({link}): {e}", 0
177
-
178
- # ------------- Парсер VK (с обновлением токена при ошибке) -------------
179
- def process_vk_link(link: str) -> tuple[str, int]:
180
- link = link.strip()
181
- if not link:
182
- return "", 0
183
-
184
- match = re.search(r'vk\.com/wall(-?\d+)_(\d+)', link)
185
- if not match:
186
- return f"**Ошибка (VK)**: не распознал ссылку — {link}", 0
187
-
188
- owner_id = int(match.group(1))
189
- post_id = match.group(2)
190
- posts_param = f"{owner_id}_{post_id}"
191
- api_url = "https://api.vk.com/method/wall.getById"
192
-
193
- def do_request(token):
194
- params = {
195
- "posts": posts_param,
196
- "access_token": token,
197
- "v": VK_API_VERSION,
198
- "extended": 1
199
- }
200
- return requests.get(api_url, params=params)
201
-
202
- # Первый запрос с текущим access_token
203
- token = st.session_state["VK_ACCESS_TOKEN"]
204
- resp = do_request(token)
205
-
206
- if resp.status_code != 200:
207
- return f"**Ошибка (VK)**: HTTP {resp.status_code} — {link}", 0
208
-
209
- data = resp.json()
210
- if "error" in data:
211
- error_msg = data["error"].get("error_msg", "")
212
- # Если токен истёк, пробуем обновить
213
- if "access_token has expired" in error_msg.lower():
214
- if refresh_vk_token():
215
- # Повторяем запрос с новым токеном
216
- new_token = st.session_state["VK_ACCESS_TOKEN"]
217
- resp = do_request(new_token)
218
- data = resp.json()
219
- if "error" in data:
220
- # Если опять ошибка - выходим
221
- err_msg2 = data["error"].get("error_msg", "")
222
- return f"**Ошибка (VK)**: {err_msg2} — {link}", 0
223
- else:
224
- return f"**Ошибка (VK)**: не удалось обновить токен — {link}", 0
225
- else:
226
- return f"**Ошибка (VK)**: {error_msg} — {link}", 0
227
-
228
- response_data = data.get("response", {})
229
- items = response_data.get("items", [])
230
- if not items:
231
- return f"**Ошибка (VK)**: пост не найден — {link}", 0
232
-
233
- post = items[0]
234
- views = post.get("views", {}).get("count", 0)
235
- post_owner_id = post.get("owner_id", owner_id)
236
-
237
- title = None
238
- if post_owner_id < 0:
239
- group_id = -post_owner_id
240
- for g in response_data.get("groups", []):
241
- if g["id"] == group_id:
242
- title = g["name"]
243
- break
244
- else:
245
- user_id = post_owner_id
246
- for p in response_data.get("profiles", []):
247
- if p["id"] == user_id:
248
- first_name = p.get("first_name", "")
249
- last_name = p.get("last_name", "")
250
- title = (first_name + " " + last_name).strip()
251
- break
252
- if not title:
253
- title = "VK пост"
254
-
255
- result = f"- [{title}]({link}) — {human_format_views(views)}"
256
- return result, views
257
-
258
- # ------------- Определение платформы -------------
259
- def detect_platform(link: str) -> str:
260
- link = link.strip().lower()
261
- if "t.me/" in link or "telegram.me/" in link:
262
- return "telegram"
263
- elif "vk.com/wall" in link:
264
- return "vk"
265
- return ""
266
-
267
- # ---------- Интерфейс Streamlit ----------
268
- st.title("PR Tool made by @Dina")
269
-
270
- st.write("Вставьте ссылки (каждая на новой строке) — как Telegram, так и ВКонтакте. Пример:")
271
- st.code("""
272
- https://t.me/meduzalive/122479
273
- https://vk.com/wall-12256840_3220312
274
- https://telegram.me/za_traktor/27423
275
- https://vk.com/wall-237426_1643234
276
- """)
277
-
278
- links_input = st.text_area("Ссылки:", height=200)
279
-
280
- if st.button("Обработать"):
281
- lines = links_input.strip().split('\n')
282
- tg_results = []
283
- tg_total_views = 0
284
- vk_results = []
285
- vk_total_views = 0
286
-
287
- for link in lines:
288
- platform = detect_platform(link)
289
- if platform == "telegram":
290
- res_line, views = process_telegram_link(link)
291
- tg_results.append((res_line, views))
292
- tg_total_views += views
293
- elif platform == "vk":
294
- res_line, views = process_vk_link(link)
295
- vk_results.append((res_line, views))
296
- vk_total_views += views
297
- else:
298
- st.markdown(f"**Ошибка**: не распознал платформу — {link}", unsafe_allow_html=True)
299
-
300
- tg_results.sort(key=lambda x: x[1], reverse=True)
301
- vk_results.sort(key=lambda x: x[1], reverse=True)
302
-
303
- md_lines = []
304
-
305
- # --- Telegram ---
306
- md_lines.append("## Telegram")
307
- md_lines.append(f"**Суммарный охват постов — {human_format_views(tg_total_views)} просмотров**")
308
- if tg_results:
309
- for r_line, _ in tg_results:
310
- md_lines.append(r_line)
311
- else:
312
- md_lines.append("_Нет ссылок на Telegram_")
313
- md_lines.append("")
314
-
315
- # --- ВКонтакте ---
316
- md_lines.append("## ВКонтакте")
317
- md_lines.append(f"**Суммарный охват постов — {human_format_views(vk_total_views)} просмотров**")
318
- if vk_results:
319
- for r_line, _ in vk_results:
320
- md_lines.append(r_line)
321
- else:
322
- md_lines.append("_Нет ссылок на ВКонтакте_")
323
- md_lines.append("")
324
-
325
- st.markdown("### Результат:")
326
- for line in md_lines:
327
- st.markdown(line, unsafe_allow_html=True)
328
-
329
- markdown_result = "\n".join(md_lines)
330
-
331
- # Кнопка копирования
332
- copy_button_html = f"""
333
- <html>
334
- <head>
335
- <script>
336
- function copyToClipboard() {{
337
- const btn = document.getElementById("copy-btn");
338
- const text = `{markdown_result}`;
339
- navigator.clipboard.writeText(text).then(function() {{
340
- btn.innerText = "Скопировано успешно";
341
- }}, function(err) {{
342
- btn.innerText = "Ошибка при копировании";
343
- }});
344
- }}
345
- </script>
346
- </head>
347
- <body>
348
- <button id="copy-btn" onclick="copyToClipboard()" style="padding: 8px 16px; font-size: 16px;">Скопировать код</button>
349
- </body>
350
- </html>
351
- """
352
- components.html(copy_button_html, height=80)