-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
110 lines (92 loc) · 3.95 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import os
import sys
import ctypes
import signal
import threading
import time
import webbrowser
import datetime
from PIL import Image
import pystray
from scraper import scrape
from webapp import app
from database import create_table, get_distinct_dates
from config import ensure_env_file, load_env
def is_admin():
"""Проверяет, запущено ли приложение с правами администратора."""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def run_as_admin():
"""Перезапускает программу с правами администратора."""
if not is_admin():
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
sys.exit()
def resource_path(relative_path):
"""Получает путь к ресурсам, как в режиме разработки, так и в собранном виде."""
try:
base_path = sys._MEIPASS
except AttributeError:
base_path = os.path.dirname(__file__)
return os.path.join(base_path, relative_path)
def create_image():
"""Создает изображение для иконки в системном трее."""
return Image.open(resource_path('github.ico'))
def run_flask():
"""Запускает Flask приложение."""
app.run(port=5000, use_reloader=False)
def scrape_daily():
"""Запускает ежедневное сканирование в 17:00, если нет записей за текущий день."""
scan_time_str = os.getenv('SCAN_TIME', '17:00')
scan_hour, scan_minute = map(int, scan_time_str.split(':'))
while not stop_event.is_set():
now = datetime.datetime.now()
date_str = now.strftime('%d.%m.%Y')
scan_time = datetime.time(scan_hour, scan_minute)
# Определяем время следующего запуска в 17:00 следующего дня
if now.time() >= scan_time:
next_run = now.replace(hour=scan_hour, minute=scan_minute, second=0, microsecond=0) + datetime.timedelta(days=1)
else:
next_run = now.replace(hour=scan_hour, minute=scan_minute, second=0, microsecond=0)
# Проверяем записи за текущий день
if now.time() >= scan_time:
if date_str not in [d[0] for d in get_distinct_dates()]:
scrape() # Выполняем сканирование
# Ожидание до следующего запуска
sleep_duration = (next_run - now).total_seconds()
time.sleep(sleep_duration)
def on_quit(icon, item):
"""Обработчик для выхода из приложения."""
stop_event.set()
icon.stop()
os.kill(os.getpid(), signal.SIGINT)
def on_open_url(icon, item):
"""Открывает веб-приложение в браузере."""
webbrowser.open('http://127.0.0.1:5000')
def setup(icon):
"""Настраивает иконку в системном трее."""
icon.visible = True
def start_icon():
"""Запускает иконку в системном трее."""
icon = pystray.Icon('Trends', create_image(), title="GitHub Trends Archive by King Triton")
icon.menu = pystray.Menu(
pystray.MenuItem('Open Web App', on_open_url),
pystray.MenuItem('Quit', on_quit)
)
icon.run(setup)
def main():
"""Основная логика приложения."""
ensure_env_file() # Создаем файл .env, если его нет
load_env() # Загружаем переменные окружения
create_table()
threading.Thread(target=scrape_daily, daemon=True).start()
threading.Thread(target=start_icon, daemon=True).start()
try:
run_flask()
except KeyboardInterrupt:
stop_event.set()
if __name__ == "__main__":
run_as_admin()
stop_event = threading.Event()
main()