Bloodsucker
This commit is contained in:
parent
6cdd924613
commit
f03d13f7db
8 changed files with 140 additions and 811 deletions
|
@ -25,7 +25,7 @@ then
|
|||
if [ -f "$page_stmp_svg" ]
|
||||
then
|
||||
echo "Processing $page_orig_path (applying stamp)"
|
||||
inkscape "$page_stmp_svg" --export-pdf "$page_stmp_pdf"
|
||||
inkscape "$page_stmp_svg" --export-filename "$page_stmp_pdf"
|
||||
pdftk "$page_orig_path" stamp "$page_stmp_pdf" output "$page_fin_pdf"
|
||||
else
|
||||
echo "Processing $page_orig_path (copying)"
|
||||
|
@ -51,7 +51,7 @@ then
|
|||
do
|
||||
page_stmp_svg="$(echo "$page_orig_path" | sed 's|_og\.pdf$|_fg\.svg|')"
|
||||
echo "Processing $page_orig_path"
|
||||
inkscape "$page_orig_path" --export-plain-svg "$page_stmp_svg"
|
||||
inkscape "$page_orig_path" --export-plain-svg --export-filename "$page_stmp_svg"
|
||||
done
|
||||
echo "Done. Make sure to edit in a a new layer in Inkscape and hide the original one."
|
||||
else
|
||||
|
|
|
@ -29,7 +29,9 @@ if __name__ == "__main__":
|
|||
"-o", "--subject", default=f"Test message {now.strftime('%H:%M:%S')}"
|
||||
)
|
||||
parser.add_argument("-m", "--me", default="Geoffrey")
|
||||
parser.add_argument("-g", "--gtube", action="store_true")
|
||||
parser.add_argument("-d", "--debug", action="store_true")
|
||||
parser.add_argument("-b", "--body", default="")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
@ -37,6 +39,17 @@ if __name__ == "__main__":
|
|||
if args.debug:
|
||||
command = print
|
||||
|
||||
gtube = ""
|
||||
if args.gtube:
|
||||
gtube = """
|
||||
|
||||
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X"""
|
||||
|
||||
body = ""
|
||||
if args.body:
|
||||
body = f"\n\n{args.body}"
|
||||
|
||||
|
||||
text = f"""Date: {now_email}
|
||||
From: {args.sender}
|
||||
Subject: {args.subject}
|
||||
|
@ -45,7 +58,7 @@ To: {args.receiver}
|
|||
Hello there,
|
||||
|
||||
This is a test message, generated from a template.
|
||||
If you didn't expect to see this message, please contact {args.me}.
|
||||
If you didn't expect to see this message, please contact {args.me}.{gtube}{body}
|
||||
|
||||
Greetings,
|
||||
|
||||
|
@ -57,11 +70,11 @@ Input arguments:
|
|||
."""
|
||||
|
||||
if not args.debug:
|
||||
for i in range(5, 0, -1):
|
||||
for i in range(3, 0, -1):
|
||||
print(f"Typing mail in {i}…")
|
||||
time.sleep(1)
|
||||
|
||||
command(f"HELO {args.helo}")
|
||||
command(f"EHLO {args.helo}")
|
||||
command(f"MAIL FROM: <{args.sender}>")
|
||||
command(f"RCPT TO: <{args.receiver}>")
|
||||
command("DATA")
|
||||
|
|
|
@ -11,9 +11,11 @@ import enum
|
|||
|
||||
# TODO Able to ignore extensions everywhere
|
||||
|
||||
class ArchiveType():
|
||||
suffix: str = ''
|
||||
dest_suffix: str = ''
|
||||
|
||||
class ArchiveType:
|
||||
suffix: str = ""
|
||||
fullname: str = ""
|
||||
dest_suffix: str = ""
|
||||
mime: typing.Optional[str] = None
|
||||
header: typing.Optional[bytes] = None
|
||||
extract_cmd: typing.Optional[typing.List[str]] = None
|
||||
|
@ -24,7 +26,7 @@ class ArchiveType():
|
|||
self.log = logging.getLogger(self.__class__.__name__)
|
||||
|
||||
def dest_name(self, archive: str) -> str:
|
||||
return archive[:-len(self.suffix)] + self.dest_suffix
|
||||
return archive + self.dest_suffix
|
||||
|
||||
def fits(self, name_lower: str, mime: str, header: bytes) -> bool:
|
||||
if not name_lower.endswith(self.suffix):
|
||||
|
@ -55,81 +57,87 @@ class ArchiveType():
|
|||
r.check_returncode()
|
||||
if self.single_file:
|
||||
assert os.path.isfile(dest)
|
||||
os.unlink(archive)
|
||||
|
||||
|
||||
extract_fun: typing.Optional[typing.Callable[[str, str], None]] = None
|
||||
|
||||
|
||||
class ArchiveZip(ArchiveType):
|
||||
suffix = '.zip'
|
||||
mime = 'application/zip'
|
||||
extract_cmd = ['unzip']
|
||||
suffix = ".zip"
|
||||
mime = "application/zip"
|
||||
extract_cmd = ["unzip"]
|
||||
|
||||
|
||||
class Archive7z(ArchiveType):
|
||||
suffix = '.7z'
|
||||
mime = 'application/x-7z-compressed'
|
||||
extract_cmd = ['7z', 'x']
|
||||
suffix = ".7z"
|
||||
mime = "application/x-7z-compressed"
|
||||
extract_cmd = ["7z", "x"]
|
||||
|
||||
|
||||
class ArchiveRar(ArchiveType):
|
||||
suffix = '.rar'
|
||||
mime = 'application/x-rar'
|
||||
extract_cmd = ['unrar', 'x']
|
||||
suffix = ".rar"
|
||||
mime = "application/x-rar"
|
||||
extract_cmd = ["unrar", "x"]
|
||||
|
||||
|
||||
class ArchiveTar(ArchiveType):
|
||||
suffix = '.tar'
|
||||
mime = 'application/x-tar'
|
||||
extract_cmd = ['tar', '--extract', '--file']
|
||||
suffix = ".tar"
|
||||
mime = "application/x-tar"
|
||||
extract_cmd = ["tar", "--extract", "--file"]
|
||||
|
||||
|
||||
class ArchiveTarGz(ArchiveType):
|
||||
suffix = '.tar.gz'
|
||||
mime = 'application/gzip'
|
||||
extract_cmd = ['tar', '--extract', '--gzip', '--file']
|
||||
suffix = ".tar.gz"
|
||||
mime = "application/gzip"
|
||||
extract_cmd = ["tar", "--extract", "--gzip", "--file"]
|
||||
|
||||
|
||||
class ArchiveTarXz(ArchiveType):
|
||||
suffix = '.tar.xz'
|
||||
mime = 'application/x-xz'
|
||||
extract_cmd = ['tar', '--extract', '--xz', '--file']
|
||||
suffix = ".tar.xz"
|
||||
mime = "application/x-xz"
|
||||
extract_cmd = ["tar", "--extract", "--xz", "--file"]
|
||||
|
||||
|
||||
class ArchiveGzip(ArchiveType):
|
||||
suffix = '.gz'
|
||||
mime = 'application/gzip'
|
||||
suffix = ".gz"
|
||||
mime = "application/gzip"
|
||||
single_file = True
|
||||
extract_cmd = ['gunzip']
|
||||
extract_cmd = ["gunzip"]
|
||||
|
||||
class TreeExtractor():
|
||||
|
||||
class TreeExtractor:
|
||||
ARCHIVE_TYPES: typing.List[ArchiveType] = [
|
||||
ArchiveZip(),
|
||||
Archive7z(),
|
||||
ArchiveRar(),
|
||||
ArchiveTar(),
|
||||
ArchiveTarGz(),
|
||||
ArchiveTarXz(),
|
||||
ArchiveGzip(),
|
||||
ArchiveZip(),
|
||||
Archive7z(),
|
||||
ArchiveRar(),
|
||||
ArchiveTar(),
|
||||
ArchiveTarGz(),
|
||||
ArchiveTarXz(),
|
||||
ArchiveGzip(),
|
||||
]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.log = logging.getLogger('TreeExtractor')
|
||||
self.extensions = set()
|
||||
self.log = logging.getLogger("TreeExtractor")
|
||||
self.suffixes = set()
|
||||
for archive_type in self.ARCHIVE_TYPES:
|
||||
suffixes = archive_type.suffix.split('.')
|
||||
self.extensions.add('.' + suffixes[-1])
|
||||
self.suffixes.add(archive_type.suffix)
|
||||
|
||||
|
||||
def extract_tree(self, directory: str = '.') -> None:
|
||||
def extract_tree(self, directory: str = ".") -> None:
|
||||
for root, dirs, files in os.walk(directory):
|
||||
real_root = os.path.realpath(root)
|
||||
for name in files:
|
||||
self.log.debug("Handling '%s' '%s'", real_root, name)
|
||||
|
||||
# Initial filtering with extensions
|
||||
extension = os.path.splitext(name)[1].lower()
|
||||
if extension not in self.extensions:
|
||||
self.log.debug("Extension not matched: %s", name)
|
||||
# Initial filtering with suffix
|
||||
name_lower = name.lower()
|
||||
for suffix in self.suffixes:
|
||||
if name_lower.endswith(suffix):
|
||||
break
|
||||
else:
|
||||
self.log.debug("Suffix not matched: %s", name)
|
||||
continue
|
||||
|
||||
name_lower = name.lower()
|
||||
filepath = os.path.join(real_root, name)
|
||||
with open(filepath, 'rb') as filedesc:
|
||||
with open(filepath, "rb") as filedesc:
|
||||
header = filedesc.read(1024)
|
||||
mime = magic.from_buffer(header, mime=True)
|
||||
|
||||
|
@ -144,19 +152,24 @@ class TreeExtractor():
|
|||
|
||||
dest_name = archive_type.dest_name(name)
|
||||
dest = os.path.join(real_root, dest_name)
|
||||
dest_tmp = dest + ".tmp"
|
||||
try:
|
||||
archive_type.extract(filepath, dest)
|
||||
archive_type.extract(filepath, dest_tmp)
|
||||
except BaseException as e:
|
||||
# TODO Parameters stop on error
|
||||
self.log.error(e, exc_info=True)
|
||||
else:
|
||||
os.unlink(filepath)
|
||||
os.rename(dest_tmp, dest)
|
||||
|
||||
if os.path.isdir(dest):
|
||||
self.extract_tree(dest)
|
||||
|
||||
def main(self) -> None:
|
||||
directory = sys.argv[1] if len(sys.argv) > 1 else '.'
|
||||
directory = sys.argv[1] if len(sys.argv) > 1 else "."
|
||||
self.extract_tree(directory)
|
||||
|
||||
if __name__ == '__main__':
|
||||
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
|
||||
|
||||
if __name__ == "__main__":
|
||||
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s")
|
||||
TreeExtractor().main()
|
||||
|
|
|
@ -15,7 +15,7 @@ log = logging.getLogger()
|
|||
|
||||
# Constants
|
||||
SOURCE_FOLDER = os.path.join(os.path.expanduser("~"), "Musiques")
|
||||
OUTPUT_FOLDER = os.path.join(os.path.expanduser("~"), ".musicCompressed")
|
||||
OUTPUT_FOLDER = os.path.join(os.path.expanduser("~"), ".MusiqueCompressed")
|
||||
CONVERSIONS = {"flac": "opus"}
|
||||
FORBIDDEN_EXTENSIONS = ["jpg", "png", "pdf", "ffs_db"]
|
||||
FORGIVEN_FILENAMES = ["cover.jpg", "front.jpg", "folder.jpg",
|
||||
|
@ -24,6 +24,7 @@ IGNORED_EMPTY_FOLDER = [".stfolder"]
|
|||
RESTRICT_CHARACTERS = '[\0\\/:*"<>|]' # FAT32, NTFS
|
||||
# RESTRICT_CHARACTERS = '[:/]' # HFS, HFS+
|
||||
# RESTRICT_CHARACTERS = '[\0/]' # ext2-4, linux-based?
|
||||
act = True
|
||||
|
||||
# TODO FEAT Make the directory structure the same as the base one and
|
||||
# remove IGNORED_EMPTY_FOLDER variable
|
||||
|
@ -96,13 +97,14 @@ for sourceFile in remainingConversions:
|
|||
# Creating folder if it doesn't exists
|
||||
fullOutputFile = os.path.join(OUTPUT_FOLDER, outputFile)
|
||||
fullOutputDir = os.path.dirname(fullOutputFile)
|
||||
os.makedirs(fullOutputDir, exist_ok=True)
|
||||
if act:
|
||||
os.makedirs(fullOutputDir, exist_ok=True)
|
||||
|
||||
# Converting
|
||||
fullSourceFile = os.path.join(SOURCE_FOLDER, sourceFile)
|
||||
if sourceFile == outputFile:
|
||||
log.debug('%s → %s', fullSourceFile, fullOutputFile)
|
||||
if os.path.isfile(fullOutputFile):
|
||||
if act and os.path.isfile(fullOutputFile):
|
||||
os.remove(fullOutputFile)
|
||||
os.link(fullSourceFile, fullOutputFile)
|
||||
else:
|
||||
|
@ -112,7 +114,8 @@ log.info("Removing extra files")
|
|||
for extraFile in extraFiles:
|
||||
fullExtraFile = os.path.join(OUTPUT_FOLDER, extraFile)
|
||||
log.debug('× %s', fullExtraFile)
|
||||
os.remove(fullExtraFile)
|
||||
if act:
|
||||
os.remove(fullExtraFile)
|
||||
|
||||
log.info("Listing files that will be converted")
|
||||
for fullSourceFile, fullOutputFile in conversions:
|
||||
|
@ -123,11 +126,14 @@ for fullSourceFile, fullOutputFile in progressbar.progressbar(conversions):
|
|||
cmd = ["ffmpeg", "-y", "-i", fullSourceFile, "-c:a", "libopus",
|
||||
"-movflags", "+faststart", "-b:a", "128k", "-vbr", "on",
|
||||
"-compression_level", "10", fullOutputFile]
|
||||
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
if act:
|
||||
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
else:
|
||||
print(cmd)
|
||||
|
||||
# Removing empty dirs
|
||||
for root, dirs, files in os.walk(OUTPUT_FOLDER):
|
||||
if not dirs and not files:
|
||||
dirBasename = os.path.basename(root)
|
||||
if dirBasename not in IGNORED_EMPTY_FOLDER:
|
||||
if act and dirBasename not in IGNORED_EMPTY_FOLDER:
|
||||
os.rmdir(root)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue