style: 代码格式化和字符串处理优化

- 优化代码缩进和换行,提高可读性
- 统一使用单引号或双引号,保持一致性
- 移除冗余的空格和括号,精简代码
This commit is contained in:
2025-02-15 21:30:24 +08:00
parent 94198f5a51
commit 1570ba320c
34 changed files with 948 additions and 358 deletions

View File

@@ -1,3 +1,3 @@
from .app import XHSDownloader
__all__ = ['XHSDownloader']
__all__ = ["XHSDownloader"]

View File

@@ -20,46 +20,53 @@ __all__ = ["About"]
class About(Screen):
BINDINGS = [
Binding(
key="Q",
action="quit",
description=_("退出程序")),
Binding(
key="U",
action="update",
description=_("检查更新")),
Binding(
key="B",
action="back",
description=_("返回首页")),
Binding(key="Q", action="quit", description=_("退出程序")),
Binding(key="U", action="update", description=_("检查更新")),
Binding(key="B", action="back", description=_("返回首页")),
]
def __init__(self, ):
def __init__(
self,
):
super().__init__()
def compose(self) -> ComposeResult:
yield Header()
yield Label(
Text(
_("如果 XHS-Downloader 对您有帮助,请考虑为它点个 Star感谢您的支持"),
_(
"如果 XHS-Downloader 对您有帮助,请考虑为它点个 Star感谢您的支持"
),
style=INFO,
),
classes="prompt",
)
yield Label(Text(_("Discord 社区"), style=PROMPT), classes="prompt", )
yield Label(
Text(_("Discord 社区"), style=PROMPT),
classes="prompt",
)
yield Link(
_("邀请链接:") + "https://discord.com/invite/ZYtmgKud9Y",
url="https://discord.com/invite/ZYtmgKud9Y",
tooltip=_("点击访问"),
)
yield Label(Text(_("作者的其他开源项目"), style=PROMPT), classes="prompt", )
yield Label(Text("TikTokDownloader (抖音 / TikTok)", style=MASTER), classes="prompt", )
yield Label(
Text(_("作者的其他开源项目"), style=PROMPT),
classes="prompt",
)
yield Label(
Text("TikTokDownloader (抖音 / TikTok)", style=MASTER),
classes="prompt",
)
yield Link(
"https://github.com/JoeanAmier/TikTokDownloader",
url="https://github.com/JoeanAmier/TikTokDownloader",
tooltip=_("点击访问"),
)
yield Label(Text("KS-Downloader (快手)", style=MASTER), classes="prompt", )
yield Label(
Text("KS-Downloader (快手)", style=MASTER),
classes="prompt",
)
yield Link(
"https://github.com/JoeanAmier/KS-Downloader",
url="https://github.com/JoeanAmier/KS-Downloader",

View File

@@ -49,20 +49,31 @@ class XHSDownloader(App):
Setting(
self.parameter,
),
name="setting")
self.install_screen(Index(self.APP, ), name="index")
name="setting",
)
self.install_screen(
Index(
self.APP,
),
name="index",
)
self.install_screen(Loading(), name="loading")
self.install_screen(About(), name="about")
self.install_screen(Record(self.APP, ), name="record")
self.install_screen(
Record(
self.APP,
),
name="record",
)
await self.push_screen("index")
self.SETTINGS.check_keys(
self.parameter,
logging,
self.query_one(RichLog),
_("配置文件 settings.json 缺少必要的参数,请删除该文件,然后重新运行程序,自动生成默认配置文件!") +
f"\n{
">" *
50}",
_(
"配置文件 settings.json 缺少必要的参数,请删除该文件,然后重新运行程序,自动生成默认配置文件!"
)
+ f"\n{'>' * 50}",
ERROR,
)
@@ -84,22 +95,41 @@ class XHSDownloader(App):
self.uninstall_screen("loading")
self.uninstall_screen("about")
self.uninstall_screen("record")
self.install_screen(Index(self.APP, ), name="index")
self.install_screen(
Index(
self.APP,
),
name="index",
)
self.install_screen(
Setting(
self.parameter,
),
name="setting")
name="setting",
)
self.install_screen(Loading(), name="loading")
self.install_screen(About(), name="about")
self.install_screen(Record(self.APP, ), name="record")
self.install_screen(
Record(
self.APP,
),
name="record",
)
await self.push_screen("index")
def update_result(self, args: tuple[str, str]) -> None:
self.notify(args[0], severity=args[1], )
self.notify(
args[0],
severity=args[1],
)
async def action_update(self):
await self.push_screen(Update(self.APP, ), callback=self.update_result)
await self.push_screen(
Update(
self.APP,
),
callback=self.update_result,
)
async def close_database(self):
await self.APP.id_recorder.cursor.close()

