Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import ttk, messagebox
- from telethon import TelegramClient, events, sync
- from telethon.tl.functions.contacts import GetContactsRequest, ImportContactsRequest, DeleteContactsRequest, GetLocatedRequest, AddContactRequest
- from telethon.tl.types import InputPeerUser, InputPeerEmpty, UserStatusOffline, UserStatusRecently, UserStatusLastMonth, UserStatusLastWeek, InputGeoPoint
- from datetime import datetime, timedelta, timezone
- import asyncio
- import time
- import threading
- from tkintermapview import TkinterMapView
- # Ваши данные из my.telegram.org
- api_id = APP_ID
- api_hash = 'APP_HASH'
- phone_number = '+70000000'
- # Создаем клиент Telegram (вне функции main)
- client = TelegramClient("read_client", api_id=api_id, api_hash=api_hash, device_model="iPhone 55 Pro", system_version="IOS 100.1")
- # Время задержки между запросами к API Telegram
- delay_seconds = 1
- # Ваш часовой пояс (в секундах)
- timezone_offset = 3 * 60 * 60
- class App(tk.Tk):
- def __init__(self):
- super().__init__()
- self.title("Поиск пользователей Telegram")
- self.geometry("1024x800")
- # --- Разделение окна на фреймы ---
- top_frame = tk.Frame(self)
- top_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
- map_frame = tk.Frame(top_frame)
- map_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
- input_frame = ttk.LabelFrame(top_frame, text="Координаты")
- input_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.Y)
- results_frame = tk.Frame(self)
- results_frame.pack(fill=tk.BOTH, expand=True)
- # --- Конец разделения ---
- # Карта OpenStreetMap
- self.map_widget = TkinterMapView(map_frame, width=600, height=400, corner_radius=0)
- self.map_widget.pack(expand=True, fill=tk.BOTH)
- # --- Фрейм для координат и кнопки ---
- self.latitude = tk.StringVar(value="55.63729")
- self.longitude = tk.StringVar(value="37.88502")
- self.radius = tk.StringVar(value="500")
- latitude_fl = float(self.latitude.get())
- longitude_fl = float(self.longitude.get())
- self.map_widget.set_position(latitude_fl, longitude_fl) # Москва
- self.map_widget.set_zoom(18)
- # Маркер на карте
- self.marker = None
- # Обработчик клика по карте
- self.bind('<Button-1>', self.on_map_click)
- ttk.Label(input_frame, text="Широта:").grid(row=0, column=0, padx=5, pady=5)
- ttk.Entry(input_frame, textvariable=self.latitude).grid(row=0, column=1, padx=5, pady=5)
- ttk.Label(input_frame, text="Долгота:").grid(row=1, column=0, padx=5, pady=5)
- ttk.Entry(input_frame, textvariable=self.longitude).grid(row=1, column=1, padx=5, pady=5)
- ttk.Label(input_frame, text="Радиус поиска:").grid(row=2, column=0, padx=5, pady=5)
- ttk.Entry(input_frame, textvariable=self.radius).grid(row=2, column=1, padx=5, pady=5)
- ttk.Button(input_frame, text="Начать поиск", command=self.start_search).grid(row=3, column=0, columnspan=2, padx=5, pady=10)
- # --- Конец фрейма ---
- # --- Таблица для вывода результатов ---
- self.results_table = ttk.Treeview(results_frame, columns=("ID", "Расстояние", "Username", "Имя", "Фамилия", "Дата онлайна"), show="headings")
- self.results_table.heading("ID", text="ID")
- self.results_table.heading("Расстояние", text="Расстояние (м)")
- self.results_table.heading("Username", text="Username")
- self.results_table.heading("Имя", text="Имя")
- self.results_table.heading("Фамилия", text="Фамилия")
- self.results_table.heading("Дата онлайна", text="Дата онлайна")
- self.results_table.column("ID", width=100)
- self.results_table.column("Расстояние", width=100)
- self.results_table.column("Username", width=150)
- self.results_table.column("Имя", width=150)
- self.results_table.column("Фамилия", width=150)
- self.results_table.column("Дата онлайна", width=150)
- self.results_table.pack(fill=tk.BOTH, expand=True)
- # --- Конец таблицы ---
- def on_map_click(self, event):
- # Получаем координаты клика
- latitude = self.map_widget.get_position()[0]
- longitude = self.map_widget.get_position()[1]
- # Удаляем старый маркер, если он есть
- if self.marker:
- self.map_widget.delete(self.marker)
- # Создаем маркер на карте
- self.marker = self.map_widget.set_marker(latitude, longitude, text="Выбранное место")
- # Обновляем поля ввода
- self.latitude.set(str(latitude))
- self.longitude.set(str(longitude))
- def start_search(self):
- try:
- latitude = float(self.latitude.get())
- longitude = float(self.longitude.get())
- except ValueError:
- messagebox.showerror("Ошибка", "Неверный формат координат.")
- return
- # Очищаем таблицу перед новым поиском
- for item in self.results_table.get_children():
- self.results_table.delete(item)
- # Запускаем асинхронную функцию поиска в отдельном потоке
- threading.Thread(target=self.run_search, args=(latitude, longitude), daemon=True).start()
- def run_search(self, latitude, longitude):
- try:
- asyncio.run(self.search_users(latitude, longitude))
- except Exception as e:
- messagebox.showerror("Ошибка", f"Произошла ошибка: {e}")
- finally:
- messagebox.showinfo("Информация", "Поиск завершен.")
- async def search_users(self, latitude, longitude):
- # Подключаемся к Telegram
- await client.connect()
- client.session.save()
- # Авторизация
- if not await client.is_user_authorized():
- await client.send_code_request(phone_number)
- # Введите код, полученный в Telegram
- me = await client.sign_in(phone_number, input('Введите код авторизации: '))
- else:
- me = await client.get_me()
- try:
- users = await client(GetLocatedRequest(
- geo_point=InputGeoPoint(
- lat=latitude,
- long=longitude,
- accuracy_radius=100
- ),
- self_expires=10
- ))
- except Exception as e:
- messagebox.showerror("Ошибка", f"Ошибка при получении местоположений пользователей: {e}")
- await client.disconnect()
- return
- # print(users.stringify())
- # Сохранение сырого ответа
- with open("raw_georequest.txt", "w", encoding="utf-8") as f2:
- f2.write(users.stringify())
- for user in users.updates[0].peers:
- if hasattr(user, 'peer') and hasattr(user.peer, 'user_id'):
- await self.get_user_info(user)
- # Отключаемся от Telegram
- await client.disconnect()
- async def get_user_info(self, user):
- user_id = user.peer.user_id
- distance = user.distance
- if distance <= int(self.radius.get()): # Не дальше 600 метров
- await asyncio.sleep(delay_seconds)
- try:
- full_user = await client.get_entity(user_id)
- except Exception as e:
- messagebox.showerror("Ошибка", f"Ошибка при получении информации о пользователе {user_id}: {e}")
- return
- date_online_str = ''
- date_online = None
- last_month = datetime.now() - timedelta(days=30)
- last_week = datetime.now() - timedelta(days=7)
- if isinstance(full_user.status, UserStatusRecently):
- date_online_str = 'online'
- else:
- if isinstance(full_user.status, UserStatusLastMonth):
- date_online = last_month
- if isinstance(full_user.status, UserStatusLastWeek):
- date_online = last_week
- if isinstance(full_user.status, UserStatusOffline):
- date_online = full_user.status.was_online
- if date_online:
- date_online = date_online.replace(tzinfo=timezone.utc) + timedelta(seconds=timezone_offset)
- date_online_str = date_online.strftime("%d.%m.%Y %H:%M")
- # Добавление информации о пользователе в таблицу
- self.results_table.insert("", tk.END, values=(
- user_id,
- distance,
- full_user.username,
- full_user.first_name,
- full_user.last_name,
- date_online_str
- ))
- # Сохранение информации о пользователе в файл (по желанию)
- with open("nearby_users.txt", "a", encoding="utf-8") as f:
- f.write(f"ID: {user_id}, Имя пользователя: {full_user.username}, Имя: {full_user.first_name}, Фамилия: {full_user.last_name}, Дата онлайна: {date_online_str}\n")
- # Добавление пользователя в контакты (с задержкой)
- try:
- result = await client(AddContactRequest(
- id=user_id,
- first_name=full_user.first_name if full_user.first_name else "",
- last_name=full_user.last_name if full_user.last_name else "",
- phone=full_user.phone if full_user.phone else "",
- ))
- except Exception as e:
- messagebox.showerror("Ошибка", f"Ошибка при добавлении пользователя в контакты: {e}")
- if __name__ == "__main__":
- app = App()
- app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment