Compare commits

...

2 Commits

Author SHA1 Message Date
Koha9
d4ed9d22f5 Add scheme dropdown and load defaults from config 2025-06-21 19:34:07 +09:00
Koha9
7ab55e3ae4 Add HTTPS support for server URL 2025-06-21 19:20:48 +09:00
5 changed files with 78 additions and 7 deletions

View File

@ -16,6 +16,7 @@ PlexPlaylistSync 是一个用于同步 Plex 播放列表和本地 `.m3u`/`.m3u8`
首次登录时使用用户名和密码连接 Plex 服务器,成功后程序会将获得的 `token` 保存在配置文件中,后续通信仅使用该 `token`,不再保存明文密码。 首次登录时使用用户名和密码连接 Plex 服务器,成功后程序会将获得的 `token` 保存在配置文件中,后续通信仅使用该 `token`,不再保存明文密码。
默认情况下 Plex 服务器使用 `32400` 端口,可在未修改服务器端口时直接使用该默认值。 默认情况下 Plex 服务器使用 `32400` 端口,可在未修改服务器端口时直接使用该默认值。
登录页面提供选择 `http``https` 的下拉框,服务器地址输入框只需填写域名或 IP默认值会从 `config.json` 读取。
## 安装 ## 安装

View File

@ -1,5 +1,5 @@
import os import os
from app.utils.config import load_config, save_config from app.utils.config import load_config, save_config, get_server_settings
from fastapi import FastAPI, Request, Form from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
@ -18,27 +18,54 @@ app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__
async def home(request: Request): async def home(request: Request):
config = load_config() config = load_config()
theme = config.get("theme", "auto") theme = config.get("theme", "auto")
return templates.TemplateResponse("login.html", {"request": request, "theme": theme, "path": "/login"}) scheme, host, port = get_server_settings(config)
return templates.TemplateResponse(
"login.html",
{
"request": request,
"theme": theme,
"path": "/login",
"scheme": scheme,
"server_url": host,
"port": port,
},
)
@app.get("/login", response_class=HTMLResponse) @app.get("/login", response_class=HTMLResponse)
async def login_page(request: Request): async def login_page(request: Request):
config = load_config() config = load_config()
theme = config.get("theme", "auto") theme = config.get("theme", "auto")
return templates.TemplateResponse("login.html", {"request": request, "theme": theme, "path": "/login"}) scheme, host, port = get_server_settings(config)
return templates.TemplateResponse(
"login.html",
{
"request": request,
"theme": theme,
"path": "/login",
"scheme": scheme,
"server_url": host,
"port": port,
},
)
@app.post("/login", response_class=HTMLResponse) @app.post("/login", response_class=HTMLResponse)
async def login( async def login(
request: Request, request: Request,
user: str = Form(...), user: str = Form(...),
pw: str = Form(...), pw: str = Form(...),
scheme: str = Form("https"),
url: str = Form(...), url: str = Form(...),
port: str = Form("32400") port: str = Form("32400")
): ):
config = load_config() config = load_config()
theme = config.get("theme", "auto") theme = config.get("theme", "auto")
try: try:
connect_plex(config, user, pw, url, port) full_url = url
if not full_url.startswith("http://") and not full_url.startswith("https://"):
full_url = f"{scheme}://{url}"
connect_plex(config, user, pw, full_url, port)
save_config(config) save_config(config)
scheme, host, port = get_server_settings(config)
return templates.TemplateResponse( return templates.TemplateResponse(
"login.html", "login.html",
{ {
@ -47,6 +74,9 @@ async def login(
"success": True, "success": True,
"theme": theme, "theme": theme,
"path": "/login", "path": "/login",
"scheme": scheme,
"server_url": host,
"port": port,
}, },
) )
except Exception as e: except Exception as e:
@ -58,6 +88,9 @@ async def login(
"success": False, "success": False,
"theme": theme, "theme": theme,
"path": "/login", "path": "/login",
"scheme": scheme,
"server_url": url,
"port": port,
}, },
) )

View File

@ -13,13 +13,20 @@
<label for="pw" class="form-label">密码</label> <label for="pw" class="form-label">密码</label>
<input type="password" class="form-control" id="pw" name="pw"> <input type="password" class="form-control" id="pw" name="pw">
</div> </div>
<div class="mb-3">
<label for="scheme" class="form-label">协议</label>
<select class="form-select" id="scheme" name="scheme">
<option value="http" {% if scheme == 'http' %}selected{% endif %}>http</option>
<option value="https" {% if scheme == 'https' %}selected{% endif %}>https</option>
</select>
</div>
<div class="mb-3"> <div class="mb-3">
<label for="url" class="form-label">服务器地址</label> <label for="url" class="form-label">服务器地址</label>
<input type="text" class="form-control" id="url" name="url" placeholder="127.0.0.1"> <input type="text" class="form-control" id="url" name="url" placeholder="127.0.0.1 或 plex.sample.com" value="{{ server_url }}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="port" class="form-label">端口</label> <label for="port" class="form-label">端口</label>
<input type="text" class="form-control" id="port" name="port" value="32400"> <input type="text" class="form-control" id="port" name="port" value="{{ port }}">
</div> </div>
<button type="submit" class="btn btn-primary">连接</button> <button type="submit" class="btn btn-primary">连接</button>
</form> </form>

View File

@ -1,5 +1,6 @@
import json import json
import os import os
from urllib.parse import urlparse
CONFIG_PATH = os.path.join(os.path.dirname(__file__), "..", "config.json") CONFIG_PATH = os.path.join(os.path.dirname(__file__), "..", "config.json")
@ -12,3 +13,23 @@ def load_config():
def save_config(new_config): def save_config(new_config):
with open(CONFIG_PATH, "w", encoding="utf-8") as f: with open(CONFIG_PATH, "w", encoding="utf-8") as f:
json.dump(new_config, f, indent=4, ensure_ascii=False) json.dump(new_config, f, indent=4, ensure_ascii=False)
def get_server_settings(config):
"""Return (scheme, host, port) using defaults when not configured."""
scheme = "https"
host = ""
port = config.get("server_port", "32400") or "32400"
url = config.get("server_url", "")
if url:
parsed = urlparse(url)
if parsed.scheme:
scheme = parsed.scheme
host = parsed.hostname or parsed.netloc
if parsed.port:
port = str(parsed.port)
else:
host = url
return scheme, host, port

View File

@ -1,5 +1,6 @@
from plexapi.myplex import MyPlexAccount from plexapi.myplex import MyPlexAccount
from plexapi.server import PlexServer from plexapi.server import PlexServer
from urllib.parse import urlparse
def connect_plex(config, username, password, url, port="32400"): def connect_plex(config, username, password, url, port="32400"):
@ -10,7 +11,15 @@ def connect_plex(config, username, password, url, port="32400"):
token = account.authenticationToken token = account.authenticationToken
config["token"] = token config["token"] = token
base_url = f"http://{url}:{port}" parsed = urlparse(url)
if parsed.scheme in ("http", "https"):
netloc = parsed.netloc or parsed.path
if ":" not in netloc and port:
netloc = f"{netloc}:{port}"
base_url = f"{parsed.scheme}://{netloc}"
else:
base_url = f"http://{url}:{port}"
server = PlexServer(base_url, token) server = PlexServer(base_url, token)
config.update({"server_url": url, "server_port": port}) config.update({"server_url": url, "server_port": port})
return server return server