View File

@@ -42,7 +42,10 @@ class Index(Screen):
Binding(key="A", action="about", description=_("关于项目")),
]
def __init__(self, app: XHS, ):
def __init__(
self,
app: XHS,
):
super().__init__()
self.xhs = app
self.url = None
@@ -51,11 +54,7 @@ class Index(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield ScrollableContainer(
Label(
Text(
_("开源协议: ") + LICENCE,
style=MASTER)
),
Label(Text(_("开源协议: ") + LICENCE, style=MASTER)),
Link(
Text(
_("项目地址: ") + REPOSITORY,
@@ -65,9 +64,8 @@ class Index(Screen):
tooltip=_("点击访问"),
),
Label(
Text(
_("请输入小红书图文/视频作品链接"),
style=PROMPT), classes="prompt",
Text(_("请输入小红书图文/视频作品链接"), style=PROMPT),
classes="prompt",
),
Input(placeholder=_("多个链接之间使用空格分隔")),
HorizontalScroll(
@@ -76,7 +74,11 @@ class Index(Screen):
Button(_("清空输入框"), id="reset"),
),
)
yield RichLog(markup=True, wrap=True, auto_scroll=True, )
yield RichLog(
markup=True,
wrap=True,
auto_scroll=True,
)
yield Footer()
def on_mount(self) -> None:
@@ -84,15 +86,12 @@ class Index(Screen):
self.url = self.query_one(Input)
self.tip = self.query_one(RichLog)
self.tip.write(
Text(
_("免责声明\n") +
f"\n{
">" *
50}",
style=MASTER),
Text(_("免责声明\n") + f"\n{'>' * 50}", style=MASTER),
scroll_end=True,
)
self.xhs.manager.print_proxy_tip(log=self.tip, )
self.xhs.manager.print_proxy_tip(
log=self.tip,
)
@on(Button.Pressed, "#deal")
async def deal_button(self):
@@ -119,7 +118,14 @@ class Index(Screen):
@work(exclusive=True)
async def deal(self):
await self.app.push_screen("loading")
if any(await self.xhs.extract(self.url.value, True, log=self.tip, data=False, )):
if any(
await self.xhs.extract(
self.url.value,
True,
log=self.tip,
data=False,
)
):
self.url.value = ""
else:
self.tip.write(
@@ -143,7 +149,11 @@ class Index(Screen):
await self.app.run_action("settings")
async def action_monitor(self):
await self.app.push_screen(Monitor(self.xhs, ))
await self.app.push_screen(
Monitor(
self.xhs,
)
)
async def action_about(self):
await self.app.push_screen("about")

View File

@@ -10,7 +10,9 @@ __all__ = ["Loading"]
class Loading(ModalScreen):
def __init__(self, ):
def __init__(
self,
):
super().__init__()
def compose(self) -> ComposeResult:

View File

@@ -27,7 +27,10 @@ class Monitor(Screen):
Binding(key="C", action="close", description=_("关闭监听")),
]
def __init__(self, app: XHS, ):
def __init__(
self,
app: XHS,
):
super().__init__()
self.xhs = app
@@ -44,15 +47,22 @@ class Monitor(Screen):
@work(exclusive=True)
async def run_monitor(self):
await self.xhs.monitor(download=True, log=self.query_one(RichLog), data=False, )
await self.xhs.monitor(
download=True,
log=self.query_one(RichLog),
data=False,
)
await self.action_close()
def on_mount(self) -> None:
self.title = PROJECT
self.query_one(RichLog).write(
Text(_(
"程序会自动读取并提取剪贴板中的小红书作品链接,并自动下载链接对应的作品文件,如需关闭,请点击关闭按钮,或者向剪贴板写入 “close” 文本!"),
style=MASTER),
Text(
_(
"程序会自动读取并提取剪贴板中的小红书作品链接,并自动下载链接对应的作品文件,如需关闭,请点击关闭按钮,或者向剪贴板写入 “close” 文本!"
),
style=MASTER,
),
scroll_end=True,
)
self.run_monitor()

View File

@@ -14,23 +14,37 @@ __all__ = ["Record"]
class Record(ModalScreen):
def __init__(self, app: XHS, ):
def __init__(
self,
app: XHS,
):
super().__init__()
self.xhs = app
def compose(self) -> ComposeResult:
yield Grid(
Label(_("请输入待删除的小红书作品链接或作品 ID"), classes="prompt"),
Input(placeholder=_("支持输入作品 ID 或包含作品 ID 的作品链接,多个链接或 ID 之间使用空格分隔"),
id="id", ),
Input(
placeholder=_(
"支持输入作品 ID 或包含作品 ID 的作品链接,多个链接或 ID 之间使用空格分隔"
),
id="id",
),
HorizontalScroll(
Button(_("删除指定作品 ID"), id="enter", ),
Button(_("返回首页"), id="close"), ),
Button(
_("删除指定作品 ID"),
id="enter",
),
Button(_("返回首页"), id="close"),
),
id="record",
)
async def delete(self, text: str):
text = await self.xhs.extract_links(text, None, )
text = await self.xhs.extract_links(
text,
None,
)
text = self.xhs.extract_id(text)
await self.xhs.id_recorder.delete(text)
self.app.notify(_("删除下载记录成功"))

