From ce8fcbf9134a749dbf9244a41a20d9ba76a19bbd Mon Sep 17 00:00:00 2001 From: zhaoyafan Date: Wed, 12 Mar 2025 23:17:50 +0800 Subject: [PATCH] First commit --- TimeMaster.iss.template | 83 +++++++ TimeMaster.py | 483 ++++++++++++++++++++++++++++++++++++++++ build.bat | 3 + favicon.ico | Bin 0 -> 202536 bytes requirements.txt | Bin 0 -> 306 bytes 5 files changed, 569 insertions(+) create mode 100644 TimeMaster.iss.template create mode 100644 TimeMaster.py create mode 100644 build.bat create mode 100644 favicon.ico create mode 100644 requirements.txt diff --git a/TimeMaster.iss.template b/TimeMaster.iss.template new file mode 100644 index 0000000..99c452c --- /dev/null +++ b/TimeMaster.iss.template @@ -0,0 +1,83 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "%APPNAME%" +#define MyAppExec "%APPEXEC%" +#define MyAppVersion "%APPVERSION%" +#define MyAppBuildDate "%APPBUILDDATE%" +#define MyAppPublisher "%APPPUBLISHER%" +#define MyAppPublisherURL "%APPPUBLISHERURL%" + +[Code] +function IsProcessRunning(ExeFileName: string): Boolean; +var + FSWbemLocator: Variant; + FWMIService: Variant; + FWbemObject: Variant; +begin + Result := False; + FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); + FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2'); + FWbemObject := FWMIService.ExecQuery(Format('SELECT * FROM Win32_Process Where Name = "%s"', [ExeFileName])); + Result := not VarIsNull(FWbemObject) and (FWbemObject.Count > 0); +end; + +function InitializeSetup(): Boolean; +begin + if IsProcessRunning(ExpandConstant('{#MyAppExec}.exe')) then + begin + MsgBox('The main program is still running, please close it before installation.', mbError, MB_OK); + Result := False; + end + else + begin + Result := True; + end; +end; + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{7E345AAD-FB40-CAF0-B0FC-3A4CBD445240} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppPublisherURL} +VersionInfoProductName={#MyAppName} +VersionInfoProductTextVersion={#MyAppVersion} +VersionInfoProductVersion={#MyAppVersion} +VersionInfoTextVersion={#MyAppVersion} +VersionInfoVersion={#MyAppVersion} +DefaultDirName={autopf}\{#MyAppName} +DisableProgramGroupPage=yes +OutputBaseFilename={#MyAppName} Setup {#MyAppVersion} +OutputDir={#MyAppExec}.output +SetupIconFile={#MyAppExec}.dist\favicon.ico +UninstallDisplayIcon={app}\{#MyAppExec}.exe +Compression=lzma +SolidCompression=yes +WizardStyle=modern +CloseApplications=yes +%DISABLEX64%ArchitecturesAllowed=x64compatible +%DISABLEX64%ArchitecturesInstallIn64BitMode=x64compatible + +[UninstallRun] +Filename: "cmd.exe"; Parameters: "/C taskkill /IM {#MyAppExec}.exe /F"; Flags: runhidden + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "{#MyAppExec}.dist\{#MyAppExec}.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#MyAppExec}.dist\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExec}.exe" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExec}.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#MyAppExec}.exe"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent diff --git a/TimeMaster.py b/TimeMaster.py new file mode 100644 index 0000000..f3e7dae --- /dev/null +++ b/TimeMaster.py @@ -0,0 +1,483 @@ +import os +import sys +import time +import json +import ctypes +import shutil +import signal +import winreg +import hashlib +import inspect +import tempfile +import platform +import threading +import subprocess +import http.client +import urllib.parse +import datetime +from wmi import WMI +from tzlocal import get_localzone +from pytz import timezone +from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox, QMenu, QAction +from PyQt5.QtCore import Qt, QCoreApplication, QTimer +from PyQt5.QtGui import QIcon +from pathlib import Path + + +def _fd(f): + return f.fileno() if hasattr(f, 'fileno') else f + + +if os.name == 'nt': + import msvcrt + from ctypes import (sizeof, c_ulong, c_void_p, c_int64, Structure, Union, POINTER, windll, byref) + from ctypes.wintypes import BOOL, DWORD, HANDLE + + LOCK_SH = 0x0 + LOCK_NB = 0x1 + LOCK_EX = 0x2 + LOCK_UN = 0x9 + + if sizeof(c_ulong) != sizeof(c_void_p): + ULONG_PTR = c_int64 + else: + ULONG_PTR = c_ulong + + PVOID = c_void_p + + + class _OFFSET(Structure): + _fields_ = [ + ('Offset', DWORD), + ('OffsetHigh', DWORD) + ] + + + class _OFFSET_UNION(Union): + _fields_ = [ + ('_offset', _OFFSET), + ('Pointer', PVOID) + ] + _anonymous_ = ['_offset'] + + + class OVERLAPPED(Structure): + _fields_ = [ + ('Internal', ULONG_PTR), + ('InternalHigh', ULONG_PTR), + ('_offset_union', _OFFSET_UNION), + ('hEvent', HANDLE) + ] + _anonymous_ = ['_offset_union'] + + + LPOVERLAPPED = POINTER(OVERLAPPED) + LockFileEx = windll.kernel32.LockFileEx + LockFileEx.restype = BOOL + LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED] + UnlockFileEx = windll.kernel32.UnlockFileEx + UnlockFileEx.restype = BOOL + UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED] + + + def flock(f, flags): + hfile = msvcrt.get_osfhandle(_fd(f)) + overlapped = OVERLAPPED() + if flags == LOCK_UN: + ret = UnlockFileEx( + hfile, + 0, + 0, + 0xFFFF0000, + byref(overlapped) + ) + else: + ret = LockFileEx( + hfile, + flags, + 0, + 0, + 0xFFFF0000, + byref(overlapped) + ) + return bool(ret) +else: + try: + import fcntl + + LOCK_SH = fcntl.LOCK_SH + LOCK_NB = fcntl.LOCK_NB + LOCK_EX = fcntl.LOCK_EX + LOCK_UN = fcntl.LOCK_UN + except (ImportError, AttributeError): + LOCK_EX = LOCK_SH = LOCK_NB = 0 + + + def flock(f, flags): + return flags == LOCK_UN + else: + def flock(f, flags): + return fcntl.flock(_fd(f), flags) == 0 + +def request_windows_admin(): + if not ctypes.windll.shell32.IsUserAnAdmin(): + exec_home = os.path.dirname(__file__) + exec_name = os.path.splitext(os.path.basename(__file__))[0] + exec_path = os.path.join(exec_home, '%s.exe' % (exec_name,)) + if os.path.exists(exec_path): + executable_path = exec_path + else: + executable_path = sys.executable + executable_args = "\x20".join(sys.argv) + print('runas admin: %s %s' % (executable_path, executable_args), file=sys.stderr) + ctypes.windll.shell32.ShellExecuteW(None, 'runas', executable_path, executable_args, None, 1) + sys.exit(1) + + +class HTTPResponse: + status: int + reason: str + result: str + header: dict + def __init__(self, response): + self.status = response[0] + self.reason = response[1] + self.result = response[2] + self.header = response[3] + + def json(self): + try: + return json.loads(self.result) + except json.decoder.JSONDecodeError: + return None + + +class HTTPRequest: + user_agent: str = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' + + @classmethod + def _parse_headers(cls, headers): + return {key.lower(): value for key, value in headers} + + @classmethod + def get(cls, url='', header=None, timeout=15) -> HTTPResponse: + url = str(url) + header = header or {} + header = {**{'User-Agent': cls.user_agent}, **header} + host = urllib.parse.urlparse(url).netloc + conn = http.client.HTTPSConnection(host, timeout=timeout) if urllib.parse.urlparse(url).scheme == 'https' else http.client.HTTPConnection(host, timeout=timeout) + conn.request('GET', url, None, header) + response = conn.getresponse() + response_data = response.read().decode('utf-8') + response_headers = cls._parse_headers(response.getheaders()) + conn.close() + return HTTPResponse((response.status, response.reason, response_data, response_headers)) + + @classmethod + def post(cls, url='', data=None, json_data=None, header=None, timeout=15) -> HTTPResponse: + url = str(url) + header = header or {} + data = json.dumps(json_data) if json_data else (data and str(data).encode('utf-8')) + header = {**{'User-Agent': cls.user_agent}, **header} + host = urllib.parse.urlparse(url).netloc + conn = http.client.HTTPSConnection(host, timeout=timeout) if urllib.parse.urlparse(url).scheme == 'https' else http.client.HTTPConnection(host, timeout=timeout) + conn.request('POST', url, data, header) + response = conn.getresponse() + response_data = response.read().decode('utf-8') + response_headers = cls._parse_headers(response.getheaders()) + conn.close() + return HTTPResponse((response.status, response.reason, response_data, response_headers)) + + @classmethod + def head(cls, url='', header=None, timeout=15) -> HTTPResponse: + url = str(url) + header = header or {} + header = {**{'User-Agent': cls.user_agent}, **header} + host = urllib.parse.urlparse(url).netloc + conn = http.client.HTTPSConnection(host, timeout=timeout) if urllib.parse.urlparse(url).scheme == 'https' else http.client.HTTPConnection(host, timeout=timeout) + conn.request('HEAD', url, None, header) + response = conn.getresponse() + response_data = response.read().decode('utf-8') + response_headers = cls._parse_headers(response.getheaders()) + conn.close() + return HTTPResponse((response.status, response.reason, response_data, response_headers)) + + +class MainWindow(QSystemTrayIcon): + def __init__(self, app_name, app_version): + self.app_name = app_name + self.app_version = app_version + self.last_sync_time = 0 + self.last_sync_exception = '' + self.is_synchronizing = None + super().__init__(QIcon(os.path.join(os.path.dirname(__file__), 'favicon.ico')), None) + self.setToolTip('') + self.tray_icon_update_timer = QTimer(self) + self.tray_icon_update_timer.timeout.connect(self.on_tray_icon_update) + self.tray_icon_update_timer.start(1500) + self.time_sync_update_timer = QTimer(self) + self.time_sync_update_timer.timeout.connect(self.sync) + self.time_sync_update_timer.start(1000 * 3600) + QTimer.singleShot(1000 * 12, self.sync) + self.tray_menu = QMenu() + action_list = [ + ['立即同步', self.sync], + ['退出程序', self.exit] + ] + for action_item in action_list: + action = QAction(action_item[0], self) + action.triggered.connect(action_item[1]) + self.tray_menu.addAction(action) + self.setContextMenu(self.tray_menu) + self.show() + self.init() + + + def init(self): + self.sync() + + @staticmethod + def exit(): + QApplication.quit() + + def _sync_execution(self): + try: + self.is_synchronizing = 1 + dt = self.get_server_datetime() + set_date = dt and self.set_date(dt[0]) + set_time = dt and self.set_time(dt[1]) + if (set_date and set_time) == 1: + self.last_sync_time = self.get_runtime() + self.last_sync_exception = '' + else: + self.last_sync_exception = '操作失败,可能需要以管理员身份运行' + except Exception as e: + if 'server' in str(e).lower(): + self.last_sync_exception = '网络错误' + finally: + self.is_synchronizing = 0 + + def sync(self): + if (not self.is_synchronizing) == 1: + print('Synchronizing...') + threading.Thread(target=self._sync_execution).start() + + @staticmethod + def format_time(secs): + return '刚刚' if secs < 60 else '%s分钟前' % ((secs // 60),) if secs < 3600 else '%s小时前' % (round(secs / 3600),) + + @staticmethod + def get_runtime(): + return time.perf_counter() + + @staticmethod + def set_date(date_str): + try: + process = subprocess.run('date %s' % (date_str,), shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=2) + if process.returncode == 0: + return True + else: + return False + except subprocess.TimeoutExpired: + pass + return True + + @staticmethod + def set_time(time_str): + try: + process = subprocess.run('time %s' % (time_str,), shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=2) + if process.returncode == 0: + return True + else: + return False + except subprocess.TimeoutExpired: + pass + + @staticmethod + def get_server_datetime(): + try: + gate = WMI().Win32_NetworkAdapterConfiguration(IPEnabled=True)[0].DefaultIPGateway[0] + except Exception: + gate = None + server_list = ['cloud.tencent.com', '1.1.1.2', gate] + date_string = '' + for server in server_list: + if server is not None: + try: + date_string = HTTPRequest.head(url='http://%s/' % (server,), timeout=1).header.get('date') + break + except Exception: + continue + if not date_string: + raise Exception('Failed to get time from server.') + ori_timezone = timezone('GMT') + tar_timezone = timezone(str(get_localzone())) + try: + date_out = ori_timezone.localize(datetime.datetime.strptime(date_string, '%a, %d %b %Y %H:%M:%S %Z')).astimezone(tar_timezone) + datetime.timedelta(seconds=1) + if (int(date_out.timestamp()) > 1735689600) == 1: + return str(date_out.date()), str(date_out.time()) + raise Exception('The time returned by the server is older.') + except ValueError: + raise Exception('Failed to get time from server.') + + def on_tray_icon_update(self): + self.setToolTip('%s %s\n上次同步:%s' % (self.app_name, self.app_version, self.last_sync_exception or self.format_time(int(self.get_runtime() - self.last_sync_time)))) + + +class MainRunner: + def __init__(self): + signal.signal(signal.SIGINT, self._handle_interrupt) + self.app_name = '时间同步助手' + self.app_version = '1.0.0.0' + self.app_publisher = 'zhaoyafan' + self.app_publisher_url = 'https://www.fanscloud.net/' + self.application = None + self.window = None + + def _copy_files_and_directories(self, src, dst): + function_name = inspect.currentframe().f_code.co_name + if (os.path.exists(src)) != 1: + return None + if (os.path.isdir(src)) == 1: + if not os.path.exists(dst): + os.makedirs(dst) + for item in os.listdir(src): + s = os.path.join(src, item) + d = os.path.join(dst, item) + if os.path.isdir(s): + self.__getattribute__(function_name)(s, d) + else: + shutil.copy(s, d) + else: + shutil.copy(src, dst) + + @staticmethod + def add_startup(entry_name, exe_path): + if not os.path.exists(exe_path): + return None + try: + key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Windows\\CurrentVersion\\Run', 0, winreg.KEY_SET_VALUE) + winreg.SetValueEx(key, entry_name, 0, winreg.REG_SZ, exe_path) + winreg.CloseKey(key) + return True + except Exception: + return False + + @staticmethod + def del_startup(entry_name): + try: + key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Windows\\CurrentVersion\\Run', 0, winreg.KEY_SET_VALUE) + winreg.DeleteValue(key, entry_name) + winreg.CloseKey(key) + return True + except Exception: + return False + + def run(self): + request_windows_admin() + exec_home = os.path.dirname(__file__) + exec_name = os.path.splitext(os.path.basename(__file__))[0] + self.add_startup(exec_name, os.path.join(exec_home, '%s.exe' % (exec_name,))) + QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) + self.application = QApplication(sys.argv) + self.window = MainWindow(app_name=self.app_name, app_version=self.app_version) + sys.exit(self.application.exec_()) + + def build(self): + if (str(__file__).endswith('.py')) == 0: + print('Build is not currently supported.', file=sys.stderr) + exit(1) + from_home = os.path.dirname(os.path.abspath(__file__)) + dist_home = os.path.join(os.path.dirname(__file__), '%s.dist' % (os.path.splitext(os.path.basename(__file__))[0],)) + ask = input('%s %s: ' % ('Build?', '[Y/n]')) + if ask.lower().strip() == 'y': + subprocess.run(['pip', 'install', 'nuitka', '-q'], shell=True, env=os.environ) + subprocess.run([ + 'python', + '-m', + 'nuitka', + '--standalone', + '--enable-plugin=pyqt5', + '--include-module=PyQt5', + '--windows-console-mode=disable', + '--windows-icon-from-ico=favicon.ico', + '--product-name=%s' % (self.app_name,), + '--file-description=%s' % (self.app_name,), + '--product-version=%s' % (self.app_version,), + '--copyright=Copyright (C) 2025', + '--output-dir=%s' % (os.path.join(os.path.dirname(__file__)),), + '%s' % (__file__,) + ], shell=True, env=os.environ) + for i in ['PyQt5', 'favicon.ico']: + self._copy_files_and_directories('%s/%s' % (from_home, i), '%s/%s' % (dist_home, i)) + else: + if (not os.path.exists(dist_home)) == 1: + return None + ask = input('%s %s: ' % ('Compile setup program?', '[Y/n]')) + if ask.lower().strip() == 'y': + compile_file = os.path.join(os.path.dirname(__file__), '%s.iss' % (os.path.splitext(os.path.basename(__file__))[0],)) + compile_template = os.path.join(os.path.dirname(__file__), '%s.iss.template' % (os.path.splitext(os.path.basename(__file__))[0],)) + compiler = 'C:\\Program Files (x86)\\Inno Setup 6\\ISCC.exe' + if (os.path.exists(compile_template)) != 1: + print('The template file \"%s\" does not exist.' % (compile_template,), file=sys.stderr) + return None + if (os.path.exists(compiler)) != 1: + print('The compiler \"%s\" does not exist. Please check if Inno Setup is installed. You can download it at https://www.innosetup.com/' % (compiler,), + file=sys.stderr) + return None + Path(compile_file).write_text( + Path(compile_template).read_text().replace( + '%APPNAME%', + self.app_name + ).replace( + '%APPEXEC%', + os.path.splitext(os.path.basename(__file__))[0] + ).replace( + '%APPVERSION%', + self.app_version + ).replace( + '%APPBUILDDATE%', + time.strftime('%Y%m%d', time.localtime()) + ).replace( + '%APPPUBLISHER%', + self.app_publisher + ).replace( + '%APPPUBLISHERURL%', + self.app_publisher_url + ).replace( + '%DISABLEX64%', + '' if platform.architecture()[0] == '64bit' else '; ' + ) + ) + subprocess.run([compiler, compile_file]) + + def _handle_interrupt(self, _signal, _frame): + print('Exit.', file=sys.stderr) + self.handle_interrupt() + + def handle_interrupt(self): + try: + self.window.exit() + except Exception as e: + print(e, file=sys.stderr) + + +if __name__ == '__main__': + if (os.path.basename(__file__).lower().endswith('.int')) == 1: + QCoreApplication.addLibraryPath(os.path.join(os.path.dirname(__file__), 'site-packages/PyQt5/Qt5/plugins')) + else: + QCoreApplication.addLibraryPath(os.path.join(os.path.dirname(__file__), 'PyQt5/Qt5/plugins')) + f_lock = open(file=os.path.join(tempfile.gettempdir(), '%s.lock' % hashlib.md5(bytes(__file__, encoding='utf-8')).hexdigest()[:16]), mode='w', encoding='utf-8') + if (not flock(f_lock, LOCK_EX | LOCK_NB)) == 1: + app = QApplication(sys.argv) + msg = QMessageBox() + msg.setIcon(QMessageBox.Warning) + msg.setText('The application is already running.') + msg.setWindowTitle('Warning') + msg.setStandardButtons(QMessageBox.Cancel) + msg.exec_() + app.exit(1) + sys.exit(1) + else: + MainRunner().run() if (len(sys.argv) > 1 and sys.argv[1] == '--build') == 0 else MainRunner().build() diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..cd47eab --- /dev/null +++ b/build.bat @@ -0,0 +1,3 @@ +@echo off +@chcp 65001 +@python TimeMaster.py --build diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..57b6fb7cc8726c7706b606f22e7ed694e9c8ba9e GIT binary patch literal 202536 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 T{=H6mvj!OIn(EYQImiDWVS<$; literal 0 HcmV?d00001 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b41ad0d4ea794bcee1436af4a5cde81430d09640 GIT binary patch literal 306 zcmZvX!3x4a3`FNF_$f+vOAj9W01twmJc?F@V$ot3L_c1ANfn`#B}Y#S}La4dlR{XQjH BDy#qi literal 0 HcmV?d00001