dfd
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
This commit is contained in:
140
API/folder.py
140
API/folder.py
@@ -16,7 +16,7 @@ import logging
|
||||
import subprocess
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Optional, Dict, Any, List, Tuple, Set
|
||||
|
||||
from SYS.utils import sha256_file
|
||||
@@ -159,10 +159,42 @@ class API_folder_store:
|
||||
self.db_path = self.library_root / self.DB_NAME
|
||||
self.connection: Optional[sqlite3.Connection] = None
|
||||
self._init_db()
|
||||
|
||||
def _normalize_input_path(self, file_path: Path) -> Path:
|
||||
p = Path(file_path).expanduser()
|
||||
if not p.is_absolute():
|
||||
p = self.library_root / p
|
||||
return p
|
||||
|
||||
def _to_db_file_path(self, file_path: Path) -> str:
|
||||
"""Convert an on-disk file path to a DB-stored relative path (POSIX separators)."""
|
||||
p = self._normalize_input_path(file_path)
|
||||
p_abs = p.resolve()
|
||||
root_abs = self.library_root.resolve()
|
||||
rel = p_abs.relative_to(root_abs)
|
||||
rel_posix = PurePosixPath(*rel.parts).as_posix()
|
||||
rel_posix = str(rel_posix or "").strip()
|
||||
if not rel_posix or rel_posix == ".":
|
||||
raise ValueError(f"Invalid relative path for DB storage: {file_path}")
|
||||
return rel_posix
|
||||
|
||||
def _from_db_file_path(self, db_file_path: str) -> Path:
|
||||
"""Convert a DB-stored relative path (POSIX separators) into an absolute path."""
|
||||
rel_str = str(db_file_path or "").strip()
|
||||
if not rel_str:
|
||||
raise ValueError("Missing DB file_path")
|
||||
rel_parts = PurePosixPath(rel_str).parts
|
||||
return self.library_root / Path(*rel_parts)
|
||||
|
||||
def _init_db(self) -> None:
|
||||
"""Initialize database connection and create tables if needed."""
|
||||
try:
|
||||
# Ensure the library root exists; sqlite cannot create parent dirs.
|
||||
try:
|
||||
self.library_root.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as exc:
|
||||
raise RuntimeError(f"Cannot create/open library root directory: {self.library_root}: {exc}") from exc
|
||||
|
||||
# Use check_same_thread=False to allow multi-threaded access
|
||||
# This is safe because we're not sharing connections across threads;
|
||||
# each thread will get its own cursor
|
||||
@@ -530,15 +562,29 @@ class API_folder_store:
|
||||
The file hash (primary key)
|
||||
"""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
logger.debug(f"[get_or_create_file_entry] Looking up: {str_path}")
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
db_path = self._to_db_file_path(abs_path)
|
||||
logger.debug(f"[get_or_create_file_entry] Looking up: {db_path}")
|
||||
|
||||
# If hash not provided, compute it
|
||||
if not file_hash:
|
||||
file_hash = sha256_file(file_path)
|
||||
file_hash = sha256_file(abs_path)
|
||||
logger.debug(f"[get_or_create_file_entry] Computed hash: {file_hash}")
|
||||
|
||||
cursor = self.connection.cursor()
|
||||
|
||||
# Prefer existing entry by path (file_path is UNIQUE in schema).
|
||||
cursor.execute("SELECT hash FROM files WHERE file_path = ?", (db_path,))
|
||||
row = cursor.fetchone()
|
||||
if row and row[0]:
|
||||
existing_hash = str(row[0])
|
||||
if existing_hash != file_hash:
|
||||
logger.debug(
|
||||
f"[get_or_create_file_entry] Found existing file_path with different hash: path={db_path} existing={existing_hash} computed={file_hash}"
|
||||
)
|
||||
else:
|
||||
logger.debug(f"[get_or_create_file_entry] Found existing file_path: {db_path} -> {existing_hash}")
|
||||
return existing_hash
|
||||
|
||||
# Check if file entry exists
|
||||
cursor.execute("SELECT hash FROM files WHERE hash = ?", (file_hash,))
|
||||
@@ -549,16 +595,26 @@ class API_folder_store:
|
||||
return file_hash
|
||||
|
||||
logger.debug(f"[get_or_create_file_entry] File entry not found, creating new one")
|
||||
stat = file_path.stat()
|
||||
cursor.execute("""
|
||||
INSERT INTO files (hash, file_path, file_modified)
|
||||
VALUES (?, ?, ?)
|
||||
""", (file_hash, str_path, stat.st_mtime))
|
||||
stat = abs_path.stat()
|
||||
try:
|
||||
cursor.execute("""
|
||||
INSERT INTO files (hash, file_path, file_modified)
|
||||
VALUES (?, ?, ?)
|
||||
""", (file_hash, db_path, stat.st_mtime))
|
||||
except sqlite3.IntegrityError:
|
||||
# Most likely: UNIQUE constraint on file_path. Re-fetch and return.
|
||||
cursor.execute("SELECT hash FROM files WHERE file_path = ?", (db_path,))
|
||||
row2 = cursor.fetchone()
|
||||
if row2 and row2[0]:
|
||||
existing_hash = str(row2[0])
|
||||
logger.debug(f"[get_or_create_file_entry] Recovered from UNIQUE(file_path): {db_path} -> {existing_hash}")
|
||||
return existing_hash
|
||||
raise
|
||||
|
||||
logger.debug(f"[get_or_create_file_entry] Created new file entry for hash: {file_hash}")
|
||||
|
||||
# Auto-create title tag
|
||||
filename_without_ext = file_path.stem
|
||||
filename_without_ext = abs_path.stem
|
||||
if filename_without_ext:
|
||||
# Normalize underscores to spaces for consistency
|
||||
title_value = filename_without_ext.replace("_", " ").strip()
|
||||
@@ -579,7 +635,8 @@ class API_folder_store:
|
||||
def get_file_hash(self, file_path: Path) -> Optional[str]:
|
||||
"""Get the file hash for a file path, or None if not found."""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
str_path = self._to_db_file_path(abs_path)
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("SELECT hash FROM files WHERE file_path = ?", (str_path,))
|
||||
row = cursor.fetchone()
|
||||
@@ -761,10 +818,11 @@ class API_folder_store:
|
||||
def save_metadata(self, file_path: Path, metadata: Dict[str, Any]) -> None:
|
||||
"""Save metadata for a file."""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
logger.debug(f"[save_metadata] Starting save for: {str_path}")
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
db_path = self._to_db_file_path(abs_path)
|
||||
logger.debug(f"[save_metadata] Starting save for: {db_path}")
|
||||
|
||||
file_hash = self.get_or_create_file_entry(file_path, metadata.get('hash'))
|
||||
file_hash = self.get_or_create_file_entry(abs_path, metadata.get('hash'))
|
||||
logger.debug(f"[save_metadata] Got/created file_hash: {file_hash}")
|
||||
|
||||
cursor = self.connection.cursor()
|
||||
@@ -815,10 +873,11 @@ class API_folder_store:
|
||||
def save_file_info(self, file_path: Path, metadata: Dict[str, Any], tags: List[str]) -> None:
|
||||
"""Save metadata and tags for a file in a single transaction."""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
logger.debug(f"[save_file_info] Starting save for: {str_path}")
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
db_path = self._to_db_file_path(abs_path)
|
||||
logger.debug(f"[save_file_info] Starting save for: {db_path}")
|
||||
|
||||
file_hash = self.get_or_create_file_entry(file_path, metadata.get('hash'))
|
||||
file_hash = self.get_or_create_file_entry(abs_path, metadata.get('hash'))
|
||||
|
||||
cursor = self.connection.cursor()
|
||||
|
||||
@@ -898,10 +957,11 @@ class API_folder_store:
|
||||
def save_tags(self, file_path: Path, tags: List[str]) -> None:
|
||||
"""Save tags for a file, replacing all existing tags."""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
logger.debug(f"[save_tags] Starting save for: {str_path}")
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
db_path = self._to_db_file_path(abs_path)
|
||||
logger.debug(f"[save_tags] Starting save for: {db_path}")
|
||||
|
||||
file_hash = self.get_or_create_file_entry(file_path)
|
||||
file_hash = self.get_or_create_file_entry(abs_path)
|
||||
logger.debug(f"[save_tags] Got/created file_hash: {file_hash}")
|
||||
|
||||
cursor = self.connection.cursor()
|
||||
@@ -923,7 +983,7 @@ class API_folder_store:
|
||||
""", (file_hash, existing_title[0]))
|
||||
logger.debug(f"[save_tags] Preserved existing title tag")
|
||||
elif not existing_title and not new_title_provided:
|
||||
filename_without_ext = file_path.stem
|
||||
filename_without_ext = abs_path.stem
|
||||
if filename_without_ext:
|
||||
# Normalize underscores to spaces for consistency
|
||||
title_value = filename_without_ext.replace("_", " ").strip()
|
||||
@@ -1325,7 +1385,16 @@ class API_folder_store:
|
||||
LIMIT ?
|
||||
""", (tag, limit))
|
||||
|
||||
return cursor.fetchall()
|
||||
rows = cursor.fetchall() or []
|
||||
results: List[tuple] = []
|
||||
for row in rows:
|
||||
try:
|
||||
file_hash = str(row[0])
|
||||
db_path = str(row[1])
|
||||
results.append((file_hash, str(self._from_db_file_path(db_path))))
|
||||
except Exception:
|
||||
continue
|
||||
return results
|
||||
except Exception as e:
|
||||
logger.error(f"Error searching by tag '{tag}': {e}", exc_info=True)
|
||||
return []
|
||||
@@ -1340,7 +1409,7 @@ class API_folder_store:
|
||||
""", (file_hash,))
|
||||
|
||||
row = cursor.fetchone()
|
||||
return Path(row[0]) if row else None
|
||||
return self._from_db_file_path(row[0]) if row else None
|
||||
except Exception as e:
|
||||
logger.error(f"Error searching by hash '{file_hash}': {e}", exc_info=True)
|
||||
return None
|
||||
@@ -1357,8 +1426,10 @@ class API_folder_store:
|
||||
def rename_file(self, old_path: Path, new_path: Path) -> None:
|
||||
"""Rename a file in the database, preserving all metadata."""
|
||||
try:
|
||||
str_old_path = str(old_path.resolve())
|
||||
str_new_path = str(new_path.resolve())
|
||||
abs_old = self._normalize_input_path(old_path)
|
||||
abs_new = self._normalize_input_path(new_path)
|
||||
str_old_path = self._to_db_file_path(abs_old)
|
||||
str_new_path = self._to_db_file_path(abs_new)
|
||||
cursor = self.connection.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
@@ -1380,7 +1451,11 @@ class API_folder_store:
|
||||
|
||||
removed_count = 0
|
||||
for file_hash, file_path in cursor.fetchall():
|
||||
if not Path(file_path).exists():
|
||||
try:
|
||||
abs_path = self._from_db_file_path(file_path)
|
||||
except Exception:
|
||||
abs_path = Path(file_path)
|
||||
if not abs_path.exists():
|
||||
cursor.execute("DELETE FROM files WHERE hash = ?", (file_hash,))
|
||||
removed_count += 1
|
||||
|
||||
@@ -1399,7 +1474,8 @@ class API_folder_store:
|
||||
deleted hash.
|
||||
"""
|
||||
try:
|
||||
str_path = str(file_path.resolve())
|
||||
abs_path = self._normalize_input_path(file_path)
|
||||
str_path = self._to_db_file_path(abs_path)
|
||||
cursor = self.connection.cursor()
|
||||
|
||||
# Get the hash first (for logging)
|
||||
@@ -2272,7 +2348,7 @@ class LocalLibraryInitializer:
|
||||
cursor = self.db.connection.cursor()
|
||||
cursor.execute(
|
||||
"UPDATE files SET file_path = ?, updated_at = CURRENT_TIMESTAMP WHERE hash = ?",
|
||||
(str(target_path.resolve()), file_hash),
|
||||
(self.db._to_db_file_path(target_path), file_hash),
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.debug(f"Failed to reset DB path to canonical file for {file_hash}: {exc}")
|
||||
@@ -2309,7 +2385,7 @@ class LocalLibraryInitializer:
|
||||
cursor = self.db.connection.cursor()
|
||||
cursor.execute(
|
||||
"UPDATE files SET file_path = ?, updated_at = CURRENT_TIMESTAMP WHERE hash = ?",
|
||||
(str(target_path.resolve()), file_hash),
|
||||
(self.db._to_db_file_path(target_path), file_hash),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -2371,7 +2447,11 @@ class LocalLibraryInitializer:
|
||||
|
||||
result = {}
|
||||
for file_hash, file_path in cursor.fetchall():
|
||||
normalized = str(Path(file_path).resolve()).lower()
|
||||
try:
|
||||
abs_path = self.db._from_db_file_path(file_path)
|
||||
except Exception:
|
||||
abs_path = Path(file_path)
|
||||
normalized = str(abs_path.resolve()).lower()
|
||||
result[normalized] = file_hash
|
||||
|
||||
return result
|
||||
|
||||
@@ -17,10 +17,11 @@ auto-window-resize=no
|
||||
ontop=yes
|
||||
|
||||
|
||||
vo=gpu-next # faster with large images
|
||||
image-display-duration=inf # don't stop displaying images after 5 second
|
||||
prefetch-playlist # load the next image before viewing it
|
||||
reset-on-next-file=video-zoom,panscan,video-unscaled,video-align-x,video-align-y,video-rotate # reset zoom, alignment and rotation between images
|
||||
# Avoid showing embedded cover art for audio-only files.
|
||||
audio-display=no
|
||||
|
||||
# gpu-next can be fragile on some Windows/D3D11 setups; prefer the stable VO.
|
||||
vo=gpu
|
||||
|
||||
# Show this after loading a new file. You can show text permanently instead by setting osd-msg1.
|
||||
osd-playing-msg=${!playlist-count==1:[${playlist-pos-1}/${playlist-count}] }${media-title} ${?width:${width}x${height}} ${?current-tracks/video/image==no:${?percent-pos==0:${duration}}${!percent-pos==0:${time-pos} / ${duration} (${percent-pos}%)}}
|
||||
@@ -44,6 +45,11 @@ auto-window-resize=no # preserve the window size when changing playlist entry
|
||||
profile-cond=get('current-tracks/video', {}).image or (not get('current-tracks/video') and get('user-data/mpv/image'))
|
||||
profile-restore=copy
|
||||
|
||||
# Stand-alone images.
|
||||
image-display-duration=inf # don't stop displaying images after 5 second
|
||||
prefetch-playlist # load the next image before viewing it
|
||||
reset-on-next-file=video-zoom,panscan,video-unscaled,video-align-x,video-align-y,video-rotate # reset zoom, alignment and rotation between images
|
||||
|
||||
d3d11-flip=no # enable background transparency if on d3d11/Windows
|
||||
video-recenter # recenter after zooming out
|
||||
input-preprocess-wheel=no # pan diagonally with a touchpad
|
||||
|
||||
@@ -195,7 +195,7 @@ class Folder(Store):
|
||||
try:
|
||||
cursor.execute(
|
||||
"UPDATE files SET file_path = ?, updated_at = CURRENT_TIMESTAMP WHERE hash = ?",
|
||||
(str(hash_path.resolve()), file_hash),
|
||||
(db._to_db_file_path(hash_path), file_hash),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -237,7 +237,7 @@ class Folder(Store):
|
||||
|
||||
for file_hash, file_path_str in files_without_title:
|
||||
try:
|
||||
file_path = Path(file_path_str)
|
||||
file_path = location_path / str(file_path_str)
|
||||
if file_path.exists():
|
||||
# Use the filename as the title
|
||||
title_tag = f"title:{file_path.name}"
|
||||
@@ -599,7 +599,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -723,7 +723,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -764,7 +764,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -793,7 +793,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -819,7 +819,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -848,7 +848,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -887,7 +887,7 @@ class Folder(Store):
|
||||
if fnmatch(value, pat):
|
||||
if ext_hashes is not None and file_hash not in ext_hashes:
|
||||
break
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if file_path.exists():
|
||||
if size_bytes is None:
|
||||
size_bytes = file_path.stat().st_size
|
||||
@@ -958,7 +958,7 @@ class Folder(Store):
|
||||
for file_hash, file_path_str, size_bytes, ext in rows:
|
||||
if not file_path_str:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if not file_path.exists():
|
||||
continue
|
||||
if size_bytes is None:
|
||||
@@ -984,7 +984,7 @@ class Folder(Store):
|
||||
if file_path_str:
|
||||
if ext_hashes is not None and file_hash not in ext_hashes:
|
||||
continue
|
||||
file_path = Path(file_path_str)
|
||||
file_path = search_dir / str(file_path_str)
|
||||
if file_path.exists():
|
||||
if size_bytes is None:
|
||||
size_bytes = file_path.stat().st_size
|
||||
@@ -1629,7 +1629,7 @@ class Folder(Store):
|
||||
if not p:
|
||||
continue
|
||||
try:
|
||||
if not Path(p).exists():
|
||||
if not (Path(self._location) / p).exists():
|
||||
continue
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
168
cmdnat/out_table.py
Normal file
168
cmdnat/out_table.py
Normal file
@@ -0,0 +1,168 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Sequence, Optional
|
||||
|
||||
from cmdlet._shared import Cmdlet, CmdletArg
|
||||
from SYS.logger import log
|
||||
import pipeline as ctx
|
||||
|
||||
|
||||
CMDLET = Cmdlet(
|
||||
name=".out-table",
|
||||
summary="Save the current result table to an SVG file.",
|
||||
usage='.out-table -path "C:\\Path\\To\\Dir"',
|
||||
arg=[
|
||||
CmdletArg(
|
||||
"path",
|
||||
type="string",
|
||||
description="Directory (or file path) to write the SVG to",
|
||||
required=True,
|
||||
),
|
||||
],
|
||||
detail=[
|
||||
"Exports the most recent table (overlay/stage/last) as an SVG using Rich.",
|
||||
"Default filename is derived from the table title (sanitized).",
|
||||
"Examples:",
|
||||
'search-store "ext:mp3" | .out-table -path "C:\\Users\\Admin\\Desktop"',
|
||||
'search-store "ext:mp3" | .out-table -path "C:\\Users\\Admin\\Desktop\\my-table.svg"',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
_WINDOWS_RESERVED_NAMES = {
|
||||
"con",
|
||||
"prn",
|
||||
"aux",
|
||||
"nul",
|
||||
*(f"com{i}" for i in range(1, 10)),
|
||||
*(f"lpt{i}" for i in range(1, 10)),
|
||||
}
|
||||
|
||||
|
||||
def _sanitize_filename_base(text: str) -> str:
|
||||
"""Sanitize a string for use as a Windows-friendly filename (no extension)."""
|
||||
s = str(text or "").strip()
|
||||
if not s:
|
||||
return "table"
|
||||
|
||||
# Replace characters illegal on Windows (and generally unsafe cross-platform).
|
||||
s = re.sub(r'[<>:"/\\|?*]', " ", s)
|
||||
|
||||
# Drop control characters.
|
||||
s = "".join(ch for ch in s if ch.isprintable())
|
||||
|
||||
# Collapse whitespace.
|
||||
s = " ".join(s.split()).strip()
|
||||
|
||||
# Windows disallows trailing space/dot.
|
||||
s = s.rstrip(" .")
|
||||
|
||||
if not s:
|
||||
s = "table"
|
||||
|
||||
# Avoid reserved device names.
|
||||
if s.lower() in _WINDOWS_RESERVED_NAMES:
|
||||
s = f"_{s}"
|
||||
|
||||
# Keep it reasonably short.
|
||||
if len(s) > 200:
|
||||
s = s[:200].rstrip(" .")
|
||||
|
||||
return s or "table"
|
||||
|
||||
|
||||
def _resolve_output_path(path_arg: str, *, table_title: str) -> Path:
|
||||
raw = str(path_arg or "").strip()
|
||||
if not raw:
|
||||
raise ValueError("-path is required")
|
||||
|
||||
# Treat trailing slash as directory intent even if it doesn't exist yet.
|
||||
ends_with_sep = raw.endswith((os.sep, os.altsep or ""))
|
||||
|
||||
target = Path(raw)
|
||||
|
||||
if target.exists() and target.is_dir():
|
||||
base = _sanitize_filename_base(table_title)
|
||||
return target / f"{base}.svg"
|
||||
|
||||
if ends_with_sep and not target.suffix:
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
base = _sanitize_filename_base(table_title)
|
||||
return target / f"{base}.svg"
|
||||
|
||||
# File path intent.
|
||||
if not target.suffix:
|
||||
return target.with_suffix(".svg")
|
||||
|
||||
if target.suffix.lower() != ".svg":
|
||||
return target.with_suffix(".svg")
|
||||
|
||||
return target
|
||||
|
||||
|
||||
def _get_active_table(piped_result: Any) -> Optional[Any]:
|
||||
# Prefer an explicit ResultTable passed through the pipe, but normally `.out-table`
|
||||
# is used after `@` which pipes item selections (not the table itself).
|
||||
if piped_result is not None and hasattr(piped_result, "__rich__"):
|
||||
# Avoid mistakenly treating a dict/list as a renderable.
|
||||
if piped_result.__class__.__name__ == "ResultTable":
|
||||
return piped_result
|
||||
|
||||
return (
|
||||
ctx.get_display_table()
|
||||
or ctx.get_current_stage_table()
|
||||
or ctx.get_last_result_table()
|
||||
)
|
||||
|
||||
|
||||
def _run(piped_result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
args_list = [str(a) for a in (args or [])]
|
||||
|
||||
# Simple flag parsing: `.out-table -path <value>`
|
||||
path_arg: Optional[str] = None
|
||||
i = 0
|
||||
while i < len(args_list):
|
||||
low = args_list[i].strip().lower()
|
||||
if low in {"-path", "--path"} and i + 1 < len(args_list):
|
||||
path_arg = args_list[i + 1]
|
||||
i += 2
|
||||
continue
|
||||
if not args_list[i].startswith("-") and path_arg is None:
|
||||
# Allow `.out-table <path>` as a convenience.
|
||||
path_arg = args_list[i]
|
||||
i += 1
|
||||
|
||||
if not path_arg:
|
||||
log("Missing required -path", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
table = _get_active_table(piped_result)
|
||||
if table is None:
|
||||
log("No table available to export", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
title = getattr(table, "title", None)
|
||||
title_text = str(title or "table")
|
||||
|
||||
try:
|
||||
out_path = _resolve_output_path(path_arg, table_title=title_text)
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
console = Console(record=True)
|
||||
console.print(table)
|
||||
console.save_svg(str(out_path))
|
||||
|
||||
log(f"Saved table SVG: {out_path}")
|
||||
return 0
|
||||
except Exception as exc:
|
||||
log(f"Failed to save table SVG: {type(exc).__name__}: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
CMDLET.exec = _run
|
||||
13
docs/cookies.md
Normal file
13
docs/cookies.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Obtain cookies.txt for youtube.com
|
||||
1. You need a google account, throwaway is fine
|
||||
2. You need webbrowser extension Get cookies.txt LOCALLY
|
||||
|
||||
Chrome based browser: [cookies.txt LOCALLY](https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)
|
||||
|
||||
Firefox based browser: [cookies.txt LOCALLY](https://addons.mozilla.org/en-US/firefox/addon/get-cookies-txt-locally/)
|
||||
|
||||
3. open incognito tab and sign into youtube with your account
|
||||
4. open extension and click on "export all cookies"
|
||||
5. with the cookies.txt file produced, place that in the project folder
|
||||
|
||||
restart the medios-macina app and verify status for cookies is FOUND
|
||||
111
docs/img/Available formats.svg
Normal file
111
docs/img/Available formats.svg
Normal file
@@ -0,0 +1,111 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 2092 391.59999999999997" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-1511995346-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-1511995346-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-1511995346-r1 { fill: #c5c8c6 }
|
||||
.terminal-1511995346-r2 { fill: #c5c8c6;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-1511995346-clip-terminal">
|
||||
<rect x="0" y="0" width="2073.0" height="340.59999999999997" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-0">
|
||||
<rect x="0" y="1.5" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-1">
|
||||
<rect x="0" y="25.9" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-2">
|
||||
<rect x="0" y="50.3" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-3">
|
||||
<rect x="0" y="74.7" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-4">
|
||||
<rect x="0" y="99.1" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-5">
|
||||
<rect x="0" y="123.5" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-6">
|
||||
<rect x="0" y="147.9" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-7">
|
||||
<rect x="0" y="172.3" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-8">
|
||||
<rect x="0" y="196.7" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-9">
|
||||
<rect x="0" y="221.1" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-10">
|
||||
<rect x="0" y="245.5" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-11">
|
||||
<rect x="0" y="269.9" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1511995346-line-12">
|
||||
<rect x="0" y="294.3" width="2074" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="2090" height="389.6" rx="8"/><text class="terminal-1511995346-title" fill="#c5c8c6" text-anchor="middle" x="1045" y="27">Rich</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-1511995346-clip-terminal)">
|
||||
|
||||
<g class="terminal-1511995346-matrix">
|
||||
<text class="terminal-1511995346-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-1511995346-line-0)">╭─</text><text class="terminal-1511995346-r1" x="24.4" y="20" textLength="2025.2" clip-path="url(#terminal-1511995346-line-0)">───────────────────────────────────────────────── Available formats for https://www.youtube.com/watch?v=_23dFb50Z2Y ──────────────────────────────────────────────────</text><text class="terminal-1511995346-r1" x="2049.6" y="20" textLength="24.4" clip-path="url(#terminal-1511995346-line-0)">─╮</text><text class="terminal-1511995346-r1" x="2074" y="20" textLength="12.2" clip-path="url(#terminal-1511995346-line-0)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-1)">│</text><text class="terminal-1511995346-r1" x="2061.8" y="44.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-1)">│</text><text class="terminal-1511995346-r1" x="2074" y="44.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-1)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-2)">│</text><text class="terminal-1511995346-r2" x="48.8" y="68.8" textLength="85.4" clip-path="url(#terminal-1511995346-line-2)">      #</text><text class="terminal-1511995346-r2" x="170.8" y="68.8" textLength="146.4" clip-path="url(#terminal-1511995346-line-2)">ID          </text><text class="terminal-1511995346-r2" x="353.8" y="68.8" textLength="390.4" clip-path="url(#terminal-1511995346-line-2)">RESOLUTION                      </text><text class="terminal-1511995346-r2" x="780.8" y="68.8" textLength="183" clip-path="url(#terminal-1511995346-line-2)">EXT            </text><text class="terminal-1511995346-r2" x="1000.4" y="68.8" textLength="207.4" clip-path="url(#terminal-1511995346-line-2)">SIZE             </text><text class="terminal-1511995346-r2" x="1244.4" y="68.8" textLength="414.8" clip-path="url(#terminal-1511995346-line-2)">VIDEO                             </text><text class="terminal-1511995346-r2" x="1695.8" y="68.8" textLength="329.4" clip-path="url(#terminal-1511995346-line-2)">AUDIO                      </text><text class="terminal-1511995346-r1" x="2061.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-2)">│</text><text class="terminal-1511995346-r1" x="2074" y="68.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-2)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-3)">│</text><text class="terminal-1511995346-r1" x="24.4" y="93.2" textLength="2025.2" clip-path="url(#terminal-1511995346-line-3)"> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </text><text class="terminal-1511995346-r1" x="2061.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-3)">│</text><text class="terminal-1511995346-r1" x="2074" y="93.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-3)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-4)">│</text><text class="terminal-1511995346-r1" x="48.8" y="117.6" textLength="85.4" clip-path="url(#terminal-1511995346-line-4)">      1</text><text class="terminal-1511995346-r1" x="170.8" y="117.6" textLength="146.4" clip-path="url(#terminal-1511995346-line-4)">140         </text><text class="terminal-1511995346-r1" x="353.8" y="117.6" textLength="390.4" clip-path="url(#terminal-1511995346-line-4)">audio only                      </text><text class="terminal-1511995346-r1" x="780.8" y="117.6" textLength="183" clip-path="url(#terminal-1511995346-line-4)">m4a            </text><text class="terminal-1511995346-r1" x="1000.4" y="117.6" textLength="207.4" clip-path="url(#terminal-1511995346-line-4)">0.4mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="117.6" textLength="414.8" clip-path="url(#terminal-1511995346-line-4)">none                              </text><text class="terminal-1511995346-r1" x="1695.8" y="117.6" textLength="329.4" clip-path="url(#terminal-1511995346-line-4)">mp4a.40.2                  </text><text class="terminal-1511995346-r1" x="2061.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-4)">│</text><text class="terminal-1511995346-r1" x="2074" y="117.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-4)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-1511995346-line-5)">│</text><text class="terminal-1511995346-r1" x="48.8" y="142" textLength="85.4" clip-path="url(#terminal-1511995346-line-5)">      2</text><text class="terminal-1511995346-r1" x="170.8" y="142" textLength="146.4" clip-path="url(#terminal-1511995346-line-5)">251         </text><text class="terminal-1511995346-r1" x="353.8" y="142" textLength="390.4" clip-path="url(#terminal-1511995346-line-5)">audio only                      </text><text class="terminal-1511995346-r1" x="780.8" y="142" textLength="183" clip-path="url(#terminal-1511995346-line-5)">webm           </text><text class="terminal-1511995346-r1" x="1000.4" y="142" textLength="207.4" clip-path="url(#terminal-1511995346-line-5)">0.4mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="142" textLength="414.8" clip-path="url(#terminal-1511995346-line-5)">none                              </text><text class="terminal-1511995346-r1" x="1695.8" y="142" textLength="329.4" clip-path="url(#terminal-1511995346-line-5)">opus                       </text><text class="terminal-1511995346-r1" x="2061.8" y="142" textLength="12.2" clip-path="url(#terminal-1511995346-line-5)">│</text><text class="terminal-1511995346-r1" x="2074" y="142" textLength="12.2" clip-path="url(#terminal-1511995346-line-5)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-6)">│</text><text class="terminal-1511995346-r1" x="48.8" y="166.4" textLength="85.4" clip-path="url(#terminal-1511995346-line-6)">      3</text><text class="terminal-1511995346-r1" x="170.8" y="166.4" textLength="146.4" clip-path="url(#terminal-1511995346-line-6)">91          </text><text class="terminal-1511995346-r1" x="353.8" y="166.4" textLength="390.4" clip-path="url(#terminal-1511995346-line-6)">256x144                         </text><text class="terminal-1511995346-r1" x="780.8" y="166.4" textLength="183" clip-path="url(#terminal-1511995346-line-6)">mp4            </text><text class="terminal-1511995346-r1" x="1244.4" y="166.4" textLength="414.8" clip-path="url(#terminal-1511995346-line-6)">avc1.4d400c                       </text><text class="terminal-1511995346-r1" x="1695.8" y="166.4" textLength="329.4" clip-path="url(#terminal-1511995346-line-6)">mp4a.40.5                  </text><text class="terminal-1511995346-r1" x="2061.8" y="166.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-6)">│</text><text class="terminal-1511995346-r1" x="2074" y="166.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-6)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-7)">│</text><text class="terminal-1511995346-r1" x="48.8" y="190.8" textLength="85.4" clip-path="url(#terminal-1511995346-line-7)">      4</text><text class="terminal-1511995346-r1" x="170.8" y="190.8" textLength="146.4" clip-path="url(#terminal-1511995346-line-7)">160         </text><text class="terminal-1511995346-r1" x="353.8" y="190.8" textLength="390.4" clip-path="url(#terminal-1511995346-line-7)">256x144                         </text><text class="terminal-1511995346-r1" x="780.8" y="190.8" textLength="183" clip-path="url(#terminal-1511995346-line-7)">mp4            </text><text class="terminal-1511995346-r1" x="1000.4" y="190.8" textLength="207.4" clip-path="url(#terminal-1511995346-line-7)">0.1mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="190.8" textLength="414.8" clip-path="url(#terminal-1511995346-line-7)">avc1.4d400c                       </text><text class="terminal-1511995346-r1" x="1695.8" y="190.8" textLength="329.4" clip-path="url(#terminal-1511995346-line-7)">none                       </text><text class="terminal-1511995346-r1" x="2061.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-7)">│</text><text class="terminal-1511995346-r1" x="2074" y="190.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-7)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-8)">│</text><text class="terminal-1511995346-r1" x="48.8" y="215.2" textLength="85.4" clip-path="url(#terminal-1511995346-line-8)">      5</text><text class="terminal-1511995346-r1" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-1511995346-line-8)">93          </text><text class="terminal-1511995346-r1" x="353.8" y="215.2" textLength="390.4" clip-path="url(#terminal-1511995346-line-8)">640x360                         </text><text class="terminal-1511995346-r1" x="780.8" y="215.2" textLength="183" clip-path="url(#terminal-1511995346-line-8)">mp4            </text><text class="terminal-1511995346-r1" x="1244.4" y="215.2" textLength="414.8" clip-path="url(#terminal-1511995346-line-8)">avc1.4d401e                       </text><text class="terminal-1511995346-r1" x="1695.8" y="215.2" textLength="329.4" clip-path="url(#terminal-1511995346-line-8)">mp4a.40.2                  </text><text class="terminal-1511995346-r1" x="2061.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-8)">│</text><text class="terminal-1511995346-r1" x="2074" y="215.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-8)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-9)">│</text><text class="terminal-1511995346-r1" x="48.8" y="239.6" textLength="85.4" clip-path="url(#terminal-1511995346-line-9)">      6</text><text class="terminal-1511995346-r1" x="170.8" y="239.6" textLength="146.4" clip-path="url(#terminal-1511995346-line-9)">134         </text><text class="terminal-1511995346-r1" x="353.8" y="239.6" textLength="390.4" clip-path="url(#terminal-1511995346-line-9)">640x360                         </text><text class="terminal-1511995346-r1" x="780.8" y="239.6" textLength="183" clip-path="url(#terminal-1511995346-line-9)">mp4            </text><text class="terminal-1511995346-r1" x="1000.4" y="239.6" textLength="207.4" clip-path="url(#terminal-1511995346-line-9)">0.6mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="239.6" textLength="414.8" clip-path="url(#terminal-1511995346-line-9)">avc1.4d401e                       </text><text class="terminal-1511995346-r1" x="1695.8" y="239.6" textLength="329.4" clip-path="url(#terminal-1511995346-line-9)">none                       </text><text class="terminal-1511995346-r1" x="2061.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-9)">│</text><text class="terminal-1511995346-r1" x="2074" y="239.6" textLength="12.2" clip-path="url(#terminal-1511995346-line-9)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="264" textLength="12.2" clip-path="url(#terminal-1511995346-line-10)">│</text><text class="terminal-1511995346-r1" x="48.8" y="264" textLength="85.4" clip-path="url(#terminal-1511995346-line-10)">      7</text><text class="terminal-1511995346-r1" x="170.8" y="264" textLength="146.4" clip-path="url(#terminal-1511995346-line-10)">18          </text><text class="terminal-1511995346-r1" x="353.8" y="264" textLength="390.4" clip-path="url(#terminal-1511995346-line-10)">640x360                         </text><text class="terminal-1511995346-r1" x="780.8" y="264" textLength="183" clip-path="url(#terminal-1511995346-line-10)">mp4            </text><text class="terminal-1511995346-r1" x="1000.4" y="264" textLength="207.4" clip-path="url(#terminal-1511995346-line-10)">0.8mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="264" textLength="414.8" clip-path="url(#terminal-1511995346-line-10)">avc1.42001e                       </text><text class="terminal-1511995346-r1" x="1695.8" y="264" textLength="329.4" clip-path="url(#terminal-1511995346-line-10)">mp4a.40.2                  </text><text class="terminal-1511995346-r1" x="2061.8" y="264" textLength="12.2" clip-path="url(#terminal-1511995346-line-10)">│</text><text class="terminal-1511995346-r1" x="2074" y="264" textLength="12.2" clip-path="url(#terminal-1511995346-line-10)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-11)">│</text><text class="terminal-1511995346-r1" x="48.8" y="288.4" textLength="85.4" clip-path="url(#terminal-1511995346-line-11)">      8</text><text class="terminal-1511995346-r1" x="170.8" y="288.4" textLength="146.4" clip-path="url(#terminal-1511995346-line-11)">243         </text><text class="terminal-1511995346-r1" x="353.8" y="288.4" textLength="390.4" clip-path="url(#terminal-1511995346-line-11)">640x360                         </text><text class="terminal-1511995346-r1" x="780.8" y="288.4" textLength="183" clip-path="url(#terminal-1511995346-line-11)">webm           </text><text class="terminal-1511995346-r1" x="1000.4" y="288.4" textLength="207.4" clip-path="url(#terminal-1511995346-line-11)">0.6mb            </text><text class="terminal-1511995346-r1" x="1244.4" y="288.4" textLength="414.8" clip-path="url(#terminal-1511995346-line-11)">vp9                               </text><text class="terminal-1511995346-r1" x="1695.8" y="288.4" textLength="329.4" clip-path="url(#terminal-1511995346-line-11)">none                       </text><text class="terminal-1511995346-r1" x="2061.8" y="288.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-11)">│</text><text class="terminal-1511995346-r1" x="2074" y="288.4" textLength="12.2" clip-path="url(#terminal-1511995346-line-11)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-12)">│</text><text class="terminal-1511995346-r1" x="2061.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-12)">│</text><text class="terminal-1511995346-r1" x="2074" y="312.8" textLength="12.2" clip-path="url(#terminal-1511995346-line-12)">
|
||||
</text><text class="terminal-1511995346-r1" x="0" y="337.2" textLength="2074" clip-path="url(#terminal-1511995346-line-13)">╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1511995346-r1" x="2074" y="337.2" textLength="12.2" clip-path="url(#terminal-1511995346-line-13)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
83
docs/img/add-file.svg
Normal file
83
docs/img/add-file.svg
Normal file
@@ -0,0 +1,83 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 2556 220.79999999999998" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-4105504262-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-4105504262-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-4105504262-r1 { fill: #c5c8c6 }
|
||||
.terminal-4105504262-r2 { fill: #c5c8c6;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-4105504262-clip-terminal">
|
||||
<rect x="0" y="0" width="2536.6" height="169.79999999999998" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-0">
|
||||
<rect x="0" y="1.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-1">
|
||||
<rect x="0" y="25.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-2">
|
||||
<rect x="0" y="50.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-3">
|
||||
<rect x="0" y="74.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-4">
|
||||
<rect x="0" y="99.1" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4105504262-line-5">
|
||||
<rect x="0" y="123.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="2554" height="218.8" rx="8"/><text class="terminal-4105504262-title" fill="#c5c8c6" text-anchor="middle" x="1277" y="27">Rich</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-4105504262-clip-terminal)">
|
||||
|
||||
<g class="terminal-4105504262-matrix">
|
||||
<text class="terminal-4105504262-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-4105504262-line-0)">╭─</text><text class="terminal-4105504262-r1" x="24.4" y="20" textLength="2488.8" clip-path="url(#terminal-4105504262-line-0)">───────────────────────────────────────────────────────────────────────────────────────── add-file -store tutorial ─────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-4105504262-r1" x="2513.2" y="20" textLength="24.4" clip-path="url(#terminal-4105504262-line-0)">─╮</text><text class="terminal-4105504262-r1" x="2537.6" y="20" textLength="12.2" clip-path="url(#terminal-4105504262-line-0)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-4105504262-line-1)">│</text><text class="terminal-4105504262-r1" x="2525.4" y="44.4" textLength="12.2" clip-path="url(#terminal-4105504262-line-1)">│</text><text class="terminal-4105504262-r1" x="2537.6" y="44.4" textLength="12.2" clip-path="url(#terminal-4105504262-line-1)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-4105504262-line-2)">│</text><text class="terminal-4105504262-r2" x="48.8" y="68.8" textLength="122" clip-path="url(#terminal-4105504262-line-2)">         #</text><text class="terminal-4105504262-r2" x="207.4" y="68.8" textLength="1281" clip-path="url(#terminal-4105504262-line-2)">TITLE                                                                                                    </text><text class="terminal-4105504262-r2" x="1525" y="68.8" textLength="439.2" clip-path="url(#terminal-4105504262-line-2)">STORE                               </text><text class="terminal-4105504262-r2" x="2000.8" y="68.8" textLength="256.2" clip-path="url(#terminal-4105504262-line-2)">SIZE                 </text><text class="terminal-4105504262-r2" x="2293.6" y="68.8" textLength="195.2" clip-path="url(#terminal-4105504262-line-2)">EXT             </text><text class="terminal-4105504262-r1" x="2525.4" y="68.8" textLength="12.2" clip-path="url(#terminal-4105504262-line-2)">│</text><text class="terminal-4105504262-r1" x="2537.6" y="68.8" textLength="12.2" clip-path="url(#terminal-4105504262-line-2)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-4105504262-line-3)">│</text><text class="terminal-4105504262-r1" x="24.4" y="93.2" textLength="2488.8" clip-path="url(#terminal-4105504262-line-3)"> ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </text><text class="terminal-4105504262-r1" x="2525.4" y="93.2" textLength="12.2" clip-path="url(#terminal-4105504262-line-3)">│</text><text class="terminal-4105504262-r1" x="2537.6" y="93.2" textLength="12.2" clip-path="url(#terminal-4105504262-line-3)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-4105504262-line-4)">│</text><text class="terminal-4105504262-r1" x="48.8" y="117.6" textLength="122" clip-path="url(#terminal-4105504262-line-4)">         1</text><text class="terminal-4105504262-r1" x="207.4" y="117.6" textLength="1281" clip-path="url(#terminal-4105504262-line-4)">terry davis - command line                                                                               </text><text class="terminal-4105504262-r1" x="1525" y="117.6" textLength="439.2" clip-path="url(#terminal-4105504262-line-4)">tutorial                            </text><text class="terminal-4105504262-r1" x="2000.8" y="117.6" textLength="256.2" clip-path="url(#terminal-4105504262-line-4)">1 mb                 </text><text class="terminal-4105504262-r1" x="2293.6" y="117.6" textLength="195.2" clip-path="url(#terminal-4105504262-line-4)">mkv             </text><text class="terminal-4105504262-r1" x="2525.4" y="117.6" textLength="12.2" clip-path="url(#terminal-4105504262-line-4)">│</text><text class="terminal-4105504262-r1" x="2537.6" y="117.6" textLength="12.2" clip-path="url(#terminal-4105504262-line-4)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-4105504262-line-5)">│</text><text class="terminal-4105504262-r1" x="2525.4" y="142" textLength="12.2" clip-path="url(#terminal-4105504262-line-5)">│</text><text class="terminal-4105504262-r1" x="2537.6" y="142" textLength="12.2" clip-path="url(#terminal-4105504262-line-5)">
|
||||
</text><text class="terminal-4105504262-r1" x="0" y="166.4" textLength="2537.6" clip-path="url(#terminal-4105504262-line-6)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-4105504262-r1" x="2537.6" y="166.4" textLength="12.2" clip-path="url(#terminal-4105504262-line-6)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
107
docs/img/add-tag.svg
Normal file
107
docs/img/add-tag.svg
Normal file
@@ -0,0 +1,107 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 2556 367.2" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-2184702832-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-2184702832-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-2184702832-r1 { fill: #c5c8c6 }
|
||||
.terminal-2184702832-r2 { fill: #c5c8c6;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-2184702832-clip-terminal">
|
||||
<rect x="0" y="0" width="2536.6" height="316.2" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-0">
|
||||
<rect x="0" y="1.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-1">
|
||||
<rect x="0" y="25.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-2">
|
||||
<rect x="0" y="50.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-3">
|
||||
<rect x="0" y="74.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-4">
|
||||
<rect x="0" y="99.1" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-5">
|
||||
<rect x="0" y="123.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-6">
|
||||
<rect x="0" y="147.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-7">
|
||||
<rect x="0" y="172.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-8">
|
||||
<rect x="0" y="196.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-9">
|
||||
<rect x="0" y="221.1" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-10">
|
||||
<rect x="0" y="245.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-2184702832-line-11">
|
||||
<rect x="0" y="269.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="2554" height="365.2" rx="8"/><text class="terminal-2184702832-title" fill="#c5c8c6" text-anchor="middle" x="1277" y="27">Rich</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-2184702832-clip-terminal)">
|
||||
|
||||
<g class="terminal-2184702832-matrix">
|
||||
<text class="terminal-2184702832-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-2184702832-line-0)">╭─</text><text class="terminal-2184702832-r1" x="24.4" y="20" textLength="2488.8" clip-path="url(#terminal-2184702832-line-0)">───────────────────────────────────────────────────────────────────────────────────── tag: terry davis - command line ──────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-2184702832-r1" x="2513.2" y="20" textLength="24.4" clip-path="url(#terminal-2184702832-line-0)">─╮</text><text class="terminal-2184702832-r1" x="2537.6" y="20" textLength="12.2" clip-path="url(#terminal-2184702832-line-0)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-1)">│</text><text class="terminal-2184702832-r1" x="2525.4" y="44.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-1)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="44.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-1)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-2)">│</text><text class="terminal-2184702832-r2" x="48.8" y="68.8" textLength="183" clip-path="url(#terminal-2184702832-line-2)">              #</text><text class="terminal-2184702832-r2" x="268.4" y="68.8" textLength="2220.4" clip-path="url(#terminal-2184702832-line-2)">TAG                                                                                                                                                                                   </text><text class="terminal-2184702832-r1" x="2525.4" y="68.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-2)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="68.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-2)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-3)">│</text><text class="terminal-2184702832-r1" x="24.4" y="93.2" textLength="2488.8" clip-path="url(#terminal-2184702832-line-3)"> ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </text><text class="terminal-2184702832-r1" x="2525.4" y="93.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-3)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="93.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-3)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-4)">│</text><text class="terminal-2184702832-r1" x="48.8" y="117.6" textLength="183" clip-path="url(#terminal-2184702832-line-4)">              1</text><text class="terminal-2184702832-r1" x="268.4" y="117.6" textLength="2220.4" clip-path="url(#terminal-2184702832-line-4)">channel:archeroflusitania                                                                                                                                                             </text><text class="terminal-2184702832-r1" x="2525.4" y="117.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-4)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="117.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-4)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-2184702832-line-5)">│</text><text class="terminal-2184702832-r1" x="48.8" y="142" textLength="183" clip-path="url(#terminal-2184702832-line-5)">              2</text><text class="terminal-2184702832-r1" x="268.4" y="142" textLength="2220.4" clip-path="url(#terminal-2184702832-line-5)">cli                                                                                                                                                                                   </text><text class="terminal-2184702832-r1" x="2525.4" y="142" textLength="12.2" clip-path="url(#terminal-2184702832-line-5)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="142" textLength="12.2" clip-path="url(#terminal-2184702832-line-5)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-6)">│</text><text class="terminal-2184702832-r1" x="48.8" y="166.4" textLength="183" clip-path="url(#terminal-2184702832-line-6)">              3</text><text class="terminal-2184702832-r1" x="268.4" y="166.4" textLength="2220.4" clip-path="url(#terminal-2184702832-line-6)">creator:archeroflusitania                                                                                                                                                             </text><text class="terminal-2184702832-r1" x="2525.4" y="166.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-6)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="166.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-6)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-7)">│</text><text class="terminal-2184702832-r1" x="48.8" y="190.8" textLength="183" clip-path="url(#terminal-2184702832-line-7)">              4</text><text class="terminal-2184702832-r1" x="268.4" y="190.8" textLength="2220.4" clip-path="url(#terminal-2184702832-line-7)">desktop                                                                                                                                                                               </text><text class="terminal-2184702832-r1" x="2525.4" y="190.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-7)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="190.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-7)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-8)">│</text><text class="terminal-2184702832-r1" x="48.8" y="215.2" textLength="183" clip-path="url(#terminal-2184702832-line-8)">              5</text><text class="terminal-2184702832-r1" x="268.4" y="215.2" textLength="2220.4" clip-path="url(#terminal-2184702832-line-8)">title:terry davis - command line                                                                                                                                                      </text><text class="terminal-2184702832-r1" x="2525.4" y="215.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-8)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="215.2" textLength="12.2" clip-path="url(#terminal-2184702832-line-8)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-9)">│</text><text class="terminal-2184702832-r1" x="48.8" y="239.6" textLength="183" clip-path="url(#terminal-2184702832-line-9)">              6</text><text class="terminal-2184702832-r1" x="268.4" y="239.6" textLength="2220.4" clip-path="url(#terminal-2184702832-line-9)">ubuntu                                                                                                                                                                                </text><text class="terminal-2184702832-r1" x="2525.4" y="239.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-9)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="239.6" textLength="12.2" clip-path="url(#terminal-2184702832-line-9)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="264" textLength="12.2" clip-path="url(#terminal-2184702832-line-10)">│</text><text class="terminal-2184702832-r1" x="48.8" y="264" textLength="183" clip-path="url(#terminal-2184702832-line-10)">              7</text><text class="terminal-2184702832-r1" x="268.4" y="264" textLength="2220.4" clip-path="url(#terminal-2184702832-line-10)">upload_date:20250728                                                                                                                                                                  </text><text class="terminal-2184702832-r1" x="2525.4" y="264" textLength="12.2" clip-path="url(#terminal-2184702832-line-10)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="264" textLength="12.2" clip-path="url(#terminal-2184702832-line-10)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-11)">│</text><text class="terminal-2184702832-r1" x="2525.4" y="288.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-11)">│</text><text class="terminal-2184702832-r1" x="2537.6" y="288.4" textLength="12.2" clip-path="url(#terminal-2184702832-line-11)">
|
||||
</text><text class="terminal-2184702832-r1" x="0" y="312.8" textLength="2537.6" clip-path="url(#terminal-2184702832-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-2184702832-r1" x="2537.6" y="312.8" textLength="12.2" clip-path="url(#terminal-2184702832-line-12)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 21 KiB |
95
docs/img/get-tag.svg
Normal file
95
docs/img/get-tag.svg
Normal file
@@ -0,0 +1,95 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 2556 294.0" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-4170162618-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-4170162618-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-4170162618-r1 { fill: #c5c8c6 }
|
||||
.terminal-4170162618-r2 { fill: #c5c8c6;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-4170162618-clip-terminal">
|
||||
<rect x="0" y="0" width="2536.6" height="243.0" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-0">
|
||||
<rect x="0" y="1.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-1">
|
||||
<rect x="0" y="25.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-2">
|
||||
<rect x="0" y="50.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-3">
|
||||
<rect x="0" y="74.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-4">
|
||||
<rect x="0" y="99.1" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-5">
|
||||
<rect x="0" y="123.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-6">
|
||||
<rect x="0" y="147.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-7">
|
||||
<rect x="0" y="172.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-4170162618-line-8">
|
||||
<rect x="0" y="196.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="2554" height="292" rx="8"/><text class="terminal-4170162618-title" fill="#c5c8c6" text-anchor="middle" x="1277" y="27">Rich</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-4170162618-clip-terminal)">
|
||||
|
||||
<g class="terminal-4170162618-matrix">
|
||||
<text class="terminal-4170162618-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-4170162618-line-0)">╭─</text><text class="terminal-4170162618-r1" x="24.4" y="20" textLength="2488.8" clip-path="url(#terminal-4170162618-line-0)">───────────────────────────────────────────────────────────────────────────────────── tag: terry davis - command line ──────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-4170162618-r1" x="2513.2" y="20" textLength="24.4" clip-path="url(#terminal-4170162618-line-0)">─╮</text><text class="terminal-4170162618-r1" x="2537.6" y="20" textLength="12.2" clip-path="url(#terminal-4170162618-line-0)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-1)">│</text><text class="terminal-4170162618-r1" x="2525.4" y="44.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-1)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="44.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-1)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-2)">│</text><text class="terminal-4170162618-r2" x="48.8" y="68.8" textLength="183" clip-path="url(#terminal-4170162618-line-2)">              #</text><text class="terminal-4170162618-r2" x="268.4" y="68.8" textLength="2220.4" clip-path="url(#terminal-4170162618-line-2)">TAG                                                                                                                                                                                   </text><text class="terminal-4170162618-r1" x="2525.4" y="68.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-2)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="68.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-2)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-3)">│</text><text class="terminal-4170162618-r1" x="24.4" y="93.2" textLength="2488.8" clip-path="url(#terminal-4170162618-line-3)"> ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </text><text class="terminal-4170162618-r1" x="2525.4" y="93.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-3)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="93.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-3)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-4170162618-line-4)">│</text><text class="terminal-4170162618-r1" x="48.8" y="117.6" textLength="183" clip-path="url(#terminal-4170162618-line-4)">              1</text><text class="terminal-4170162618-r1" x="268.4" y="117.6" textLength="2220.4" clip-path="url(#terminal-4170162618-line-4)">channel:archeroflusitania                                                                                                                                                             </text><text class="terminal-4170162618-r1" x="2525.4" y="117.6" textLength="12.2" clip-path="url(#terminal-4170162618-line-4)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="117.6" textLength="12.2" clip-path="url(#terminal-4170162618-line-4)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-4170162618-line-5)">│</text><text class="terminal-4170162618-r1" x="48.8" y="142" textLength="183" clip-path="url(#terminal-4170162618-line-5)">              2</text><text class="terminal-4170162618-r1" x="268.4" y="142" textLength="2220.4" clip-path="url(#terminal-4170162618-line-5)">creator:archeroflusitania                                                                                                                                                             </text><text class="terminal-4170162618-r1" x="2525.4" y="142" textLength="12.2" clip-path="url(#terminal-4170162618-line-5)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="142" textLength="12.2" clip-path="url(#terminal-4170162618-line-5)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-6)">│</text><text class="terminal-4170162618-r1" x="48.8" y="166.4" textLength="183" clip-path="url(#terminal-4170162618-line-6)">              3</text><text class="terminal-4170162618-r1" x="268.4" y="166.4" textLength="2220.4" clip-path="url(#terminal-4170162618-line-6)">title:terry davis - command line                                                                                                                                                      </text><text class="terminal-4170162618-r1" x="2525.4" y="166.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-6)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="166.4" textLength="12.2" clip-path="url(#terminal-4170162618-line-6)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-7)">│</text><text class="terminal-4170162618-r1" x="48.8" y="190.8" textLength="183" clip-path="url(#terminal-4170162618-line-7)">              4</text><text class="terminal-4170162618-r1" x="268.4" y="190.8" textLength="2220.4" clip-path="url(#terminal-4170162618-line-7)">upload_date:20250728                                                                                                                                                                  </text><text class="terminal-4170162618-r1" x="2525.4" y="190.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-7)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="190.8" textLength="12.2" clip-path="url(#terminal-4170162618-line-7)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-8)">│</text><text class="terminal-4170162618-r1" x="2525.4" y="215.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-8)">│</text><text class="terminal-4170162618-r1" x="2537.6" y="215.2" textLength="12.2" clip-path="url(#terminal-4170162618-line-8)">
|
||||
</text><text class="terminal-4170162618-r1" x="0" y="239.6" textLength="2537.6" clip-path="url(#terminal-4170162618-line-9)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-4170162618-r1" x="2537.6" y="239.6" textLength="12.2" clip-path="url(#terminal-4170162618-line-9)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
83
docs/img/search-store.svg
Normal file
83
docs/img/search-store.svg
Normal file
@@ -0,0 +1,83 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 2556 220.79999999999998" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-1147275963-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-1147275963-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-1147275963-r1 { fill: #c5c8c6 }
|
||||
.terminal-1147275963-r2 { fill: #c5c8c6;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-1147275963-clip-terminal">
|
||||
<rect x="0" y="0" width="2536.6" height="169.79999999999998" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-0">
|
||||
<rect x="0" y="1.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-1">
|
||||
<rect x="0" y="25.9" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-2">
|
||||
<rect x="0" y="50.3" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-3">
|
||||
<rect x="0" y="74.7" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-4">
|
||||
<rect x="0" y="99.1" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1147275963-line-5">
|
||||
<rect x="0" y="123.5" width="2537.6" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="2554" height="218.8" rx="8"/><text class="terminal-1147275963-title" fill="#c5c8c6" text-anchor="middle" x="1277" y="27">Rich</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-1147275963-clip-terminal)">
|
||||
|
||||
<g class="terminal-1147275963-matrix">
|
||||
<text class="terminal-1147275963-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-1147275963-line-0)">╭─</text><text class="terminal-1147275963-r1" x="24.4" y="20" textLength="2488.8" clip-path="url(#terminal-1147275963-line-0)">────────────────────────────────────────────────────────────────────────────────────────── search-store "ubuntu" ───────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-1147275963-r1" x="2513.2" y="20" textLength="24.4" clip-path="url(#terminal-1147275963-line-0)">─╮</text><text class="terminal-1147275963-r1" x="2537.6" y="20" textLength="12.2" clip-path="url(#terminal-1147275963-line-0)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-1147275963-line-1)">│</text><text class="terminal-1147275963-r1" x="2525.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1147275963-line-1)">│</text><text class="terminal-1147275963-r1" x="2537.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1147275963-line-1)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1147275963-line-2)">│</text><text class="terminal-1147275963-r2" x="48.8" y="68.8" textLength="122" clip-path="url(#terminal-1147275963-line-2)">         #</text><text class="terminal-1147275963-r2" x="207.4" y="68.8" textLength="1281" clip-path="url(#terminal-1147275963-line-2)">TITLE                                                                                                    </text><text class="terminal-1147275963-r2" x="1525" y="68.8" textLength="439.2" clip-path="url(#terminal-1147275963-line-2)">STORE                               </text><text class="terminal-1147275963-r2" x="2000.8" y="68.8" textLength="256.2" clip-path="url(#terminal-1147275963-line-2)">SIZE                 </text><text class="terminal-1147275963-r2" x="2293.6" y="68.8" textLength="195.2" clip-path="url(#terminal-1147275963-line-2)">EXT             </text><text class="terminal-1147275963-r1" x="2525.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1147275963-line-2)">│</text><text class="terminal-1147275963-r1" x="2537.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1147275963-line-2)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-1147275963-line-3)">│</text><text class="terminal-1147275963-r1" x="24.4" y="93.2" textLength="2488.8" clip-path="url(#terminal-1147275963-line-3)"> ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </text><text class="terminal-1147275963-r1" x="2525.4" y="93.2" textLength="12.2" clip-path="url(#terminal-1147275963-line-3)">│</text><text class="terminal-1147275963-r1" x="2537.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1147275963-line-3)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-1147275963-line-4)">│</text><text class="terminal-1147275963-r1" x="48.8" y="117.6" textLength="122" clip-path="url(#terminal-1147275963-line-4)">         1</text><text class="terminal-1147275963-r1" x="207.4" y="117.6" textLength="1281" clip-path="url(#terminal-1147275963-line-4)">terry davis - command line                                                                               </text><text class="terminal-1147275963-r1" x="1525" y="117.6" textLength="439.2" clip-path="url(#terminal-1147275963-line-4)">tutorial                            </text><text class="terminal-1147275963-r1" x="2000.8" y="117.6" textLength="256.2" clip-path="url(#terminal-1147275963-line-4)">1 mb                 </text><text class="terminal-1147275963-r1" x="2293.6" y="117.6" textLength="195.2" clip-path="url(#terminal-1147275963-line-4)">mkv             </text><text class="terminal-1147275963-r1" x="2525.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1147275963-line-4)">│</text><text class="terminal-1147275963-r1" x="2537.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1147275963-line-4)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-1147275963-line-5)">│</text><text class="terminal-1147275963-r1" x="2525.4" y="142" textLength="12.2" clip-path="url(#terminal-1147275963-line-5)">│</text><text class="terminal-1147275963-r1" x="2537.6" y="142" textLength="12.2" clip-path="url(#terminal-1147275963-line-5)">
|
||||
</text><text class="terminal-1147275963-r1" x="0" y="166.4" textLength="2537.6" clip-path="url(#terminal-1147275963-line-6)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1147275963-r1" x="2537.6" y="166.4" textLength="12.2" clip-path="url(#terminal-1147275963-line-6)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
76
docs/tutorial.md
Normal file
76
docs/tutorial.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# set up config.conf
|
||||
the config file is meant to be modular, you only need to put in what you want. technically you do not need a file store, but you will miss out on a bunch features. For this tutorial we are going to make an example folderstore. Add the below to your config.conf, pick a path for you that is a blank folder non-system folder.
|
||||
|
||||
|
||||
<figure>
|
||||
<figcaption>config.conf</figcaption>
|
||||
<pre><code class="language-powershell">[store=folder]
|
||||
name="tutorial"
|
||||
path="C:\Users\Admin\Downloads\tutorial"
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||
|
||||
after your done save the file and restart the cli.py
|
||||
|
||||
# Downloading from youtube
|
||||
### cookies.txt required - [cookies.txt guide](cookies.md)
|
||||
start up the cli and enter this at prompt, you can copy and paste
|
||||
|
||||
<figure>
|
||||
<figcaption><🜂🜄|🜁🜃></figcaption>
|
||||
<pre><code class="language-powershell">download-media "https://www.youtube.com/watch?v=_23dFb50Z2Y" | add-file -store tutorial
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||

|
||||
this shows the available formats you can download, the audio is audio only, and the video will automatically merge audio so you only need to pick the video if you want video and audio. it is ordered best quality at the lowest/highest number down.
|
||||
|
||||
the # column is how you select what you want to pick, run this next
|
||||
|
||||
<figure>
|
||||
<figcaption><🜂🜄|🜁🜃></figcaption>
|
||||
<pre><code class="language-powershell">@8
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||

|
||||
|
||||
files inside of stores are renamed as their hash, you will only be able to find your file by searching for it, the title: tag acts as a psuedo filename, if you search "terry" then the file will be brought up, if you search "archeroflusitania" the file will not come up, you need to prepend the namespace first, "channel:archeroflusitania"; you can also use wild card "channel:arch*" and that will pull it up. lets see what tags the file has, run this.
|
||||
|
||||
<figure>
|
||||
<figcaption><🜂🜄|🜁🜃></figcaption>
|
||||
<pre><code class="language-powershell">@1 | get-tag
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||

|
||||
these tags are scraped from the youtube video using yt-dlp, they are stored in your store's database, this is how you will actually find your files so make sure it has either a title: tag that you can look up or you add your custom tags
|
||||
now lets add more tags, run this
|
||||
|
||||
<figure>
|
||||
<figcaption><🜂🜄|🜁🜃></figcaption>
|
||||
<pre><code class="language-powershell">@ | add-tag "cli,ubuntu,desktop"
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||

|
||||
|
||||
we added freeform tags, freeform tags are tags that dont have colons in them, these tags show up in searches without any special prepends. run the following below to search for our new tags added to the file.
|
||||
|
||||
<figure>
|
||||
<figcaption><🜂🜄|🜁🜃></figcaption>
|
||||
<pre><code class="language-powershell">search-store "ubuntu"
|
||||
</code></pre>
|
||||
</figure>
|
||||
|
||||

|
||||
|
||||
to access your file and view it, you can run either
|
||||
|
||||
@1 | get-file
|
||||
|
||||
or if you have mpv installed (the preferred way for video files)
|
||||
|
||||
@1 | .pipe
|
||||
|
||||
Reference in New Issue
Block a user