View File

@@ -23,49 +23,151 @@ class Setting(Screen):
Binding(key="B", action="index", description=_("返回首页")),
]
def __init__(self, data: dict, ):
def __init__(
self,
data: dict,
):
super().__init__()
self.data = data
def compose(self) -> ComposeResult:
yield Header()
yield ScrollableContainer(
Label(_("作品数据 / 文件保存根路径"), classes="params", ),
Input(self.data["work_path"], placeholder=_("程序根路径"), valid_empty=True,
id="work_path", ),
Label(_("作品文件储存文件夹名称"), classes="params", ),
Input(self.data["folder_name"], placeholder="Download", id="folder_name", ),
Label(_("作品文件名称格式"), classes="params", ),
Input(self.data["name_format"], placeholder="发布时间 作者昵称 作品标题", valid_empty=True,
id="name_format", ),
Label("User-Agent", classes="params", ),
Input(self.data["user_agent"], placeholder=_("内置 Chrome User Agent"), valid_empty=True,
id="user_agent", ),
Label(_("小红书网页版 Cookie"), classes="params", ),
Input(placeholder=self.__check_cookie(), valid_empty=True, id="cookie", ),
Label(_("网络代理"), classes="params", ),
Input(self.data["proxy"], placeholder=_("不使用代理"), valid_empty=True, id="proxy", ),
Label(_("请求数据超时限制,单位:秒"), classes="params", ),
Input(str(self.data["timeout"]), placeholder="10", type="integer", id="timeout", ),
Label(_("下载文件时,每次从服务器获取的数据块大小,单位:字节"), classes="params", ),
Input(str(self.data["chunk"]), placeholder="1048576", type="integer", id="chunk", ),
Label(_("请求数据失败时,重试的最大次数"), classes="params", ),
Input(str(self.data["max_retry"]), placeholder="5", type="integer", id="max_retry", ),
Label(
_("作品数据 / 文件保存根路径"),
classes="params",
),
Input(
self.data["work_path"],
placeholder=_("程序根路径"),
valid_empty=True,
id="work_path",
),
Label(
_("作品文件储存文件夹名称"),
classes="params",
),
Input(
self.data["folder_name"],
placeholder="Download",
id="folder_name",
),
Label(
_("作品文件名称格式"),
classes="params",
),
Input(
self.data["name_format"],
placeholder="发布时间 作者昵称 作品标题",
valid_empty=True,
id="name_format",
),
Label(
"User-Agent",
classes="params",
),
Input(
self.data["user_agent"],
placeholder=_("内置 Chrome User Agent"),
valid_empty=True,
id="user_agent",
),
Label(
_("小红书网页版 Cookie"),
classes="params",
),
Input(
placeholder=self.__check_cookie(),
valid_empty=True,
id="cookie",
),
Label(
_("网络代理"),
classes="params",
),
Input(
self.data["proxy"],
placeholder=_("不使用代理"),
valid_empty=True,
id="proxy",
),
Label(
_("请求数据超时限制,单位:秒"),
classes="params",
),
Input(
str(self.data["timeout"]),
placeholder="10",
type="integer",
id="timeout",
),
Label(
_("下载文件时,每次从服务器获取的数据块大小,单位:字节"),
classes="params",
),
Input(
str(self.data["chunk"]),
placeholder="1048576",
type="integer",
id="chunk",
),
Label(
_("请求数据失败时,重试的最大次数"),
classes="params",
),
Input(
str(self.data["max_retry"]),
placeholder="5",
type="integer",
id="max_retry",
),
Label(),
Container(
Checkbox(_("记录作品详细数据"), id="record_data", value=self.data["record_data"], ),
Checkbox(_("作品文件夹归档模式"), id="folder_mode", value=self.data["folder_mode"], ),
Checkbox(_("视频作品下载开关"), id="video_download", value=self.data["video_download"], ),
Checkbox(_("图文作品下载开关"), id="image_download", value=self.data["image_download"], ),
classes="horizontal-layout"),
Checkbox(
_("记录作品详细数据"),
id="record_data",
value=self.data["record_data"],
),
Checkbox(
_("作品文件夹归档模式"),
id="folder_mode",
value=self.data["folder_mode"],
),
Checkbox(
_("视频作品下载开关"),
id="video_download",
value=self.data["video_download"],
),
Checkbox(
_("图文作品下载开关"),
id="image_download",
value=self.data["image_download"],
),
classes="horizontal-layout",
),
Label(),
Container(
Checkbox(_("动图文件下载开关"), id="live_download", value=self.data["live_download"], ),
Checkbox(_("作品下载记录开关"), id="download_record", value=self.data["download_record"], ),
classes="horizontal-layout"),
Checkbox(
_("动图文件下载开关"),
id="live_download",
value=self.data["live_download"],
),
Checkbox(
_("作品下载记录开关"),
id="download_record",
value=self.data["download_record"],
),
classes="horizontal-layout",
),
Container(
Label(_("图片下载格式"), classes="params", ),
Label(_("程序语言"), classes="params", ),
Label(
_("图片下载格式"),
classes="params",
),
Label(
_("程序语言"),
classes="params",
),
classes="horizontal-layout",
),
Label(),
@@ -74,17 +176,27 @@ class Setting(Screen):
("PNG", "WEBP"),
value=self.data["image_format"].upper(),
allow_blank=False,
id="image_format"),
id="image_format",
),
Select.from_values(
["zh_CN", "en_US"],
value=self.data["language"],
allow_blank=False,
id="language", ),
classes="horizontal-layout"),
id="language",
),
classes="horizontal-layout",
),
Container(
Button(_("保存配置"), id="save", ),
Button(_("放弃更改"), id="abandon", ),
classes="settings_button", ),
Button(
_("保存配置"),
id="save",
),
Button(
_("放弃更改"),
id="abandon",
),
classes="settings_button",
),
)
yield Footer()
@@ -98,25 +210,27 @@ class Setting(Screen):
@on(Button.Pressed, "#save")
def save_settings(self):
self.dismiss({
"work_path": self.query_one("#work_path").value,
"folder_name": self.query_one("#folder_name").value,
"name_format": self.query_one("#name_format").value,
"user_agent": self.query_one("#user_agent").value,
"cookie": self.query_one("#cookie").value or self.data["cookie"],
"proxy": self.query_one("#proxy").value or None,
"timeout": int(self.query_one("#timeout").value),
"chunk": int(self.query_one("#chunk").value),
"max_retry": int(self.query_one("#max_retry").value),
"record_data": self.query_one("#record_data").value,
"image_format": self.query_one("#image_format").value,
"folder_mode": self.query_one("#folder_mode").value,
"language": self.query_one("#language").value,
"image_download": self.query_one("#image_download").value,
"video_download": self.query_one("#video_download").value,
"live_download": self.query_one("#live_download").value,
"download_record": self.query_one("#download_record").value,
})
self.dismiss(
{
"work_path": self.query_one("#work_path").value,
"folder_name": self.query_one("#folder_name").value,
"name_format": self.query_one("#name_format").value,
"user_agent": self.query_one("#user_agent").value,
"cookie": self.query_one("#cookie").value or self.data["cookie"],
"proxy": self.query_one("#proxy").value or None,
"timeout": int(self.query_one("#timeout").value),
"chunk": int(self.query_one("#chunk").value),
"max_retry": int(self.query_one("#max_retry").value),
"record_data": self.query_one("#record_data").value,
"image_format": self.query_one("#image_format").value,
"folder_mode": self.query_one("#folder_mode").value,
"language": self.query_one("#language").value,
"image_download": self.query_one("#image_download").value,
"video_download": self.query_one("#video_download").value,
"live_download": self.query_one("#live_download").value,
"download_record": self.query_one("#download_record").value,
}
)
@on(Button.Pressed, "#abandon")
def reset(self):

