migrate os.run to subprocess
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
from typing import Sequence
|
||||||
from classes.user import User
|
from classes.user import User
|
||||||
from functions import LOG
|
from functions import LOG
|
||||||
from functions import load_config_variables
|
from functions import load_config_variables
|
||||||
from functions import quote
|
|
||||||
from functions import run
|
from functions import run
|
||||||
|
|
||||||
|
|
||||||
@@ -13,43 +15,54 @@ class Gallery:
|
|||||||
self.link: str = ""
|
self.link: str = ""
|
||||||
self.dest: str = ""
|
self.dest: str = ""
|
||||||
self.list: str = ""
|
self.list: str = ""
|
||||||
self.opt_args: str = ""
|
self.opt_args: str | Sequence[str] = ""
|
||||||
self.command: str = ""
|
self.command: list[str] = []
|
||||||
|
|
||||||
def generate_command(self, user: User = User(1), is_comic: bool = False) -> None:
|
def generate_command(self, user: User = User(1), is_comic: bool = False) -> None:
|
||||||
"""Generates a command string."""
|
"""Generates a command string."""
|
||||||
if is_comic:
|
if is_comic:
|
||||||
configs = load_config_variables()
|
configs = load_config_variables()
|
||||||
directory = quote(configs["comic"]["download-dir"])
|
directory = str(configs["comic"]["download-dir"])
|
||||||
database = quote(configs["comic"]["database"])
|
database = str(configs["comic"]["database"])
|
||||||
queue = quote(configs["comic"][f"{self.list}-list"]) if self.list else ""
|
queue = str(configs["comic"][f"{self.list}-list"]) if self.list else ""
|
||||||
else:
|
else:
|
||||||
directory = quote(str(user.directories[self.dest]))
|
directory = str(user.directories[self.dest])
|
||||||
database = quote(str(user.dbs["gallery"]))
|
database = str(user.dbs["gallery"])
|
||||||
queue = quote(str(user.lists[self.list])) if self.list else ""
|
queue = str(user.lists[self.list]) if self.list else ""
|
||||||
|
|
||||||
command = f"gallery-dl --sleep {str(user.sleep)}"
|
command = ["gallery-dl", "--sleep", str(user.sleep)]
|
||||||
command += self.skip_arg if self.skip_arg else ""
|
if self.skip_arg:
|
||||||
command += f" --dest {directory}" if self.dest or is_comic else ""
|
command += shlex.split(self.skip_arg)
|
||||||
command += f" --download-archive {database}" if self.archive else ""
|
if self.dest or is_comic:
|
||||||
command += self.opt_args if self.opt_args else ""
|
command += ["--dest", directory]
|
||||||
|
if self.archive:
|
||||||
|
command += ["--download-archive", database]
|
||||||
|
if self.opt_args:
|
||||||
|
if isinstance(self.opt_args, str):
|
||||||
|
command += shlex.split(self.opt_args)
|
||||||
|
else:
|
||||||
|
command += list(self.opt_args)
|
||||||
|
|
||||||
# Add authentication options from environment variables
|
# Add authentication options from environment variables
|
||||||
command += ' -o "extractor.pixiv.refresh-token=${GALLERY_DL_PIXIV_REFRESH_TOKEN}"'
|
auth_env = {
|
||||||
command += ' -o "extractor.bluesky.password=${GALLERY_DL_BLUESKY_PASSWORD}"'
|
"extractor.pixiv.refresh-token": "GALLERY_DL_PIXIV_REFRESH_TOKEN",
|
||||||
command += ' -o "extractor.deviantart.refresh-token=${GALLERY_DL_DEVIANTART_REFRESH_TOKEN}"'
|
"extractor.bluesky.password": "GALLERY_DL_BLUESKY_PASSWORD",
|
||||||
command += ' -o "extractor.flickr.access-token=${GALLERY_DL_FLICKR_ACCESS_TOKEN}"'
|
"extractor.deviantart.refresh-token": "GALLERY_DL_DEVIANTART_REFRESH_TOKEN",
|
||||||
command += ' -o "extractor.flickr.access-token-secret=${GALLERY_DL_FLICKR_ACCESS_TOKEN_SECRET}"'
|
"extractor.flickr.access-token": "GALLERY_DL_FLICKR_ACCESS_TOKEN",
|
||||||
command += ' -o "extractor.reddit.refresh-token=${GALLERY_DL_REDDIT_REFRESH_TOKEN}"'
|
"extractor.flickr.access-token-secret": "GALLERY_DL_FLICKR_ACCESS_TOKEN_SECRET",
|
||||||
command += ' -o "extractor.tumblr.access-token=${GALLERY_DL_TUMBLR_ACCESS_TOKEN}"'
|
"extractor.reddit.refresh-token": "GALLERY_DL_REDDIT_REFRESH_TOKEN",
|
||||||
command += ' -o "extractor.tumblr.access-token-secret=${GALLERY_DL_TUMBLR_ACCESS_TOKEN_SECRET}"'
|
"extractor.tumblr.access-token": "GALLERY_DL_TUMBLR_ACCESS_TOKEN",
|
||||||
command += ' -o "extractor.tumblr.api-key=${GALLERY_DL_TUMBLR_API_KEY}"'
|
"extractor.tumblr.access-token-secret": "GALLERY_DL_TUMBLR_ACCESS_TOKEN_SECRET",
|
||||||
command += ' -o "extractor.tumblr.api-secret=${GALLERY_DL_TUMBLR_API_SECRET}"'
|
"extractor.tumblr.api-key": "GALLERY_DL_TUMBLR_API_KEY",
|
||||||
|
"extractor.tumblr.api-secret": "GALLERY_DL_TUMBLR_API_SECRET",
|
||||||
|
}
|
||||||
|
for key, env_var in auth_env.items():
|
||||||
|
command += ["-o", f"{key}={os.environ.get(env_var, '')}"]
|
||||||
|
|
||||||
if self.link and not self.list:
|
if self.link and not self.list:
|
||||||
command += f" {quote(self.link)}"
|
command.append(self.link)
|
||||||
if self.list and not self.link:
|
if self.list and not self.link:
|
||||||
command += f" -i {queue}"
|
command += ["-i", queue]
|
||||||
|
|
||||||
LOG.debug(command)
|
LOG.debug(command)
|
||||||
self.command = command
|
self.command = command
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ Also following in line more posix and python rules.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from pathlib import Path
|
||||||
import yaml
|
import yaml
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from functions import LOG
|
from functions import LOG
|
||||||
from functions import run
|
from functions import run
|
||||||
from functions import quote
|
|
||||||
from functions import list_lines
|
from functions import list_lines
|
||||||
from functions import load_config_variables
|
from functions import load_config_variables
|
||||||
from functions import parse_link
|
from functions import parse_link
|
||||||
@@ -57,40 +57,55 @@ def parse_gallery(gdl_list: str, user: User) -> None:
|
|||||||
gallery.run_command(ARGS.flag_verbose)
|
gallery.run_command(ARGS.flag_verbose)
|
||||||
|
|
||||||
|
|
||||||
def parse_instagram(link: str) -> str:
|
def parse_instagram(link: str) -> list[str]:
|
||||||
"""Fix instagram links"""
|
"""Fix instagram links"""
|
||||||
if "instagram" not in link:
|
if "instagram" not in link:
|
||||||
return ""
|
return []
|
||||||
if isinstance(ARGS.post_type, list):
|
if isinstance(ARGS.post_type, list):
|
||||||
return f" -o include={quote(','.join(ARGS.post_type))}"
|
return ["-o", f"include={','.join(ARGS.post_type)}"]
|
||||||
return f" -o include={quote(ARGS.post_type)}"
|
return ["-o", f"include={ARGS.post_type}"]
|
||||||
|
|
||||||
|
|
||||||
def video_command(video: Video) -> str:
|
def video_command(video: Video):
|
||||||
"""Filters and processes the required command to download videos"""
|
"""Filters and processes the required command to download videos"""
|
||||||
command = "yt-dlp"
|
command = ["yt-dlp"]
|
||||||
rgx_yt = re.compile(r"(https:\/\/youtube|https:\/\/www.youtube|https:\/\/youtu.be)")
|
rgx_yt = re.compile(r"(https:\/\/youtube|https:\/\/www.youtube|https:\/\/youtu.be)")
|
||||||
rgx_music = re.compile(r"(https:\/\/music.youtube.*)")
|
rgx_music = re.compile(r"(https:\/\/music.youtube.*)")
|
||||||
|
|
||||||
if re.search(r"chaturbate", video.link):
|
if re.search(r"chaturbate", video.link):
|
||||||
return f"stream-dl {video.link.rstrip("/").split("/")[-1]}"
|
return ["stream-dl", video.link.rstrip("/").split("/")[-1]]
|
||||||
|
|
||||||
if rgx_yt.search(video.link):
|
if rgx_yt.search(video.link):
|
||||||
command += " --embed-subs --embed-thumbnail"
|
command += [
|
||||||
command += " --embed-metadata --embed-chapters"
|
"--embed-subs",
|
||||||
command += f" -o {quote(video.dest + '/%(title)s.%(ext)s')}"
|
"--embed-thumbnail",
|
||||||
|
"--embed-metadata",
|
||||||
|
"--embed-chapters",
|
||||||
|
"-o",
|
||||||
|
f"{video.dest}/%(title)s.%(ext)s",
|
||||||
|
]
|
||||||
|
|
||||||
elif rgx_music.search(video.link):
|
elif rgx_music.search(video.link):
|
||||||
command += f" --download-archive {video.database}" if video.use_archive else ""
|
if video.use_archive:
|
||||||
command += " --no-playlist --newline -x"
|
command += ["--download-archive", video.database]
|
||||||
command += " --audio-format best --add-metadata --audio-quality 0 -o"
|
command += [
|
||||||
command += f" {quote(video.dest + '/%(title)s.%(ext)s')}"
|
"--no-playlist",
|
||||||
|
"--newline",
|
||||||
|
"-x",
|
||||||
|
"--audio-format",
|
||||||
|
"best",
|
||||||
|
"--add-metadata",
|
||||||
|
"--audio-quality",
|
||||||
|
"0",
|
||||||
|
"-o",
|
||||||
|
f"{video.dest}/%(title)s.%(ext)s",
|
||||||
|
]
|
||||||
|
|
||||||
else: # Any other video link, just do it generic
|
else: # Any other video link, just do it generic
|
||||||
command += f" -f mp4 -o {quote(video.dest + '/%(title)s.%(ext)s')}"
|
command += ["-f", "mp4", "-o", f"{video.dest}/%(title)s.%(ext)s"]
|
||||||
|
|
||||||
LOG.info("%s %s", command, video.link)
|
LOG.info("%s %s", " ".join(command), video.link)
|
||||||
return f"{command} {quote(video.link)}"
|
return command + [video.link]
|
||||||
|
|
||||||
|
|
||||||
def comic_manager(skip_arg: str, category: str) -> None:
|
def comic_manager(skip_arg: str, category: str) -> None:
|
||||||
@@ -133,15 +148,19 @@ def webcomic_manager():
|
|||||||
|
|
||||||
LOG.info("The webcomic is %s", dest)
|
LOG.info("The webcomic is %s", dest)
|
||||||
|
|
||||||
command = f"cd {quote(dest)} && webcomix custom"
|
command = [
|
||||||
command += f" {quote(name)}"
|
"webcomix",
|
||||||
command += " --start-url"
|
"custom",
|
||||||
command += f" {quote(link)}"
|
name,
|
||||||
command += f" --next-page-xpath={quote(nxt_code)}"
|
"--start-url",
|
||||||
command += f" --image-xpath={quote(img_code)}"
|
link,
|
||||||
command += " -y --cbz"
|
f"--next-page-xpath={nxt_code}",
|
||||||
|
f"--image-xpath={img_code}",
|
||||||
|
"-y",
|
||||||
|
"--cbz",
|
||||||
|
]
|
||||||
|
|
||||||
run(command, ARGS.flag_verbose)
|
run(command, ARGS.flag_verbose, cwd=Path(dest))
|
||||||
|
|
||||||
|
|
||||||
def save_comic(link: str) -> None:
|
def save_comic(link: str) -> None:
|
||||||
@@ -231,8 +250,8 @@ def push_manager(user: User):
|
|||||||
video = Video()
|
video = Video()
|
||||||
video.use_archive = ARGS.flag_archive
|
video.use_archive = ARGS.flag_archive
|
||||||
video.link = link
|
video.link = link
|
||||||
video.dest = f"{user.directories['media']}"
|
video.dest = str(user.directories["media"])
|
||||||
video.database = quote(f"{user.dbs['media']}")
|
video.database = str(user.dbs["media"])
|
||||||
run(video_command(video), ARGS.flag_verbose)
|
run(video_command(video), ARGS.flag_verbose)
|
||||||
|
|
||||||
for link in links_other:
|
for link in links_other:
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import fileinput
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
from typing import Sequence
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
@@ -60,14 +63,24 @@ def clean_cache(directory: Path):
|
|||||||
directory.rmdir()
|
directory.rmdir()
|
||||||
|
|
||||||
|
|
||||||
def run(command: str, verbose: bool):
|
def run(command: str | Sequence[str], verbose: bool, cwd: Path | None = None) -> None:
|
||||||
"""Run command in a subprocess"""
|
"""Run command in a subprocess"""
|
||||||
# pylint: disable=subprocess-run-check
|
# pylint: disable=subprocess-run-check
|
||||||
# This toggle allows for a really wasy debug when using -v
|
# This toggle allows for a really wasy debug when using -v
|
||||||
if verbose:
|
if verbose:
|
||||||
print(command)
|
if isinstance(command, (list, tuple)):
|
||||||
|
print(shlex.join(command))
|
||||||
else:
|
else:
|
||||||
os.system(command)
|
print(command)
|
||||||
|
return
|
||||||
|
|
||||||
|
if isinstance(command, str):
|
||||||
|
expanded = os.path.expandvars(command)
|
||||||
|
args = shlex.split(expanded)
|
||||||
|
else:
|
||||||
|
args = list(command)
|
||||||
|
|
||||||
|
subprocess.run(args, check=False, cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
def list_lines(i: int, line: str) -> str:
|
def list_lines(i: int, line: str) -> str:
|
||||||
@@ -84,19 +97,19 @@ def sort_txt_file(file_path: Path):
|
|||||||
"""Sort every line alphabetically
|
"""Sort every line alphabetically
|
||||||
remove duplicated and empty lines"""
|
remove duplicated and empty lines"""
|
||||||
file = str(file_path.resolve())
|
file = str(file_path.resolve())
|
||||||
run(f"sort -u {quote(file)} -o {quote(file)}", VERBOSE_G)
|
run(["sort", "-u", file, "-o", file], VERBOSE_G)
|
||||||
run(f"sed -i '/^$/d' {quote(file)}", VERBOSE_G)
|
run(["sed", "-i", "/^$/d", file], VERBOSE_G)
|
||||||
run(f'sed -i -e "s,http:,https:," {quote(file)}', VERBOSE_G)
|
run(["sed", "-i", "-e", "s,http:,https:,", file], VERBOSE_G)
|
||||||
# fix this using strip on python
|
# fix this using strip on python
|
||||||
# line.strip("/")
|
# line.strip("/")
|
||||||
run(f'sed -i -e "s,/$,," {quote(file)}', VERBOSE_G) # trailing /
|
run(["sed", "-i", "-e", "s,/$,,", file], VERBOSE_G) # trailing /
|
||||||
|
|
||||||
|
|
||||||
def randomize_txt_file(file_path: Path):
|
def randomize_txt_file(file_path: Path):
|
||||||
"""Randomize the order of the
|
"""Randomize the order of the
|
||||||
lines of the txt file"""
|
lines of the txt file"""
|
||||||
file = str(file_path.resolve())
|
file = str(file_path.resolve())
|
||||||
run(f"sort -R {quote(file)} -o {quote(file)}", VERBOSE_G)
|
run(["sort", "-R", file, "-o", file], VERBOSE_G)
|
||||||
|
|
||||||
|
|
||||||
def parse_list(file):
|
def parse_list(file):
|
||||||
|
|||||||
Reference in New Issue
Block a user