jh
This commit is contained in:
@@ -292,10 +292,10 @@ class PodcastIndex(Provider):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from SYS.config import resolve_output_dir
|
from SYS.config import resolve_output_dir
|
||||||
|
|
||||||
output_dir = resolve_output_dir(self.config or {})
|
output_dir = resolve_output_dir(self.config or {})
|
||||||
except Exception:
|
except Exception:
|
||||||
output_dir = Path.home() / "Downloads"
|
import tempfile
|
||||||
|
output_dir = Path(tempfile.gettempdir())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
output_dir = Path(output_dir).expanduser()
|
output_dir = Path(output_dir).expanduser()
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ class Soulseek(Provider):
|
|||||||
# NOTE: These defaults preserve existing behavior.
|
# NOTE: These defaults preserve existing behavior.
|
||||||
USERNAME = "asjhkjljhkjfdsd334"
|
USERNAME = "asjhkjljhkjfdsd334"
|
||||||
PASSWORD = "khhhg"
|
PASSWORD = "khhhg"
|
||||||
DOWNLOAD_DIR = "./downloads"
|
DOWNLOAD_DIR = None
|
||||||
MAX_WAIT_TRANSFER = 1200
|
MAX_WAIT_TRANSFER = 1200
|
||||||
|
|
||||||
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
||||||
@@ -325,13 +325,17 @@ class Soulseek(Provider):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Use tempfile directory as default if '.' or generic placeholder was passed
|
# Use tempfile directory as default if generic path elements were passed or None.
|
||||||
# by a caller that didn't know better.
|
if output_dir is None:
|
||||||
target_dir = Path(output_dir)
|
|
||||||
if str(target_dir) == "." or str(target_dir) == "downloads":
|
|
||||||
import tempfile
|
import tempfile
|
||||||
target_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
target_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
||||||
target_dir.mkdir(parents=True, exist_ok=True)
|
else:
|
||||||
|
target_dir = Path(output_dir)
|
||||||
|
if str(target_dir) in (".", "downloads", "Downloads"):
|
||||||
|
import tempfile
|
||||||
|
target_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
||||||
|
|
||||||
|
target_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# This cmdlet stack is synchronous; use asyncio.run for clarity.
|
# This cmdlet stack is synchronous; use asyncio.run for clarity.
|
||||||
return asyncio.run(
|
return asyncio.run(
|
||||||
@@ -348,12 +352,22 @@ class Soulseek(Provider):
|
|||||||
# dedicated loop in this thread.
|
# dedicated loop in this thread.
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
try:
|
try:
|
||||||
|
# Re-resolve target_dir inside rescue block just in case
|
||||||
|
if output_dir is None:
|
||||||
|
import tempfile
|
||||||
|
target_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
||||||
|
else:
|
||||||
|
target_dir = Path(output_dir)
|
||||||
|
if str(target_dir) in (".", "downloads", "Downloads"):
|
||||||
|
import tempfile
|
||||||
|
target_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
||||||
|
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
return loop.run_until_complete(
|
return loop.run_until_complete(
|
||||||
download_soulseek_file(
|
download_soulseek_file(
|
||||||
username=username,
|
username=username,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
output_dir=output_dir,
|
output_dir=target_dir,
|
||||||
timeout=self.MAX_WAIT_TRANSFER,
|
timeout=self.MAX_WAIT_TRANSFER,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -642,7 +656,7 @@ class Soulseek(Provider):
|
|||||||
async def download_soulseek_file(
|
async def download_soulseek_file(
|
||||||
username: str,
|
username: str,
|
||||||
filename: str,
|
filename: str,
|
||||||
output_dir: Path = Path("./downloads"),
|
output_dir: Optional[Path] = None,
|
||||||
timeout: int = 1200,
|
timeout: int = 1200,
|
||||||
*,
|
*,
|
||||||
client_username: Optional[str] = None,
|
client_username: Optional[str] = None,
|
||||||
@@ -656,6 +670,10 @@ async def download_soulseek_file(
|
|||||||
from aioslsk.transfer.model import Transfer, TransferDirection
|
from aioslsk.transfer.model import Transfer, TransferDirection
|
||||||
from aioslsk.transfer.state import TransferState
|
from aioslsk.transfer.state import TransferState
|
||||||
|
|
||||||
|
if output_dir is None:
|
||||||
|
import tempfile
|
||||||
|
output_dir = Path(tempfile.gettempdir()) / "Medios" / "Soulseek"
|
||||||
|
|
||||||
output_dir = Path(output_dir)
|
output_dir = Path(output_dir)
|
||||||
output_dir.mkdir(parents=True, exist_ok=True)
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
from SYS.logger import log
|
from SYS.logger import log
|
||||||
@@ -22,6 +23,12 @@ def global_config() -> List[Dict[str, Any]]:
|
|||||||
"label": "Debug Output",
|
"label": "Debug Output",
|
||||||
"default": "false",
|
"default": "false",
|
||||||
"choices": ["true", "false"]
|
"choices": ["true", "false"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "auto_update",
|
||||||
|
"label": "Auto-Update",
|
||||||
|
"default": "true",
|
||||||
|
"choices": ["true", "false"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -185,7 +192,7 @@ def parse_conf_text(text: str, *, base: Optional[Dict[str, Any]] = None) -> Dict
|
|||||||
"""Parse a lightweight .conf format into the app's config dict.
|
"""Parse a lightweight .conf format into the app's config dict.
|
||||||
|
|
||||||
Supported patterns:
|
Supported patterns:
|
||||||
- Top-level key/value: temp="C:\\Users\\Me\\Downloads"
|
- Top-level key/value: temp="./temp"
|
||||||
- Sections: [store=folder] + name/path lines
|
- Sections: [store=folder] + name/path lines
|
||||||
- Sections: [store=hydrusnetwork] + name/access key/url lines
|
- Sections: [store=hydrusnetwork] + name/access key/url lines
|
||||||
- Sections: [provider=OpenLibrary] + email/password lines
|
- Sections: [provider=OpenLibrary] + email/password lines
|
||||||
@@ -447,7 +454,7 @@ def resolve_output_dir(config: Dict[str, Any]) -> Path:
|
|||||||
Priority:
|
Priority:
|
||||||
1. config["temp"] - explicitly set temp/output directory
|
1. config["temp"] - explicitly set temp/output directory
|
||||||
2. config["outfile"] - fallback to outfile setting
|
2. config["outfile"] - fallback to outfile setting
|
||||||
3. Home/Videos - safe user directory fallback
|
3. System Temp - default fallback directory
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path to output directory
|
Path to output directory
|
||||||
@@ -471,8 +478,8 @@ def resolve_output_dir(config: Dict[str, Any]) -> Path:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Fallback to user's Videos directory
|
# Fallback to system temp directory
|
||||||
return Path.home() / "Videos"
|
return Path(tempfile.gettempdir())
|
||||||
|
|
||||||
|
|
||||||
def get_local_storage_path(config: Dict[str, Any]) -> Optional[Path]:
|
def get_local_storage_path(config: Dict[str, Any]) -> Optional[Path]:
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class CmdletArg:
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
# For STORAGE arg with a handler
|
# For STORAGE arg with a handler
|
||||||
storage_path = SharedArgs.STORAGE.resolve('local') # Returns Path.home() / "Videos"
|
storage_path = SharedArgs.STORAGE.resolve('local') # Returns Path(tempfile.gettempdir())
|
||||||
"""
|
"""
|
||||||
if self.handler is not None and callable(self.handler):
|
if self.handler is not None and callable(self.handler):
|
||||||
return self.handler(value)
|
return self.handler(value)
|
||||||
@@ -354,47 +354,29 @@ class SharedArgs:
|
|||||||
) -> Path:
|
) -> Path:
|
||||||
"""Resolve a storage location name to a filesystem Path.
|
"""Resolve a storage location name to a filesystem Path.
|
||||||
|
|
||||||
Maps storage identifiers (hydrus, local, ftp) to their actual
|
Maps storage identifiers to their actual filesystem paths.
|
||||||
filesystem paths. This is the single source of truth for storage location resolution.
|
This project has been refactored to use system temporary directories
|
||||||
Note: 0x0.st is now accessed via file providers (-provider 0x0), not storage.
|
for all staging/downloads by default.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
storage_value: One of 'hydrus', 'local', 'ftp', or None
|
storage_value: One of 'hydrus', 'local', 'ftp', or None (currently unified to temp)
|
||||||
default: Path to return if storage_value is None (defaults to Videos)
|
default: Path to return if storage_value is None (defaults to temp directory)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Resolved Path object for the storage location
|
Resolved Path object for the storage location (typically system temp)
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If storage_value is not a recognized storage type
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
# In a cmdlet:
|
# In a cmdlet:
|
||||||
storage_path = SharedArgs.resolve_storage(parsed.storage)
|
storage_path = SharedArgs.resolve_storage(parsed.get('storage'))
|
||||||
|
# Returns Path(tempfile.gettempdir())
|
||||||
# With defaults:
|
|
||||||
path = SharedArgs.resolve_storage(None) # Returns home/Videos
|
|
||||||
path = SharedArgs.resolve_storage('local') # Returns home/Videos
|
|
||||||
path = SharedArgs.resolve_storage('hydrus') # Returns home/.hydrus/client_files
|
|
||||||
"""
|
"""
|
||||||
storage_map = {
|
# We no longer maintain a hardcoded map for 'hydrus' (~/.hydrus) or 'local' (~/Videos).
|
||||||
"local": Path.home() / "Videos",
|
# Everything defaults to the system temp directory unless a specific default is provided.
|
||||||
"hydrus": Path.home() / ".hydrus" / "client_files",
|
# This ensures environment independence.
|
||||||
"ftp": Path.home() / "FTP",
|
if default is not None:
|
||||||
"matrix": Path.home() / "Matrix", # Placeholder, not used for upload path
|
return default
|
||||||
}
|
|
||||||
|
|
||||||
if storage_value is None:
|
return Path(tempfile.gettempdir())
|
||||||
return default or (Path.home() / "Videos")
|
|
||||||
|
|
||||||
storage_lower = storage_value.lower()
|
|
||||||
if storage_lower not in storage_map:
|
|
||||||
raise ValueError(
|
|
||||||
f"Unknown storage location '{storage_value}'. "
|
|
||||||
f"Must be one of: {', '.join(storage_map.keys())}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return storage_map[storage_lower]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, name: str) -> Optional[CmdletArg]:
|
def get(cls, name: str) -> Optional[CmdletArg]:
|
||||||
|
|||||||
@@ -3946,8 +3946,8 @@ class Download_File(Cmdlet):
|
|||||||
final_output_dir = resolve_output_dir(config)
|
final_output_dir = resolve_output_dir(config)
|
||||||
except Exception:
|
except Exception:
|
||||||
import tempfile
|
import tempfile
|
||||||
final_output_dir = Path(tempfile.gettempdir()) / "Medios-Macina"
|
final_output_dir = Path(tempfile.gettempdir())
|
||||||
|
|
||||||
debug(f"Using default directory: {final_output_dir}")
|
debug(f"Using default directory: {final_output_dir}")
|
||||||
|
|
||||||
# Ensure directory exists
|
# Ensure directory exists
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Get_File(sh.Cmdlet):
|
|||||||
super().__init__(
|
super().__init__(
|
||||||
name="get-file",
|
name="get-file",
|
||||||
summary="Export file to local path",
|
summary="Export file to local path",
|
||||||
usage="@1 | get-file -path C:\\Downloads",
|
usage="@1 | get-file -path ./output",
|
||||||
arg=[
|
arg=[
|
||||||
sh.SharedArgs.QUERY,
|
sh.SharedArgs.QUERY,
|
||||||
sh.SharedArgs.STORE,
|
sh.SharedArgs.STORE,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import httpx
|
import httpx
|
||||||
@@ -948,9 +949,9 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Default: User's Videos directory
|
# Default: system temp directory
|
||||||
if screenshot_dir is None:
|
if screenshot_dir is None:
|
||||||
screenshot_dir = Path.home() / "Videos"
|
screenshot_dir = Path(tempfile.gettempdir())
|
||||||
debug(f"[screen_shot] Using default directory: {screenshot_dir}")
|
debug(f"[screen_shot] Using default directory: {screenshot_dir}")
|
||||||
|
|
||||||
ensure_directory(screenshot_dir)
|
ensure_directory(screenshot_dir)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ CMDLET = Cmdlet(
|
|||||||
CmdletArg(
|
CmdletArg(
|
||||||
"-outdir",
|
"-outdir",
|
||||||
description=
|
description=
|
||||||
"Output directory for the clip (defaults to source folder for local files; otherwise uses config temp/videos).",
|
"Output directory for the clip (defaults to source folder for local files; otherwise uses system temp).",
|
||||||
),
|
),
|
||||||
CmdletArg(
|
CmdletArg(
|
||||||
"-delete",
|
"-delete",
|
||||||
|
|||||||
@@ -1094,6 +1094,26 @@ def main() -> int:
|
|||||||
ps1_text = r"""Param([Parameter(ValueFromRemainingArguments=$true)] $args)
|
ps1_text = r"""Param([Parameter(ValueFromRemainingArguments=$true)] $args)
|
||||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
$repo = (Resolve-Path (Join-Path $scriptDir "..")).Path
|
$repo = (Resolve-Path (Join-Path $scriptDir "..")).Path
|
||||||
|
|
||||||
|
# Automatically check for updates if this is a git repository
|
||||||
|
if (Test-Path (Join-Path $repo ".git")) {
|
||||||
|
try {
|
||||||
|
if (-not $env:MM_NO_UPDATE) {
|
||||||
|
$conf = Join-Path $repo "config.conf"
|
||||||
|
$skip = $false
|
||||||
|
if (Test-Path $conf) {
|
||||||
|
if ((Get-Content $conf | Select-String "auto_update\s*=\s*(false|no|off|0)") -ne $null) {
|
||||||
|
$skip = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $skip) {
|
||||||
|
Write-Host "Checking for updates..." -ForegroundColor Gray
|
||||||
|
git -C "$repo" pull --ff-only --quiet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
$venv = Join-Path $repo '.venv'
|
$venv = Join-Path $repo '.venv'
|
||||||
$py = Join-Path $venv 'Scripts\python.exe'
|
$py = Join-Path $venv 'Scripts\python.exe'
|
||||||
if (Test-Path $py) {
|
if (Test-Path $py) {
|
||||||
@@ -1139,6 +1159,22 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
|
|||||||
"@echo off\n"
|
"@echo off\n"
|
||||||
"setlocal enabledelayedexpansion\n"
|
"setlocal enabledelayedexpansion\n"
|
||||||
f'set "REPO={repo_bat_str}"\n'
|
f'set "REPO={repo_bat_str}"\n'
|
||||||
|
"\n"
|
||||||
|
"# Automatically check for updates if this is a git repository\n"
|
||||||
|
"if not defined MM_NO_UPDATE (\n"
|
||||||
|
" if exist \"!REPO!\\.git\" (\n"
|
||||||
|
" set \"AUTO_UPDATE=true\"\n"
|
||||||
|
" if exist \"!REPO!\\config.conf\" (\n"
|
||||||
|
" findstr /i /r \"auto_update.*=.*false auto_update.*=.*no auto_update.*=.*off auto_update.*=.*0\" \"!REPO!\\config.conf\" >nul 2>&1\n"
|
||||||
|
" if !errorlevel! == 0 set \"AUTO_UPDATE=false\"\n"
|
||||||
|
" )\n"
|
||||||
|
" if \"!AUTO_UPDATE!\" == \"true\" (\n"
|
||||||
|
" echo Checking for updates...\n"
|
||||||
|
" git -C \"!REPO!\" pull --ff-only --quiet\n"
|
||||||
|
" )\n"
|
||||||
|
" )\n"
|
||||||
|
")\n"
|
||||||
|
"\n"
|
||||||
"set \"VENV=!REPO!\\.venv\"\n"
|
"set \"VENV=!REPO!\\.venv\"\n"
|
||||||
"set \"PY=!VENV!\\Scripts\\python.exe\"\n"
|
"set \"PY=!VENV!\\Scripts\\python.exe\"\n"
|
||||||
"set \"ENTRY=!REPO!\\scripts\\cli_entry.py\"\n"
|
"set \"ENTRY=!REPO!\\scripts\\cli_entry.py\"\n"
|
||||||
@@ -1299,6 +1335,21 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
|
|||||||
" done\n"
|
" done\n"
|
||||||
' echo "MM_DEBUG: end diagnostics" >&2\n'
|
' echo "MM_DEBUG: end diagnostics" >&2\n'
|
||||||
"fi\n"
|
"fi\n"
|
||||||
|
"\n"
|
||||||
|
"# Automatically check for updates if this is a git repository\n"
|
||||||
|
'if [ -z "${MM_NO_UPDATE:-}" ] && [ -d "$REPO/.git" ] && command -v git >/dev/null 2>&1; then\n'
|
||||||
|
' AUTO_UPDATE="true"\n'
|
||||||
|
' if [ -f "$REPO/config.conf" ]; then\n'
|
||||||
|
' if grep -qiE \'auto_update\s*=\s*(false|no|off|0)\' "$REPO/config.conf"; then\n'
|
||||||
|
' AUTO_UPDATE="false"\n'
|
||||||
|
' fi\n'
|
||||||
|
' fi\n'
|
||||||
|
' if [ "$AUTO_UPDATE" = "true" ]; then\n'
|
||||||
|
' echo "Checking for updates..."\n'
|
||||||
|
' git -C "$REPO" pull --ff-only --quiet || true\n'
|
||||||
|
' fi\n'
|
||||||
|
"fi\n"
|
||||||
|
"\n"
|
||||||
"# Use -m scripts.cli_entry directly instead of pip-generated wrapper to avoid entry point issues\n"
|
"# Use -m scripts.cli_entry directly instead of pip-generated wrapper to avoid entry point issues\n"
|
||||||
"# Prefer venv's python3, then venv's python\n"
|
"# Prefer venv's python3, then venv's python\n"
|
||||||
'if [ -x "$VENV/bin/python3" ]; then\n'
|
'if [ -x "$VENV/bin/python3" ]; then\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user