[feat] Add support for grouping in management scripts

This commit is contained in:
acite
2025-09-27 00:51:23 +08:00
parent 79add11c08
commit b2f91175f7
2 changed files with 63 additions and 35 deletions

View File

@@ -10,15 +10,8 @@
</component>
<component name="ChangeListManager">
<list default="true" id="bf317275-3039-49bb-a475-725a800a0cce" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/Abyss/Misc/StringClusterer.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources.local.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources/91acd9d8-5f8b-442f-9d50-17006d4e1ac7.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/dataSources/91acd9d8-5f8b-442f-9d50-17006d4e1ac7.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Abyss/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss.sln.DotSettings.user" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss.sln.DotSettings.user" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Controllers/Media/VideoController.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Components/Services/IndexService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Components/Services/IndexService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Model/Video.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Model/Video.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Program.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Abyss/Toolkits/update-video.py" beforeDir="false" afterPath="$PROJECT_DIR$/Abyss/Toolkits/update-video.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -119,7 +112,7 @@
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RunManager" selected=".NET Launch Settings Profile.Abyss: http">
<component name="RunManager" selected="Publish to folder.Publish Abyss to folder">
<configuration name="Publish Abyss to folder x86" type="DotNetFolderPublish" factoryName="Publish to folder">
<riderPublish configuration="Release" platform="Any CPU" produce_single_file="true" ready_to_run="true" self_contained="true" target_folder="/opt/security/https/server" target_framework="net9.0" uuid_high="3690631506471504162" uuid_low="-4858628519588143325">
<runtimes>
@@ -254,7 +247,8 @@
<workItem from="1758767744733" duration="12501000" />
<workItem from="1758794950242" duration="9381000" />
<workItem from="1758814543368" duration="642000" />
<workItem from="1758815224532" duration="297000" />
<workItem from="1758815224532" duration="430000" />
<workItem from="1758905391249" duration="31000" />
</task>
<servers />
</component>
@@ -304,19 +298,6 @@
<properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" />
<option name="timeStamp" value="3" />
</breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Abyss/Program.cs</url>
<line>31</line>
<properties documentPath="$PROJECT_DIR$/Abyss/Program.cs" containingFunctionPresentation="Method 'Main'">
<startOffsets>
<option value="1008" />
</startOffsets>
<endOffsets>
<option value="1062" />
</endOffsets>
</properties>
<option name="timeStamp" value="4" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>

View File

@@ -130,10 +130,12 @@ def find_video_in_dir(base_path):
return None
def update_summary(base_path, name_input=None, author_input=None):
def update_summary(base_path, name_input=None, author_input=None, group_input=None):
"""
Updates the summary.json file for a given path.
name_input and author_input are optional, used for the '-a' mode.
name_input, author_input, group_input are optional, used for the '-a' mode.
If group_input is provided, the written summary.json will include the "group" key.
If summary.json already contains a "group" and group_input is None, existing group is preserved.
"""
summary_path = base_path / "summary.json"
gallery_path = base_path / "gallery"
@@ -154,18 +156,26 @@ def update_summary(base_path, name_input=None, author_input=None):
"author": author_input if author_input is not None else "anonymous"
}
existing_data = {}
# Load existing summary if available
if summary_path.exists():
try:
with open(summary_path, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
# Update default with existing values
# Update default with existing values for known keys
for key in default_summary:
if key in existing_data:
default_summary[key] = existing_data[key]
except json.JSONDecodeError:
print("Warning: Invalid JSON in summary.json, using defaults")
# Handle group: preserve existing if no new group provided; otherwise set new group
if group_input is not None:
default_summary["group"] = group_input
else:
if isinstance(existing_data, dict) and "group" in existing_data:
default_summary["group"] = existing_data["group"]
# Update duration from video file if found
if video_path and video_path.exists():
default_summary["duration"] = get_video_duration(video_path)
@@ -206,7 +216,8 @@ def main():
print("Usage: python script.py <command> [arguments]")
print("Commands:")
print(" -u <path> Update the summary.json in the specified path.")
print(" -a <video_file> <path> Add a new video project in a new directory under the specified path. Optional -y to accept defaults.")
print(" -a <video_file> <path> Add a new video project in a new directory under the specified path.")
print(" Optional flags for -a: -y (accept defaults anywhere), -g <group name> (set group in summary.json).")
print(" -c <path> <time> Create a cover image from the video in the specified path at a given time percentage (0.0-1.0).")
sys.exit(1)
@@ -226,14 +237,33 @@ def main():
update_summary(base_path)
elif command == '-a':
# allow invocation with optional -y flag anywhere; expecting at least video and base path
params = [p for p in sys.argv[2:] if p != '-y']
if len(params) != 2:
print("Usage: python script.py -a <video_file> <path> (optional -y to accept defaults)")
# Parse tokens allowing -y (global) and -g <group> anywhere; remaining two positionals must be video_file and base_path
tokens = sys.argv[2:]
positional = []
group_name = None
i = 0
while i < len(tokens):
t = tokens[i]
if t == '-y':
i += 1
continue
if t == '-g':
if i + 1 >= len(tokens):
print("Usage: python script.py -a <video_file> <path> (optional -y to accept defaults, optional -g <group name>)")
sys.exit(1)
group_name = tokens[i + 1]
i += 2
continue
positional.append(t)
i += 1
if len(positional) != 2:
print("Usage: python script.py -a <video_file> <path> (optional -y to accept defaults, optional -g <group name>)")
sys.exit(1)
video_source_path = Path(params[0])
base_path = Path(params[1])
video_source_path = Path(positional[0])
base_path = Path(positional[1])
if not video_source_path.exists() or not video_source_path.is_file():
print(f"Error: Video file not found: {video_source_path}")
@@ -259,6 +289,23 @@ def main():
shutil.copy(video_source_path, video_dest_path)
print(f"Video copied to {video_dest_path}")
# === 新增:如果源视频同目录存在同名 .vtt 字幕,复制为 subtitle.vtt 到新项目目录 ===
subtitle_copied = False
candidate_vtt = video_source_path.with_suffix('.vtt')
candidate_vtt_upper = video_source_path.with_suffix('.VTT')
for candidate in (candidate_vtt, candidate_vtt_upper):
if candidate.exists() and candidate.is_file():
try:
shutil.copy2(candidate, new_project_path / 'subtitle.vtt')
print(f"Subtitle '{candidate.name}' copied to {new_project_path / 'subtitle.vtt'}")
subtitle_copied = True
except Exception as e:
print(f"Warning: failed to copy subtitle '{candidate}': {e}")
break
if not subtitle_copied:
print("No matching .vtt subtitle found next to source video; skipping subtitle copy.")
# === 新增结束 ===
# Auto-generate thumbnails
create_thumbnails(video_dest_path, gallery_path)
@@ -282,8 +329,8 @@ def main():
if not video_author:
video_author = "Anonymous"
# Update the summary with user input or default values
update_summary(new_project_path, name_input=video_name, author_input=video_author)
# Update the summary with user input or default values, include group_name if provided
update_summary(new_project_path, name_input=video_name, author_input=video_author, group_input=group_name)
elif command == '-c':
if len(sys.argv) != 4: