Chris Pomeroy
2023-12-03 498dcd887df4a6affd800b78bd2ccae3bb52fb19
aaxConvert.py
@@ -1,24 +1,25 @@
#!/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()
@@ -43,132 +44,169 @@
    stats = "-nostats"
def sendtodiscord(audiofile):
    webhookurl = "https://discord.com/api/webhooks/764667082272145418/vorf2JdFG47WAmQP3yZhgHH12wW_qUXG0bS0SG8INLYVwU0HcDFajq9doaDgi_hnI00-"  # noqa E501
    data = {
        "content": f"There was a problem with file{audiofile}",
        "username": "Captain Audio",
        }
    with requests.Session() as r:
        resp = r.post(webhookurl, json=data)
        if resp.status_code == 204:
            return True
def getmetadata(aaxfile):
# 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
    # Returns the metadata from an aax file
    try:
        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
    except Exception as err:
        sys.stderr.write("Error processing metadata: {}\n".format(err))
        return "None"
def getmetabitrate():
#Return the bitrate of the media
    # Return the bitrate of the media
    bit_rate = metadata['format']['bit_rate']
    return bit_rate[:2]
def getmetacopyright():
# Return normalized copyright data
    copyright = unicodedata.normalize('NFKD', metadata['format']['tags']['copyright']).encode('ascii','ignore')
    return copyright.decode()
    # 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
    pattern = re.compile('[^\p{Latin}]', u'', data)
    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.replace(' ', '_'))
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 = hashsum.decode().strip('\n')
#     return hashsum
def getcorrectkey():
#request the key for the checksum
    # request the key for the checksum
    try:
        r = requests.post('http://prod-faas-gw.darkurthe.net:8080/function/checkkey', metadata['checksum'], verify=False, timeout=None)
        return r.text
        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 error
        return None
        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')
def findalbumbyname_stub(album):
    return False
if args.filename.find("aax"):
    rfile = args.filename
    metadata = getmetadata(rfile)
    if metadata == "None":
        sendtodiscord(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 == None:
                sys.exit("Can't continue with this file {rfile}")
            if act_byte is None or act_byte == '':
                sendtodiscord(rfile)
                sys.exit(f"Can't continue with this file {rfile}")
            else:
                ddir = "%s/%s/%s" % (path, artist.replace(' ', '_'), title.replace(' ', '_'))
                single_file_path = "/processing/%s.mp3" % (title.replace(' ','_'))
                ddir = "%s/%s/%s" % (path, artist, title)
                single_file_path = "/processing/%s.mp3" % (title)
                if not os.path.exists(ddir):
                    os.makedirs(ddir)
                print(ddir)
@@ -176,15 +214,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')