Buckets:
| #!/usr/bin/env python3 | |
| """ | |
| Cara Master Index Dataset Explorer CLI Tool | |
| Zero External Dependencies (Runs on standard Python 3.7+ across Windows, macOS, Linux). | |
| """ | |
| import sys | |
| import os | |
| import re | |
| import json | |
| import sqlite3 | |
| import argparse | |
| from urllib.parse import urlparse | |
| from collections import Counter | |
| # Dynamic discovery of catalog.db (100% portable & anonymous) | |
| DB_CANDIDATE_PATHS = [ | |
| "catalog.db", | |
| os.path.join(os.path.dirname(os.path.abspath(__file__)), "catalog.db"), | |
| "../catalog.db", | |
| ] | |
| COMMON_PLACEHOLDERS = [ | |
| "username", | |
| "<username>", | |
| "your_username", | |
| "yourname", | |
| "your_name", | |
| "handle", | |
| "<handle>", | |
| "artist", | |
| "<artist>" | |
| ] | |
| def find_database() -> str: | |
| """Auto-detects catalog.db location dynamically.""" | |
| for path in DB_CANDIDATE_PATHS: | |
| if os.path.exists(path) and os.path.getsize(path) > 1000000: | |
| return path | |
| return None | |
| def get_db_connection(): | |
| """Connects to catalog.db with clean error guidance if missing.""" | |
| db_path = find_database() | |
| if not db_path: | |
| print("\n" + "=" * 80) | |
| print("โ DATABASE NOT FOUND: 'catalog.db'") | |
| print("=" * 80) | |
| print("Please make sure 'catalog.db' is located in the same folder as this script!") | |
| print(f"Current working directory: {os.getcwd()}") | |
| print("=" * 80 + "\n") | |
| sys.exit(1) | |
| try: | |
| conn = sqlite3.connect(db_path) | |
| conn.row_factory = sqlite3.Row | |
| return conn | |
| except Exception as e: | |
| print(f"\nโ Error opening database: {e}\n") | |
| sys.exit(1) | |
| def sanitize_username(input_str: str) -> str: | |
| """Cleans artist handle input.""" | |
| if not input_str: | |
| return "" | |
| cleaned = input_str.strip().lstrip("<").rstrip(">").strip() | |
| if "cara.app" in cleaned or "http" in cleaned: | |
| path = urlparse(cleaned).path.strip("/") | |
| parts = path.split("/") | |
| if len(parts) > 0 and parts[0] not in ["post", "search", "explore"]: | |
| cleaned = parts[0] | |
| elif len(parts) > 1 and parts[0] == "user": | |
| cleaned = parts[1] | |
| return cleaned.lstrip("@").strip() | |
| def sanitize_post_id(input_str: str) -> str: | |
| """Cleans post input and extracts UUID.""" | |
| if not input_str: | |
| return "" | |
| cleaned = input_str.strip().lstrip("<").rstrip(">").strip() | |
| uuid_match = re.search(r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', cleaned) | |
| if uuid_match: | |
| return uuid_match.group(0).lower() | |
| if "/" in cleaned: | |
| cleaned = cleaned.split("/")[-1].split("?")[0] | |
| return cleaned.strip() | |
| def sanitize_art_query(input_str: str) -> str: | |
| """Extracts clean image hash / filename from CDN URL.""" | |
| if not input_str: | |
| return "" | |
| cleaned = input_str.strip().lstrip("<").rstrip(">").strip() | |
| if "/" in cleaned: | |
| cleaned = cleaned.split("/")[-1].split("?")[0] | |
| return cleaned.strip() | |
| def explore_user(username_raw: str, is_overview: bool = False): | |
| """ | |
| Explores all posts and artworks by an artist handle. | |
| - is_overview=True: Shows stats and clean list of posts without image URLs. | |
| - is_overview=False: Shows full breakdown with every master slide and thumbnail URL. | |
| """ | |
| username = sanitize_username(username_raw) | |
| if username.lower() in [p.lower() for p in COMMON_PLACEHOLDERS]: | |
| print("\n" + "=" * 80) | |
| print(f"๐ I doubt your account is named '{username}' โ did you forget to type your own name?") | |
| print("Example: python tool.py --user mayonnaisejar1446 --overview") | |
| print("=" * 80 + "\n") | |
| return | |
| if not username: | |
| print("\nโ ๏ธ Please specify an artist handle (e.g. 'python tool.py --user mayonnaisejar1446')\n") | |
| return | |
| conn = get_db_connection() | |
| cur = conn.cursor() | |
| # 1. Fetch Posts from artworks table | |
| cur.execute(""" | |
| SELECT post_id, cdn_url as cover_url, created_at | |
| FROM artworks | |
| WHERE author_slug = ? COLLATE NOCASE | |
| ORDER BY created_at DESC; | |
| """, (username,)) | |
| posts = cur.fetchall() | |
| if not posts: | |
| cur.execute("SELECT DISTINCT author_slug FROM master_artworks_12m WHERE author_slug = ? COLLATE NOCASE;", (username,)) | |
| found_slug = cur.fetchone() | |
| if not found_slug: | |
| print("\n" + "=" * 80) | |
| print(f"โ Artist '@{username}' was not found in the database.") | |
| print("Tip: Double-check the exact handle as it appears in the artist's Cara profile URL.") | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| return | |
| # 2. Fetch Master Artworks | |
| cur.execute(""" | |
| SELECT post_id, slide_number, title, cdn_url, width, height, created_at | |
| FROM master_artworks_12m | |
| WHERE author_slug = ? COLLATE NOCASE | |
| ORDER BY post_id, slide_number; | |
| """, (username,)) | |
| artworks = cur.fetchall() | |
| # 3. Fetch Post Metadata | |
| cur.execute(""" | |
| SELECT post_id, author_name, title, content, softwares, tags, created_at | |
| FROM post_metadata | |
| WHERE author_slug = ? COLLATE NOCASE; | |
| """, (username,)) | |
| meta_rows = {r["post_id"]: r for r in cur.fetchall()} | |
| post_artworks = {} | |
| for art in artworks: | |
| post_artworks.setdefault(art["post_id"], []).append(art) | |
| # Aggregate stats | |
| display_name = None | |
| all_softwares = [] | |
| all_tags = [] | |
| all_dates = [] | |
| for pid, meta in meta_rows.items(): | |
| if meta["author_name"] and not display_name: | |
| display_name = meta["author_name"] | |
| if meta["created_at"]: | |
| all_dates.append(meta["created_at"][:10]) | |
| try: | |
| sw = json.loads(meta["softwares"]) | |
| if isinstance(sw, list): | |
| all_softwares.extend(sw) | |
| except Exception: | |
| pass | |
| try: | |
| tg = json.loads(meta["tags"]) | |
| if isinstance(tg, list): | |
| all_tags.extend(tg) | |
| except Exception: | |
| pass | |
| top_software = [s for s, _ in Counter(all_softwares).most_common(5)] | |
| top_tags = [t for t, _ in Counter(all_tags).most_common(8)] | |
| date_range = f"{min(all_dates)} to {max(all_dates)}" if all_dates else "N/A" | |
| name_header = f"@{username}" + (f" ({display_name})" if display_name else "") | |
| print("\n" + "=" * 80) | |
| print(f"๐ค ARTIST SUMMARY: {name_header}") | |
| print("=" * 80) | |
| print(f"๐ Total Posts (Cover Thumbnails): {len(posts):,}") | |
| print(f"๐ผ๏ธ Total Master Artworks (Full-Res): {len(artworks):,}") | |
| if top_software: | |
| print(f"๐ป Primary Software: {', '.join(top_software)}") | |
| if top_tags: | |
| print(f"๐ท๏ธ Top Tags: {', '.join(top_tags)}") | |
| if all_dates: | |
| print(f"๐ Activity Span: {date_range}") | |
| print(f"๐ Profile Link: https://cara.app/{username}") | |
| print("=" * 80) | |
| if is_overview: | |
| print(f"๐ POSTS OVERVIEW ({len(posts)} posts): [Tip: Omit --overview to view all image links]") | |
| print("-" * 80) | |
| for idx, p in enumerate(posts, 1): | |
| pid = p["post_id"] | |
| arts = post_artworks.get(pid, []) | |
| meta = meta_rows.get(pid) | |
| title = "Untitled" | |
| if meta and meta["title"] and meta["title"].strip(): | |
| title = meta["title"].strip() | |
| elif arts and arts[0]["title"] and arts[0]["title"].strip(): | |
| title = arts[0]["title"].strip() | |
| date_str = p["created_at"][:10] if p["created_at"] else "Unknown" | |
| slides_info = f"{len(arts)} master slide(s)" if arts else "1 cover image" | |
| print(f"[{idx}] ๐ {title} ({date_str}) | {slides_info}") | |
| print(f" ๐ https://cara.app/post/{pid}") | |
| else: | |
| print("๐ DETAILED POSTS & ARTWORK LINKS:") | |
| print("-" * 80) | |
| for idx, p in enumerate(posts, 1): | |
| pid = p["post_id"] | |
| arts = post_artworks.get(pid, []) | |
| meta = meta_rows.get(pid) | |
| title = "Untitled" | |
| if meta and meta["title"] and meta["title"].strip(): | |
| title = meta["title"].strip() | |
| elif arts and arts[0]["title"] and arts[0]["title"].strip(): | |
| title = arts[0]["title"].strip() | |
| date_str = p["created_at"][:10] if p["created_at"] else "Unknown" | |
| print(f"\n[{idx}] ๐ {title} ({date_str})") | |
| print(f" ๐ Post: https://cara.app/post/{pid}") | |
| if p["cover_url"]: | |
| print(f" ๐ผ๏ธ Thumbnail: {p['cover_url']}") | |
| if arts: | |
| for a in arts: | |
| res = f"[{a['width']}x{a['height']}]" if a['width'] and a['height'] else "[Full-Res]" | |
| print(f" โข Slide {a['slide_number']} {res}: {a['cdn_url']}") | |
| print("\n" + "=" * 80 + "\n") | |
| conn.close() | |
| def explore_post(post_raw: str): | |
| """Explores a post by URL or UUID.""" | |
| post_id = sanitize_post_id(post_raw) | |
| if not post_id or post_id.lower() in ["post url", "<post url>", "post_id", "<post_id>"]: | |
| print("\n" + "=" * 80) | |
| print("๐ Did you copy '<Post url>' literally from the README?") | |
| print("Example: python tool.py --post https://cara.app/post/5aac58cb-c33f-4622-9199-d6531e8f47f8") | |
| print("=" * 80 + "\n") | |
| return | |
| conn = get_db_connection() | |
| cur = conn.cursor() | |
| cur.execute(""" | |
| SELECT id, post_id, author_slug, slide_number, title, cdn_url, width, height, created_at | |
| FROM master_artworks_12m | |
| WHERE post_id = ? | |
| ORDER BY slide_number; | |
| """, (post_id,)) | |
| slides = cur.fetchall() | |
| cur.execute("SELECT cdn_url FROM artworks WHERE post_id = ?;", (post_id,)) | |
| cover_row = cur.fetchone() | |
| cover_url = cover_row["cdn_url"] if cover_row else None | |
| if not slides and not cover_url: | |
| print("\n" + "=" * 80) | |
| print(f"โ Post ID '{post_id}' was not found in the master catalog.") | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| return | |
| cur.execute("SELECT * FROM post_metadata WHERE post_id = ?;", (post_id,)) | |
| meta = cur.fetchone() | |
| author = slides[0]["author_slug"] if slides else (meta["author_slug"] if meta else "unknown") | |
| title = (slides[0]["title"] if slides and slides[0]["title"] else None) or (meta["title"] if meta and meta["title"] else "Untitled") | |
| print("\n" + "=" * 80) | |
| print(f"๐ POST ID: {post_id}") | |
| print(f"๐ค ARTIST: @{author} (https://cara.app/{author})") | |
| print(f"๐จ TITLE: {title}") | |
| print(f"๐ WEB LINK: https://cara.app/post/{post_id}") | |
| if cover_url: | |
| print(f"๐ผ๏ธ THUMBNAIL: {cover_url}") | |
| if meta: | |
| try: | |
| tags = json.loads(meta["tags"]) | |
| softwares = json.loads(meta["softwares"]) | |
| if softwares: | |
| print(f"๐ป SOFTWARE: {softwares}") | |
| if tags: | |
| print(f"๐ท๏ธ TAGS: {tags}") | |
| if meta["content"]: | |
| print(f"\n๐ POST BODY:\n{meta['content'].strip()}") | |
| except Exception: | |
| pass | |
| if slides: | |
| print("\n๐ผ๏ธ MASTER ARTWORKS (" + str(len(slides)) + " slide(s)):") | |
| print("-" * 80) | |
| for s in slides: | |
| res = f"{s['width']}x{s['height']}" if s['width'] and s['height'] else "Full-Res" | |
| print(f" โข Slide {s['slide_number']} [{res}]: {s['cdn_url']}") | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| def explore_artwork(art_raw: str): | |
| """Reverse traces an artwork CDN link or image filename back to its post and creator.""" | |
| raw_clean = art_raw.strip().lstrip("<").rstrip(">").strip() | |
| art_hash = sanitize_art_query(raw_clean) | |
| if not art_hash or art_hash.lower() in ["cdn url", "<cdn url>", "cdn_url", "<cdn_url>"]: | |
| print("\n" + "=" * 80) | |
| print("๐ Did you copy '<CDN url>' literally from the README?") | |
| print("Example: python tool.py --art otawrou-8L8tjCPtnNl1TStnB3Psu-0000-00091.gif") | |
| print("=" * 80 + "\n") | |
| return | |
| conn = get_db_connection() | |
| cur = conn.cursor() | |
| # Fast Path 1: Exact URL match | |
| cur.execute("SELECT post_id, author_slug, slide_number, title, cdn_url, width, height, created_at FROM master_artworks_12m WHERE cdn_url = ?;", (raw_clean,)) | |
| match = cur.fetchone() | |
| # Fast Path 2: Exact Filename match | |
| if not match: | |
| cur.execute("SELECT post_id, author_slug, slide_number, title, cdn_url, width, height, created_at FROM master_artworks_12m WHERE cdn_url LIKE ?;", (f"https://cdn.cara.app/production/posts/%/{art_hash}",)) | |
| match = cur.fetchone() | |
| # Fallback Path 3: Substring search | |
| if not match: | |
| cur.execute("SELECT post_id, author_slug, slide_number, title, cdn_url, width, height, created_at FROM master_artworks_12m WHERE cdn_url LIKE ?;", (f"%{art_hash}%",)) | |
| match = cur.fetchone() | |
| # Fallback Path 4: Check cover thumbnails in artworks | |
| if not match: | |
| cur.execute("SELECT post_id, author_slug, cdn_url, created_at FROM artworks WHERE cdn_url LIKE ?;", (f"%{art_hash}%",)) | |
| cover_match = cur.fetchone() | |
| if cover_match: | |
| print("\n" + "=" * 80) | |
| print("๐ REVERSE ARTWORK TRACER (Feed Cover Thumbnail)") | |
| print("=" * 80) | |
| print(f"๐ผ๏ธ Thumbnail: {cover_match['cdn_url']}") | |
| print(f"๐ Post ID: {cover_match['post_id']}") | |
| print(f"๐ค Creator: @{cover_match['author_slug']} (https://cara.app/{cover_match['author_slug']})") | |
| print(f"๐ Direct Web: https://cara.app/post/{cover_match['post_id']}") | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| return | |
| if not match: | |
| print("\n" + "=" * 80) | |
| print(f"โ Artwork image '{art_hash}' was not found in the database.") | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| return | |
| pid = match["post_id"] | |
| cur.execute("SELECT * FROM post_metadata WHERE post_id = ?;", (pid,)) | |
| meta = cur.fetchone() | |
| print("\n" + "=" * 80) | |
| print("๐ REVERSE ARTWORK TRACER (Master Full-Res Artwork)") | |
| print("=" * 80) | |
| print(f"๐ผ๏ธ Image Link: {match['cdn_url']}") | |
| print(f"๐ Resolution: {match['width']}x{match['height']} (Slide {match['slide_number']})") | |
| print(f"๐ Post ID: {match['post_id']}") | |
| print(f"๐ค Creator: @{match['author_slug']} (https://cara.app/{match['author_slug']})") | |
| print(f"๐จ Title: {match['title'] or 'Untitled'}") | |
| print(f"๐ Upload Date: {match['created_at']}") | |
| print(f"๐ Direct Web: https://cara.app/post/{match['post_id']}") | |
| if meta: | |
| try: | |
| tags = json.loads(meta["tags"]) | |
| if tags: | |
| print(f"๐ท๏ธ Post Tags: {tags[:6]}") | |
| except Exception: | |
| pass | |
| print("=" * 80 + "\n") | |
| conn.close() | |
| def interactive_menu(): | |
| """Interactive CLI menu when run with zero arguments.""" | |
| print("\n" + "=" * 80) | |
| print("๐จ CARA MASTER INDEX DATASET EXPLORER") | |
| print("=" * 80) | |
| print("Choose an option:") | |
| print(" 1. Look up an Artist / Username (Summary Overview)") | |
| print(" 2. Look up an Artist / Username (Full Artwork Links)") | |
| print(" 3. Look up a Post Link / Post UUID") | |
| print(" 4. Reverse Trace an Artwork CDN Image URL") | |
| print(" 5. Exit") | |
| print("=" * 80) | |
| choice = input("\nEnter choice (1-5): ").strip() | |
| if choice == "1": | |
| user_input = input("Enter username or profile URL: ").strip() | |
| explore_user(user_input, is_overview=True) | |
| elif choice == "2": | |
| user_input = input("Enter username or profile URL: ").strip() | |
| explore_user(user_input, is_overview=False) | |
| elif choice == "3": | |
| post_input = input("Enter post URL or UUID: ").strip() | |
| explore_post(post_input) | |
| elif choice == "4": | |
| art_input = input("Enter CDN URL or image filename: ").strip() | |
| explore_artwork(art_input) | |
| elif choice == "5" or choice.lower() in ["q", "exit", "quit"]: | |
| print("Goodbye!") | |
| sys.exit(0) | |
| else: | |
| print("Invalid choice. Exiting.") | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Cara Master Index Dataset CLI Tool") | |
| parser.add_argument("--user", help="Query creator handle (e.g. --user alex123)") | |
| parser.add_argument("--overview", action="store_true", help="Clean summary overview (disables showing image links)") | |
| parser.add_argument("--post", help="Query post metadata, lore & gallery (e.g. --post https://cara.app/post/...)") | |
| parser.add_argument("--art", help="Reverse trace an image CDN link back to creator & post") | |
| if len(sys.argv) == 1: | |
| interactive_menu() | |
| return | |
| args = parser.parse_args() | |
| if args.user: | |
| explore_user(args.user, is_overview=args.overview) | |
| elif args.post: | |
| explore_post(args.post) | |
| elif args.art: | |
| explore_artwork(args.art) | |
| else: | |
| interactive_menu() | |
| if __name__ == "__main__": | |
| main() | |
Xet Storage Details
- Size:
- 17.1 kB
- Xet hash:
- f92cec9252333be447b234c5fa04483cf01fb215466264e90aadeb24317a3feb
ยท
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.