View File

@@ -15,7 +15,10 @@ __all__ = ["Update"]
class Update(ModalScreen):
def __init__(self, app: XHS, ):
def __init__(
self,
app: XHS,
):
super().__init__()
self.xhs = app
@@ -29,9 +32,16 @@ class Update(ModalScreen):
@work(exclusive=True)
async def check_update(self) -> None:
try:
url = await self.xhs.html.request_url(RELEASES, False, None, timeout=5, )
url = await self.xhs.html.request_url(
RELEASES,
False,
None,
timeout=5,
)
version = url.split("/")[-1]
match self.compare_versions(f"{XHS.VERSION_MAJOR}.{XHS.VERSION_MINOR}", version, XHS.VERSION_BETA):
match self.compare_versions(
f"{XHS.VERSION_MAJOR}.{XHS.VERSION_MINOR}", version, XHS.VERSION_BETA
):
case 4:
args = (
_("检测到新版本:{0}.{1}").format(
@@ -58,7 +68,10 @@ class Update(ModalScreen):
case _:
raise ValueError
except ValueError:
args = (_("检测新版本失败"), "error",)
args = (
_("检测新版本失败"),
"error",
)
self.dismiss(args)
def on_mount(self) -> None:
@@ -66,11 +79,10 @@ class Update(ModalScreen):
@staticmethod
def compare_versions(
current_version: str,
target_version: str,
is_development: bool) -> int:
current_major, current_minor = map(int, current_version.split('.'))
target_major, target_minor = map(int, target_version.split('.'))
current_version: str, target_version: str, is_development: bool
) -> int:
current_major, current_minor = map(int, current_version.split("."))
target_major, target_minor = map(int, target_version.split("."))
if target_major > current_major:
return 4