168 lines
5.2 KiB
Python
Executable file
168 lines
5.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Copyright (c) 2023 zhbaor <zhbaor@zhaozuohong.vip>
|
|
|
|
This file is part of mower-ng (https://git.zhaozuohong.vip/mower-ng/mower-ng).
|
|
|
|
Mower-ng is free software: you may copy, redistribute and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation, version 3 or later.
|
|
|
|
This file is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
This file incorporates work covered by the following copyright and
|
|
permission notice:
|
|
|
|
Copyright (c) 2024 MuelNova <muel@nova.gal>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import time
|
|
import webbrowser
|
|
from datetime import datetime, timedelta
|
|
from threading import Thread
|
|
|
|
|
|
def show_error_then_exit(msg: str):
|
|
try:
|
|
from tkinter import messagebox
|
|
|
|
messagebox.showerror(title="mower-ng", message=msg)
|
|
except Exception:
|
|
print(msg)
|
|
sys.exit()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from mower.utils import path
|
|
|
|
if len(sys.argv) == 2:
|
|
path.global_space = sys.argv[1]
|
|
|
|
lock_file = path.get_path("@app/lockfile.json")
|
|
if lock_file.exists():
|
|
import psutil
|
|
|
|
try:
|
|
with lock_file.open("r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
pid = data["pid"]
|
|
if psutil.pid_exists(pid):
|
|
show_error_then_exit(f"mower-ng进程正在运行(PID: {pid})")
|
|
except Exception:
|
|
pass
|
|
|
|
from mower import __system__, __version__
|
|
from mower.utils import config
|
|
from mower.utils.network import get_new_port, is_port_in_use
|
|
from server import app
|
|
|
|
token = config.conf.webview.token
|
|
host = "0.0.0.0" if token else "127.0.0.1"
|
|
if token:
|
|
port = config.conf.webview.port
|
|
if is_port_in_use(port):
|
|
show_error_then_exit(f"端口{port}已被占用,无法启动")
|
|
else:
|
|
port = get_new_port()
|
|
|
|
with lock_file.open("w", encoding="utf-8") as f:
|
|
json.dump({"pid": os.getpid(), "port": port, "token": token}, f)
|
|
|
|
url = f"http://127.0.0.1:{port}"
|
|
if token:
|
|
url += f"?token={token}"
|
|
if token:
|
|
app.token = token
|
|
|
|
flask_thread = Thread(
|
|
target=app.run,
|
|
kwargs={"host": "::" if token else "127.0.0.1", "port": port},
|
|
daemon=True,
|
|
)
|
|
flask_thread.start()
|
|
if __system__ == "windows" and token:
|
|
Thread(
|
|
target=app.run,
|
|
kwargs={"host": "0.0.0.0", "port": port},
|
|
daemon=True,
|
|
).start()
|
|
|
|
from PIL import Image
|
|
from pystray import Icon, Menu, MenuItem
|
|
|
|
img = Image.open(path.get_path("@install/logo.png"))
|
|
display_path = path.global_space or "单开运行"
|
|
|
|
icon = Icon(
|
|
name="mower-ng",
|
|
icon=img,
|
|
menu=Menu(
|
|
MenuItem(
|
|
text=f"mower-ng@{__version__}",
|
|
action=None,
|
|
enabled=False,
|
|
),
|
|
MenuItem(
|
|
text=display_path,
|
|
action=None,
|
|
enabled=False,
|
|
),
|
|
Menu.SEPARATOR,
|
|
MenuItem(
|
|
text="打开网页面板",
|
|
action=lambda: webbrowser.open(url),
|
|
default=True,
|
|
),
|
|
MenuItem(
|
|
text="退出",
|
|
action=lambda: icon.stop(),
|
|
),
|
|
),
|
|
title=f"mower-ng ({display_path})",
|
|
)
|
|
|
|
def open_browser():
|
|
start_time = datetime.now()
|
|
port_occupied = False
|
|
while datetime.now() - start_time < timedelta(seconds=10):
|
|
if is_port_in_use(port):
|
|
port_occupied = True
|
|
break
|
|
time.sleep(0.1)
|
|
if not port_occupied:
|
|
show_error_then_exit("Flask服务器启动失败")
|
|
|
|
webbrowser.open(url)
|
|
|
|
Thread(target=open_browser, daemon=True).start()
|
|
icon.run()
|
|
|
|
lock_file.unlink()
|