Created
April 8, 2026 20:48
-
-
Save chhaugen/490a3902f67b35a8c5b430e70ecc0507 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import requests | |
| import os | |
| import re | |
| download_folder = r"<lokal mappe sti>" | |
| os.makedirs(download_folder, exist_ok=True) | |
| # F12 på apex, finn api-forespørselen som ligner, bytt ut leilighetsnummeret. | |
| # I Request headers feltet, finn cookies og lim det inn under også. | |
| root_folder_url = "https://api.apexapp.io/project/1899/apartment/<ditt leilighetsnummer>/mom" | |
| headers = { | |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", | |
| "Accept": "application/json, text/plain, */*", | |
| "Accept-Language": "nb,no;q=0.9,en-US;q=0.8,en;q=0.7", | |
| "content-type": "application/json", | |
| "Origin": "https://portal.apexapp.io", | |
| "Referer": "https://portal.apexapp.io/", | |
| "Cookie": "<Dine cookies>", | |
| "Sec-Fetch-Dest": "empty", | |
| "Sec-Fetch-Mode": "cors", | |
| "Sec-Fetch-Site": "same-site", | |
| "Pragma": "no-cache", | |
| "Cache-Control": "no-cache", | |
| "TE": "trailers", | |
| } | |
| def sanitize_windows_filename(name: str, replacement: str = "_") -> str: | |
| # Replace invalid characters | |
| name = re.sub(r'[<>:"/\\|?*]', replacement, name) | |
| # Remove trailing spaces and dots | |
| name = name.rstrip(" .") | |
| # Handle reserved names (case-insensitive) | |
| reserved_names = { | |
| "CON", "PRN", "AUX", "NUL", | |
| *(f"COM{i}" for i in range(1, 10)), | |
| *(f"LPT{i}" for i in range(1, 10)), | |
| } | |
| if name.upper() in reserved_names: | |
| name = f"{name}{replacement}" | |
| # Prevent empty name | |
| if not name: | |
| name = "untitled" | |
| return name | |
| def download_file(file_object, local_folder_path): | |
| signed = file_object["signed"] | |
| download_url = signed["url"] | |
| local_file_path = local_folder_path + "/" + sanitize_windows_filename(file_object["name"]) | |
| respnse = requests.get(download_url) | |
| print(f"Downloading: {local_file_path}") | |
| with open(local_file_path, "wb") as local_file: | |
| local_file.write(respnse.content) | |
| print(f"Downloaded: {local_file_path}") | |
| def download_folder_recursivly(folder_object, parent_local_folder_path): | |
| local_folder_path = parent_local_folder_path + "/" + sanitize_windows_filename(folder_object["name"]) | |
| files = folder_object["Files"] | |
| folders = folder_object["Children"] | |
| if len(files) == 0 and len(folders) == 0: | |
| print(f"Empty folder: {local_folder_path}") | |
| return | |
| os.makedirs(local_folder_path, exist_ok=True) | |
| for file in files: | |
| download_file(file, local_folder_path) | |
| for folder in folders: | |
| folder_id = folder["id"] | |
| folder_url = root_folder_url + "/" + folder_id | |
| folder_response = requests.get(folder_url, headers=headers) | |
| child_folder_object = folder_response.json()["Entity"] | |
| download_folder_recursivly(child_folder_object, local_folder_path) | |
| root_folder_response = requests.get(root_folder_url, headers=headers) | |
| root_folder = root_folder_response.json()["Entity"] | |
| download_folder_recursivly(root_folder, download_folder) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment