# ================================================================ # AMPP Framelight X — Nested Prefix Folder Organizer # Production v3.3 — Delimiter: -- # # Examples: # "BMG--Videos--File.mp4" → BMG / Videos / (asset linked) # "NEWS--PKG--Clip1.mxf" → NEWS / PKG / (asset linked) # "IMG--4709.jpg" → IMG / (asset linked) # "No-Delimiter.mp4" → skipped # # v3.3 Fix: Properly URL-encode folder paths including special # characters (apostrophes, ampersands, etc.) in hierarchy lookups. # ================================================================ import json import urllib.parse PREFIX_DELIM = "--" asset_id = str(asset.Id) asset_name = str(job.AssetName) if PREFIX_DELIM not in asset_name: pass else: parts = asset_name.split(PREFIX_DELIM) if len(parts) < 2: pass else: folder_names = parts[:-1] parent_id = None current_path = "" for fname in folder_names: fname = fname.strip() if not fname: continue if current_path: current_path = current_path + "/" + fname else: current_path = fname folder_id = None try: # URL-encode the full path, preserving "/" as path separator encoded = urllib.parse.quote(current_path, safe="/") resp = httpClient.sendAsync( "GET", "api/v1/store/folder/folders/hierarchy?path=" + encoded ) hlist = resp["hierarchy:list"] if hlist and hlist.Count > 0: last = hlist[hlist.Count - 1] folder_id = str(last["folder:id"]) except: folder_id = None if not folder_id: create_body = json.dumps({"name:text": fname}) if parent_id: create_body = json.dumps({ "name:text": fname, "parentFolders:tags": [parent_id] }) try: fresp = httpClient.sendAsync( "POST", "api/v1/store/folder/folders", create_body ) folder_id = str(fresp["folder:id"]) except Exception as ex: raise Exception( "Failed to create folder '" + fname + "' in '" + current_path + "': " + str(ex) ) parent_id = folder_id if parent_id: link_body = json.dumps( {"folder:id": parent_id, "asset:id": asset_id}, separators=(',', ':') ) try: httpClient.sendAsync( "POST", "api/v1/store/folder/references", link_body ) except: pass