Chris Pomeroy
2023-11-30 1bc382c0c65a3721982861d16abdeeecd651320e
aaxConvert.py
@@ -1,24 +1,26 @@
#!/usr/local/bin/python -u
#!/usr/bin/env -S python -u
import argparse
import os
import glob
import subprocess
import shlex
import json
import re
import requests
import unicodedata
from querysubsonic import findalbumbyname
from time import sleep
import sys
from queryAudiobookServer import findalbumbyname
# arguments
# activation_key, file name, codec(default to mp3)
parser = argparse.ArgumentParser()
parser.add_argument("-s","--single", help="Use this option to create a single file. This is false by default", action="store_true")
parser.add_argument("-d","--dpath", help="Use this to set the destination path. Otherwise I will use the current directory")
parser.add_argument("-v", "--verbose", help="Send output to stdout", action="store_true")
parser.add_argument("filename", help="Filename to convert, or directory to look in")
parser.add_argument("-s", "--single", help="Use this option to create a single\
                     file. This is false by default", action="store_true")
parser.add_argument("-d", "--dpath", help="Use this to set the destination\
                    path. Otherwise I will use the current directory")
parser.add_argument("-v", "--verbose", help="Send output to stdout",
                    action="store_true")
parser.add_argument("filename", help="Filename to convert, or directory to\
                     look in")
args = parser.parse_args()
@@ -44,129 +46,146 @@
def getmetadata(aaxfile):
    ret = subprocess.check_output(["ffprobe", "-v", "info", "-hide_banner", "-show_format", "-show_chapters", "-print_format", "json", os.path.abspath(aaxfile)])
    mdata = json.loads(ret)
    # Returns the metadata from an aax file
    ret = subprocess.run(["ffprobe", "-v", "info", "-hide_banner",
                          "-show_format", "-show_chapters",
                          "-print_format", "json",
                          os.path.abspath(aaxfile)], capture_output=True)
    mdata = json.loads(ret.stdout)
    aret = ret.stderr.decode().split('\n')[0]
    mdata["checksum"] = aret.split()[-1]
    return mdata
def getmetabitrate():
    # Return the bitrate of the media
    bit_rate = metadata['format']['bit_rate']
    return bit_rate[:2]
def getmetacopyright():
    copyright = unicodedata.normalize('NFKD', metadata['format']['tags']['copyright']).encode('ascii','ignore')
    # Return normalized copyright data
    copyright = normalize_data(metadata['format']['tags']['copyright'])
    return copyright
def getmetadatatags(key):
# get specific data
    # get specific data
    tag = metadata['format']['tags'][key]
    return tag
    return " ".join(tag.split())
def normalize_data(data):
    # Return a normalized title
    data = data.replace(" ", "_")
    pattern = re.compile('\W')
    return re.sub(pattern, '', data)
def reencode(aaxfile, outpath):
# decrypt and reencode to mp3
    command = ("ffmpeg -loglevel error {} -activation_bytes {} -i {} -vn -codec:a libmp3lame -ab {}k -map_metadata -1 "
               "-metadata \"title={}\" -metadata 'artist={}' -metadata 'album_artist={}' -metadata \"album={}\" -metadata 'date={}' "
               "-metadata track=1/1 -metadata 'genre={}' -metadata 'copyright={}' \"{}\" " ).format(stats, act_byte,aaxfile,getmetabitrate(),
                                                                                           getmetadatatags('title'), getmetadatatags('artist'),
                                                                                           getmetadatatags('album_artist'), getmetadatatags('album'),
                                                                                           getmetadatatags('date'), getmetadatatags('genre'),
                                                                                           getmetacopyright(),outpath)
    # decrypt and reencode to mp3
    command = (
        "ffmpeg -loglevel error {} -activation_bytes {} -i"
        " {} -vn -codec:a libmp3lame -ab {}k -map_metadata -1"
        "-metadata \"title={}\" -metadata 'artist={}' -metadata"
        " 'album_artist={}' -metadata \"album={}\" -metadata 'date={}' "
        "-metadata track=1/1 -metadata 'genre={}' -metadata "
        "'copyright={}' \"{}\" ").format(
            stats, act_byte, aaxfile, getmetabitrate(),
            getmetadatatags('title'), getmetadatatags('artist'),
            getmetadatatags('album_artist'), getmetadatatags('album'),
            getmetadatatags('date'), getmetadatatags('genre'),
            getmetacopyright(), outpath)
    if args.verbose:
        print(command)
        process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print(output.strip())
        rc = process.poll()
        process = subprocess.run(command, shell=True, capture_output=True)
        # while True:
        #     output = process.stdout.readline()
        #     if output == '' and process.poll() is not None:
        #         break
        #     if output:
        #         print(output.strip())
        rc = process.stdout
        return rc
    else:
        process = subprocess.call(shlex.split(command))
    return
        process = subprocess.run(command, shell=True)
    return
def getchaptercount():
# Get the number of chapters
    # Get the number of chapters
    ccount = metadata['chapters']
    return len(ccount)
