dfd
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled

This commit is contained in:
nose
2025-12-24 22:15:54 -08:00
parent df24a0cb44
commit f410edb91e
11 changed files with 868 additions and 46 deletions

View File

@@ -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
@@ -160,9 +160,41 @@ class API_folder_store:
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,16 +562,30 @@ 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,))
row = cursor.fetchone()
@@ -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

View File

@@ -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

View File

@@ -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
View 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
View 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

View 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)">─────────────────────────────────────────────────&#160;Available&#160;formats&#160;for&#160;https://www.youtube.com/watch?v=_23dFb50Z2Y&#160;──────────────────────────────────────────────────</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)">&#160;&#160;&#160;&#160;&#160;&#160;#</text><text class="terminal-1511995346-r2" x="170.8" y="68.8" textLength="146.4" clip-path="url(#terminal-1511995346-line-2)">ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r2" x="353.8" y="68.8" textLength="390.4" clip-path="url(#terminal-1511995346-line-2)">RESOLUTION&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r2" x="780.8" y="68.8" textLength="183" clip-path="url(#terminal-1511995346-line-2)">EXT&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r2" x="1000.4" y="68.8" textLength="207.4" clip-path="url(#terminal-1511995346-line-2)">SIZE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r2" x="1244.4" y="68.8" textLength="414.8" clip-path="url(#terminal-1511995346-line-2)">VIDEO&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r2" x="1695.8" y="68.8" textLength="329.4" clip-path="url(#terminal-1511995346-line-2)">AUDIO&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;1</text><text class="terminal-1511995346-r1" x="170.8" y="117.6" textLength="146.4" clip-path="url(#terminal-1511995346-line-4)">140&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="117.6" textLength="390.4" clip-path="url(#terminal-1511995346-line-4)">audio&#160;only&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="117.6" textLength="183" clip-path="url(#terminal-1511995346-line-4)">m4a&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="117.6" textLength="207.4" clip-path="url(#terminal-1511995346-line-4)">0.4mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="117.6" textLength="414.8" clip-path="url(#terminal-1511995346-line-4)">none&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;2</text><text class="terminal-1511995346-r1" x="170.8" y="142" textLength="146.4" clip-path="url(#terminal-1511995346-line-5)">251&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="142" textLength="390.4" clip-path="url(#terminal-1511995346-line-5)">audio&#160;only&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="142" textLength="183" clip-path="url(#terminal-1511995346-line-5)">webm&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="142" textLength="207.4" clip-path="url(#terminal-1511995346-line-5)">0.4mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="142" textLength="414.8" clip-path="url(#terminal-1511995346-line-5)">none&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1695.8" y="142" textLength="329.4" clip-path="url(#terminal-1511995346-line-5)">opus&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;3</text><text class="terminal-1511995346-r1" x="170.8" y="166.4" textLength="146.4" clip-path="url(#terminal-1511995346-line-6)">91&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="166.4" textLength="390.4" clip-path="url(#terminal-1511995346-line-6)">256x144&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="166.4" textLength="183" clip-path="url(#terminal-1511995346-line-6)">mp4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="166.4" textLength="414.8" clip-path="url(#terminal-1511995346-line-6)">avc1.4d400c&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;4</text><text class="terminal-1511995346-r1" x="170.8" y="190.8" textLength="146.4" clip-path="url(#terminal-1511995346-line-7)">160&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="190.8" textLength="390.4" clip-path="url(#terminal-1511995346-line-7)">256x144&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="190.8" textLength="183" clip-path="url(#terminal-1511995346-line-7)">mp4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="190.8" textLength="207.4" clip-path="url(#terminal-1511995346-line-7)">0.1mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="190.8" textLength="414.8" clip-path="url(#terminal-1511995346-line-7)">avc1.4d400c&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1695.8" y="190.8" textLength="329.4" clip-path="url(#terminal-1511995346-line-7)">none&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;5</text><text class="terminal-1511995346-r1" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-1511995346-line-8)">93&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="215.2" textLength="390.4" clip-path="url(#terminal-1511995346-line-8)">640x360&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="215.2" textLength="183" clip-path="url(#terminal-1511995346-line-8)">mp4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="215.2" textLength="414.8" clip-path="url(#terminal-1511995346-line-8)">avc1.4d401e&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;6</text><text class="terminal-1511995346-r1" x="170.8" y="239.6" textLength="146.4" clip-path="url(#terminal-1511995346-line-9)">134&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="239.6" textLength="390.4" clip-path="url(#terminal-1511995346-line-9)">640x360&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="239.6" textLength="183" clip-path="url(#terminal-1511995346-line-9)">mp4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="239.6" textLength="207.4" clip-path="url(#terminal-1511995346-line-9)">0.6mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="239.6" textLength="414.8" clip-path="url(#terminal-1511995346-line-9)">avc1.4d401e&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1695.8" y="239.6" textLength="329.4" clip-path="url(#terminal-1511995346-line-9)">none&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;7</text><text class="terminal-1511995346-r1" x="170.8" y="264" textLength="146.4" clip-path="url(#terminal-1511995346-line-10)">18&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="264" textLength="390.4" clip-path="url(#terminal-1511995346-line-10)">640x360&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="264" textLength="183" clip-path="url(#terminal-1511995346-line-10)">mp4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="264" textLength="207.4" clip-path="url(#terminal-1511995346-line-10)">0.8mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="264" textLength="414.8" clip-path="url(#terminal-1511995346-line-10)">avc1.42001e&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1695.8" y="264" textLength="329.4" clip-path="url(#terminal-1511995346-line-10)">mp4a.40.2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;8</text><text class="terminal-1511995346-r1" x="170.8" y="288.4" textLength="146.4" clip-path="url(#terminal-1511995346-line-11)">243&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="353.8" y="288.4" textLength="390.4" clip-path="url(#terminal-1511995346-line-11)">640x360&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="780.8" y="288.4" textLength="183" clip-path="url(#terminal-1511995346-line-11)">webm&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1000.4" y="288.4" textLength="207.4" clip-path="url(#terminal-1511995346-line-11)">0.6mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1244.4" y="288.4" textLength="414.8" clip-path="url(#terminal-1511995346-line-11)">vp9&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1511995346-r1" x="1695.8" y="288.4" textLength="329.4" clip-path="url(#terminal-1511995346-line-11)">none&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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
View 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)">─────────────────────────────────────────────────────────────────────────────────────────&#160;add-file&#160;-store&#160;tutorial&#160;─────────────────────────────────────────────────────────────────────────────────────────</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#</text><text class="terminal-4105504262-r2" x="207.4" y="68.8" textLength="1281" clip-path="url(#terminal-4105504262-line-2)">TITLE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r2" x="1525" y="68.8" textLength="439.2" clip-path="url(#terminal-4105504262-line-2)">STORE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r2" x="2000.8" y="68.8" textLength="256.2" clip-path="url(#terminal-4105504262-line-2)">SIZE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r2" x="2293.6" y="68.8" textLength="195.2" clip-path="url(#terminal-4105504262-line-2)">EXT&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1</text><text class="terminal-4105504262-r1" x="207.4" y="117.6" textLength="1281" clip-path="url(#terminal-4105504262-line-4)">terry&#160;davis&#160;-&#160;command&#160;line&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r1" x="1525" y="117.6" textLength="439.2" clip-path="url(#terminal-4105504262-line-4)">tutorial&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r1" x="2000.8" y="117.6" textLength="256.2" clip-path="url(#terminal-4105504262-line-4)">1&#160;mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-4105504262-r1" x="2293.6" y="117.6" textLength="195.2" clip-path="url(#terminal-4105504262-line-4)">mkv&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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
View 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)">─────────────────────────────────────────────────────────────────────────────────────&#160;tag:&#160;terry&#160;davis&#160;-&#160;command&#160;line&#160;──────────────────────────────────────────────────────────────────────────────────────</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#</text><text class="terminal-2184702832-r2" x="268.4" y="68.8" textLength="2220.4" clip-path="url(#terminal-2184702832-line-2)">TAG&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;2</text><text class="terminal-2184702832-r1" x="268.4" y="142" textLength="2220.4" clip-path="url(#terminal-2184702832-line-5)">cli&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;4</text><text class="terminal-2184702832-r1" x="268.4" y="190.8" textLength="2220.4" clip-path="url(#terminal-2184702832-line-7)">desktop&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;davis&#160;-&#160;command&#160;line&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;6</text><text class="terminal-2184702832-r1" x="268.4" y="239.6" textLength="2220.4" clip-path="url(#terminal-2184702832-line-9)">ubuntu&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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
View 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)">─────────────────────────────────────────────────────────────────────────────────────&#160;tag:&#160;terry&#160;davis&#160;-&#160;command&#160;line&#160;──────────────────────────────────────────────────────────────────────────────────────</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#</text><text class="terminal-4170162618-r2" x="268.4" y="68.8" textLength="2220.4" clip-path="url(#terminal-4170162618-line-2)">TAG&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;2</text><text class="terminal-4170162618-r1" x="268.4" y="142" textLength="2220.4" clip-path="url(#terminal-4170162618-line-5)">creator:archeroflusitania&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;davis&#160;-&#160;command&#160;line&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;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&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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
View 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)">──────────────────────────────────────────────────────────────────────────────────────────&#160;search-store&#160;&quot;ubuntu&quot;&#160;───────────────────────────────────────────────────────────────────────────────────────────</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#</text><text class="terminal-1147275963-r2" x="207.4" y="68.8" textLength="1281" clip-path="url(#terminal-1147275963-line-2)">TITLE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r2" x="1525" y="68.8" textLength="439.2" clip-path="url(#terminal-1147275963-line-2)">STORE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r2" x="2000.8" y="68.8" textLength="256.2" clip-path="url(#terminal-1147275963-line-2)">SIZE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r2" x="2293.6" y="68.8" textLength="195.2" clip-path="url(#terminal-1147275963-line-2)">EXT&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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)">&#160;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;</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)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1</text><text class="terminal-1147275963-r1" x="207.4" y="117.6" textLength="1281" clip-path="url(#terminal-1147275963-line-4)">terry&#160;davis&#160;-&#160;command&#160;line&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r1" x="1525" y="117.6" textLength="439.2" clip-path="url(#terminal-1147275963-line-4)">tutorial&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r1" x="2000.8" y="117.6" textLength="256.2" clip-path="url(#terminal-1147275963-line-4)">1&#160;mb&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1147275963-r1" x="2293.6" y="117.6" textLength="195.2" clip-path="url(#terminal-1147275963-line-4)">mkv&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</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
View 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>
![Available formats](<img/Available formats.svg>)
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>
![add-file](<img/add-file.svg>)
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>
![get-tag](<img/get-tag.svg>)
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>
![add-tag](<img/add-tag.svg>)
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>
![search-store](<img/search-store.svg>)
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