Compare commits
2 Commits
e0628b1792
...
v2.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
| cd5e6e1f6b | |||
| 4b3347a069 |
@@ -1 +1 @@
|
|||||||
APP_VERSION = "2.2.0"
|
APP_VERSION = "2.2.2"
|
||||||
|
|||||||
46
main.py
46
main.py
@@ -2,7 +2,6 @@
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from PySide6.QtCore import QProcess
|
from PySide6.QtCore import QProcess
|
||||||
@@ -172,6 +171,7 @@ class VkChatManager(QMainWindow):
|
|||||||
self.update_channel = UPDATE_CHANNEL_DEFAULT
|
self.update_channel = UPDATE_CHANNEL_DEFAULT
|
||||||
self.update_checker = None
|
self.update_checker = None
|
||||||
self.update_thread = None
|
self.update_thread = None
|
||||||
|
self._update_in_progress = False
|
||||||
self._update_check_silent = False
|
self._update_check_silent = False
|
||||||
self._bulk_worker_thread = None
|
self._bulk_worker_thread = None
|
||||||
self._bulk_worker = None
|
self._bulk_worker = None
|
||||||
@@ -463,10 +463,11 @@ class VkChatManager(QMainWindow):
|
|||||||
self._log_event("update_channel", f"update_channel={self.update_channel}")
|
self._log_event("update_channel", f"update_channel={self.update_channel}")
|
||||||
|
|
||||||
def check_for_updates(self, silent_no_updates=False):
|
def check_for_updates(self, silent_no_updates=False):
|
||||||
if self.update_thread and self.update_thread.is_alive():
|
if self._update_in_progress:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._update_check_silent = silent_no_updates
|
self._update_check_silent = silent_no_updates
|
||||||
|
self._update_in_progress = True
|
||||||
self._set_update_action_state(True)
|
self._set_update_action_state(True)
|
||||||
channel_label = "бета" if self.update_channel == "beta" else "релизы"
|
channel_label = "бета" if self.update_channel == "beta" else "релизы"
|
||||||
self.status_label.setText(f"Статус: проверка обновлений ({channel_label})...")
|
self.status_label.setText(f"Статус: проверка обновлений ({channel_label})...")
|
||||||
@@ -477,15 +478,21 @@ class VkChatManager(QMainWindow):
|
|||||||
request_timeout=UPDATE_REQUEST_TIMEOUT,
|
request_timeout=UPDATE_REQUEST_TIMEOUT,
|
||||||
channel=self.update_channel,
|
channel=self.update_channel,
|
||||||
)
|
)
|
||||||
|
self.update_thread = QThread(self)
|
||||||
|
self.update_checker.moveToThread(self.update_thread)
|
||||||
|
self.update_thread.started.connect(self.update_checker.run)
|
||||||
self.update_checker.check_finished.connect(self._on_update_check_finished)
|
self.update_checker.check_finished.connect(self._on_update_check_finished)
|
||||||
self.update_checker.check_failed.connect(self._on_update_check_failed)
|
self.update_checker.check_failed.connect(self._on_update_check_failed)
|
||||||
self.update_thread = threading.Thread(target=self.update_checker.run, daemon=True)
|
self.update_checker.check_finished.connect(self.update_thread.quit)
|
||||||
|
self.update_checker.check_failed.connect(self.update_thread.quit)
|
||||||
|
self.update_checker.check_finished.connect(self.update_checker.deleteLater)
|
||||||
|
self.update_checker.check_failed.connect(self.update_checker.deleteLater)
|
||||||
|
self.update_thread.finished.connect(self._on_update_thread_finished)
|
||||||
|
self.update_thread.finished.connect(self.update_thread.deleteLater)
|
||||||
self.update_thread.start()
|
self.update_thread.start()
|
||||||
|
|
||||||
def _on_update_check_finished(self, result):
|
def _on_update_check_finished(self, result):
|
||||||
self._set_update_action_state(False)
|
self._set_update_action_state(False)
|
||||||
self.update_checker = None
|
|
||||||
self.update_thread = None
|
|
||||||
|
|
||||||
if result.get("has_update"):
|
if result.get("has_update"):
|
||||||
latest_version = result.get("latest_version") or result.get("latest_tag") or "unknown"
|
latest_version = result.get("latest_version") or result.get("latest_tag") or "unknown"
|
||||||
@@ -499,6 +506,14 @@ class VkChatManager(QMainWindow):
|
|||||||
f"Доступная версия: {latest_version}\n\n"
|
f"Доступная версия: {latest_version}\n\n"
|
||||||
"Открыть страницу загрузки?"
|
"Открыть страницу загрузки?"
|
||||||
)
|
)
|
||||||
|
release_notes = (result.get("release_notes") or "").strip()
|
||||||
|
if release_notes:
|
||||||
|
preview_lines = [line.strip() for line in release_notes.splitlines() if line.strip()]
|
||||||
|
preview_text = "\n".join(preview_lines[:8])
|
||||||
|
if len(preview_lines) > 8:
|
||||||
|
preview_text += "\n..."
|
||||||
|
message_box.setInformativeText(f"Что нового:\n{preview_text}")
|
||||||
|
message_box.setDetailedText(release_notes)
|
||||||
update_now_button = message_box.addButton("Обновить сейчас", QMessageBox.ButtonRole.AcceptRole)
|
update_now_button = message_box.addButton("Обновить сейчас", QMessageBox.ButtonRole.AcceptRole)
|
||||||
download_button = message_box.addButton("Скачать", QMessageBox.ButtonRole.AcceptRole)
|
download_button = message_box.addButton("Скачать", QMessageBox.ButtonRole.AcceptRole)
|
||||||
setup_button = None
|
setup_button = None
|
||||||
@@ -538,8 +553,6 @@ class VkChatManager(QMainWindow):
|
|||||||
|
|
||||||
def _on_update_check_failed(self, error_text):
|
def _on_update_check_failed(self, error_text):
|
||||||
self._set_update_action_state(False)
|
self._set_update_action_state(False)
|
||||||
self.update_checker = None
|
|
||||||
self.update_thread = None
|
|
||||||
self._log_event("update_check_failed", error_text, level="WARN")
|
self._log_event("update_check_failed", error_text, level="WARN")
|
||||||
if not self.update_repository_url:
|
if not self.update_repository_url:
|
||||||
self.status_label.setText("Статус: обновления не настроены (URL репозитория не задан).")
|
self.status_label.setText("Статус: обновления не настроены (URL репозитория не задан).")
|
||||||
@@ -556,6 +569,11 @@ class VkChatManager(QMainWindow):
|
|||||||
if not self._update_check_silent:
|
if not self._update_check_silent:
|
||||||
QMessageBox.warning(self, "Проверка обновлений", error_text)
|
QMessageBox.warning(self, "Проверка обновлений", error_text)
|
||||||
|
|
||||||
|
def _on_update_thread_finished(self):
|
||||||
|
self._update_in_progress = False
|
||||||
|
self.update_checker = None
|
||||||
|
self.update_thread = None
|
||||||
|
|
||||||
def setup_token_timer(self):
|
def setup_token_timer(self):
|
||||||
self.token_countdown_timer = QTimer(self)
|
self.token_countdown_timer = QTimer(self)
|
||||||
self.token_countdown_timer.timeout.connect(self.update_token_timer_display)
|
self.token_countdown_timer.timeout.connect(self.update_token_timer_display)
|
||||||
@@ -975,12 +993,26 @@ class VkChatManager(QMainWindow):
|
|||||||
|
|
||||||
self.token = token
|
self.token = token
|
||||||
# Сохраняем и получаем корректный expiration_time (0 или будущее время)
|
# Сохраняем и получаем корректный expiration_time (0 или будущее время)
|
||||||
|
try:
|
||||||
self.token_expiration_time = token_store_save_token(
|
self.token_expiration_time = token_store_save_token(
|
||||||
self.token,
|
self.token,
|
||||||
TOKEN_FILE,
|
TOKEN_FILE,
|
||||||
APP_DATA_DIR,
|
APP_DATA_DIR,
|
||||||
expires_in=expires_in,
|
expires_in=expires_in,
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
expires_value = int(expires_in)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
expires_value = 0
|
||||||
|
self.token_expiration_time = (time.time() + expires_value) if expires_value > 0 else 0
|
||||||
|
self._log_event("token_store_save", str(e), level="WARN")
|
||||||
|
QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
"Предупреждение",
|
||||||
|
"Не удалось безопасно сохранить токен на диске. "
|
||||||
|
"Текущая сессия активна, но после перезапуска потребуется повторная авторизация.",
|
||||||
|
)
|
||||||
|
|
||||||
self.token_input.setText(self.token[:50] + "...")
|
self.token_input.setText(self.token[:50] + "...")
|
||||||
self.status_label.setText("Статус: авторизован")
|
self.status_label.setText("Статус: авторизован")
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ def save_token(token, token_file, app_data_dir, expires_in=0):
|
|||||||
try:
|
try:
|
||||||
stored_token = _encrypt_token(token)
|
stored_token = _encrypt_token(token)
|
||||||
encrypted = True
|
encrypted = True
|
||||||
except Exception:
|
except Exception as exc:
|
||||||
pass
|
raise RuntimeError("Failed to securely store token with DPAPI.") from exc
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"token": stored_token,
|
"token": stored_token,
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ def _extract_release_payload(release_data, repository_url, current_version):
|
|||||||
latest_tag = release_data.get("tag_name") or release_data.get("name") or ""
|
latest_tag = release_data.get("tag_name") or release_data.get("name") or ""
|
||||||
latest_version = latest_tag.lstrip("vV").strip()
|
latest_version = latest_tag.lstrip("vV").strip()
|
||||||
html_url = release_data.get("html_url") or releases_url
|
html_url = release_data.get("html_url") or releases_url
|
||||||
|
release_notes = (release_data.get("body") or "").strip()
|
||||||
assets = release_data.get("assets") or []
|
assets = release_data.get("assets") or []
|
||||||
download_url = ""
|
download_url = ""
|
||||||
download_name = ""
|
download_name = ""
|
||||||
@@ -147,6 +148,7 @@ def _extract_release_payload(release_data, repository_url, current_version):
|
|||||||
"current_version": current_version,
|
"current_version": current_version,
|
||||||
"latest_tag": latest_tag,
|
"latest_tag": latest_tag,
|
||||||
"release_url": html_url,
|
"release_url": html_url,
|
||||||
|
"release_notes": release_notes,
|
||||||
"download_url": download_url,
|
"download_url": download_url,
|
||||||
"download_name": download_name,
|
"download_name": download_name,
|
||||||
"installer_url": installer_url,
|
"installer_url": installer_url,
|
||||||
|
|||||||
Reference in New Issue
Block a user