def getchaptermetadata(cid, key):
# get the Chapter metadata
    # get the Chapter metadata
    for i in metadata['chapters']:
        if i['id'] == cid:
            return i[key]
def movetochapters(path, outpath, chapter, title, start,end):
# Creating individual chapters
    outfile = "{}/Ch - {} {}.mp3".format(outpath, chapter, title)
def movetochapters(path, outpath, chapter, title, start, end):
    # Creating individual chapters
    outfile = "{}/Ch-{}_{}.mp3".format(
        outpath, chapter, title.replace(' ', '_')
    )
    command = "ffmpeg -loglevel error {} -i \"{}\" -ss {} -to {} -codec:a copy -metadata 'track={}' \"{}\"".format(stats, path,
                                                                                                               start, end,
                                                                                                               chapter, outfile)
                                                                                                                   start, end,
                                                                                                                   chapter, outfile)
    if args.verbose:
        print(command)
        process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print(output.strip())
        process = subprocess.run(command, shell=True, capture_output=True)
        # while True:
        #     output = process.stdout.readline()
        #     if output == '' and process.poll() is not None:
        #         break
        #     if output:
        #         print(output.strip())
        rc = process.poll()
        return rc
    else:
        process = subprocess.call(shlex.split(command))
        process = subprocess.run(command, shell=True)
    return
def getcoverart(path,outpath):
# Pull the coverart from the file
def getcoverart(path, outpath):
    # Pull the coverart from the file
    command = "ffmpeg -loglevel error -activation_bytes {} -i \"{}\" -an -codec:v copy \"{}/cover.jpg\"".format(act_byte,
                                                                                                               path, outpath)
                                                                                                                path, outpath)
    if args.verbose:
        print(command)
    process = subprocess.call(shlex.split(command))
        subprocess.run(command, shell=True)
    return
def filechecksum(aaxfile):
#The the hex checksum from the file
    ret = subprocess.Popen(["ffprobe", "-v", "info", "-hide_banner", os.path.abspath(aaxfile)], stderr=subprocess.PIPE)
    grep = subprocess.Popen(["grep", "checksum"], stdin=ret.stderr, stdout=subprocess.PIPE)
    awk = subprocess.Popen(["awk", " { print $8 } "], stdin=grep.stdout, stdout=subprocess.PIPE)
    hashsum,out = awk.communicate()
    hashsum = str(hashsum).strip('\n')
    return hashsum
def getcorrectkey(aaxfile):
#request the key for the checksum
    hex = filechecksum(aaxfile)
    payload = hex
    recovery = 3
    while recovery != 0:
      r = requests.post('http://prod-faas-gw.darkurthe.net:8080/function/checkkey', payload, verify=False, timeout=None)
      if r.status_code == 200:
          key = r.text
          recovery = 0
          return key
      else:
          print('Checkkey function is down please wait')
          recovery = recovery - 1
          sleep(15)
def getcorrectkey():
    # request the key for the checksum
    try:
        r = requests.post('http://faas.darkurthe.net/function/checkkey',
                          metadata['checksum'], verify=False, timeout=None)
        return r.text.strip()
    except requests.exceptions.HTTPError as err:
        raise err
for rfile in glob.glob(args.filename):
    if rfile.find("aax") != -1 and os.path.isfile(rfile):
        metadata = getmetadata(rfile)
        album = getmetadatatags('album')
        #See if we got it already
        if (findalbumbyname(album) == False):
            artist = getmetadatatags('artist')
            title = getmetadatatags('title')
            act_byte = getcorrectkey(rfile)
def findalbumbyname_stub(album):
    return False
if args.filename.find("aax"):
    rfile = args.filename
    metadata = getmetadata(rfile)
    album = getmetadatatags('album')
    # See if we got it already
    if not findalbumbyname(album):
        artist = normalize_data(getmetadatatags('artist'))
        title = normalize_data(getmetadatatags('title'))
        act_byte = getcorrectkey()
        if act_byte is None or act_byte == '':
            sys.exit(f"Can't continue with this file {rfile}")
        else:
            ddir = "%s/%s/%s" % (path, artist, title)
            single_file_path = "/processing/%s.mp3" % (title)
            if not os.path.exists(ddir):
@@ -176,15 +195,15 @@
            if mode == 'chapter':
                chapter = 0
                numchapters = getchaptercount()
                while (numchapters > 0 ):
                while (numchapters > 0):
                    cstart = getchaptermetadata(chapter, 'start_time')
                    cend = getchaptermetadata(chapter, 'end_time')
                    chapter += 1
                    numchapters -= 1
                    schap = str(chapter).zfill(2)
                    movetochapters(single_file_path, ddir, schap, title, cstart,cend)
                    movetochapters(single_file_path, ddir, schap, title,
                                   cstart, cend)
                os.remove(single_file_path)
            getcoverart(rfile, ddir)
        else:
            print('We have that book already')
    else:
        print('We have that book already')