Chris Pomeroy
9 days ago 2bca657babf8bec3f9cee673c92eb21f68a68a68
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,146 +44,185 @@
    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):
    ret = subprocess.check_output(["ffprobe", "-v", "info", "-hide_banner", "-show_format", "-show_chapters", "-print_format", "json", os.path.abspath(aaxfile)])
    mdata = json.loads(ret)
    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
    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
    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)
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):
    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.strip('\n')
    return hashsum
def getcorrectkey(aaxfile):
    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(5)
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)
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 (findalbumbyname(album) == False):
            artist = getmetadatatags('artist')
            title = getmetadatatags('title')
            act_byte = getcorrectkey(rfile)
            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)
            reencode(rfile, single_file_path)
            if mode == 'chapter':
                chapter = 0
                numchapters = getchaptercount()
                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)
                os.remove(single_file_path)
            getcoverart(rfile, ddir)
        # 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 == '':
                sendtodiscord(rfile)
                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):
                    os.makedirs(ddir)
                print(ddir)
                reencode(rfile, single_file_path)
                if mode == 'chapter':
                    chapter = 0
                    numchapters = getchaptercount()
                    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)
                    os.remove(single_file_path)
                getcoverart(rfile, ddir)
        else:
            print('We have that book already')