# Imports import os import json import logging import sys import threading import time import zipfile import git from flask import Flask, request # Config vars runPath = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(runPath, "..")) import conf # Logging logging.basicConfig(level=logging.INFO, format='%(levelname)-7s:%(message)s') logging.getLogger("Webhook") # Vars app = Flask(__name__) repo = git.Repo(conf.ese_location) # Helper functions # Threaded hooks def update_self(): time.sleep(0.5) # sleep to let the server reply git.Repo(runPath).remote().pull() logging.info("Pulled the update. Webhook should restart soon") def update_ese(): # Update local git if not pull_repo(): logging.error("Could not pull update the ESE repo") return "ERROR" # Blocking issue # Write songlist to repo if not make_song_list(): logging.error("Could not write songlist") # Not a blocking issue, so we can continue # zip up the repo into chunks if not package(): logging.error("Could not finish updating zip files") # Not blocking # Actions def pull_repo(): try: logging.debug("Pulling ESE repo") repo.remote().pull() logging.info("Local ESE repo updated") return True except Exception as e: print(e) return False def get_folder_struct(): root = repo.working_dir rel = len(root)+1 dirs = sorted([x[0][rel:] for x in os.walk(root) if not x[0][rel:].startswith('.git') and x[0] != root]) return dirs def make_song_list(): root = repo.working_dir rel = len(root)+1 data = "" for path in get_folder_struct(): level = path.count(os.sep) if level == 0: data+=f"\n[{path}]" else: indent = ' ' * 4 * (level) data += f"\n{indent}-{os.path.basename(path)}" try: logging.info("Writing songlist to repo") open(os.path.join(root, "songlist.txt"), "w").write(data.strip()) return True except Exception as e: print(e) return False def make_zip(dirs, location): logging.info(f"writing {location}") with zipfile.ZipFile(location, 'w') as chunk: for dir in dirs: dir = os.path.join(repo.working_dir, dir) for file in [os.path.join(dir, f) for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]: arcname = file.replace(repo.working_dir, "") chunk.write(file, arcname) def package(): folder = get_folder_struct() # Split per genre groups = {group: [dir for dir in folder if dir.startswith(group) and dir != group] for group in folder if group.count(os.sep) == 0} # Split in chunks size = conf.songs_per_zip groups = {key: [val[i:i+size] for i in range(0, len(val), size)] for key, val in groups.items()} # zip the individual chunks for group, dirs in groups.items(): for i, chunk in enumerate(dirs): outfile = os.path.join(conf.zip_location, f"{group}-{i+1}.zip") make_zip(chunk, outfile) # Web routes @app.route(conf.webhook_ese,methods=['POST']) def webhook_ese(): data = json.loads(request.data) authors = [a.get('author', {}).get('name') for a in data.get('commits', [])] authors = " & ".join(set([a for a in authors if a])) pusher = data.get('pusher', {}).get('login', '[UNKNOWN]') logging.info(f"Push made by {pusher}. Edits made by {authors}") threading.Thread(target = update_ese).start() return "OK" @app.route(conf.webhook_self, methods=['POST']) def webhook_update(): logging.info("Webhook repo was updated. Pulling updates") threading.Thread(target = update_self).start() return "OK" if __name__ == '__main__': logging.info("Webhook (re)started") app.run(host=conf.host, port=conf.port, debug=True) logging.info("Webhook stopped")