""" Dynamic Link Page Manager utilities """ import uuid import json import os from datetime import datetime from .url_shortener import URLShortener # Data storage directory DATA_DIR = 'data' LINK_PAGES_FILE = os.path.join(DATA_DIR, 'link_pages.json') # Ensure data directory exists os.makedirs(DATA_DIR, exist_ok=True) class LinkPageManager: def __init__(self): self.url_shortener = URLShortener() self.link_pages_db = self._load_link_pages() def _load_link_pages(self): """Load link pages from JSON file""" try: if os.path.exists(LINK_PAGES_FILE): with open(LINK_PAGES_FILE, 'r', encoding='utf-8') as f: return json.load(f) return {} except Exception as e: print(f"Error loading link pages: {e}") return {} def _save_link_pages(self): """Save link pages to JSON file""" try: with open(LINK_PAGES_FILE, 'w', encoding='utf-8') as f: json.dump(self.link_pages_db, f, indent=2, ensure_ascii=False) except Exception as e: print(f"Error saving link pages: {e}") def create_link_page(self, title="My Links", description="Collection of useful links"): """Create a new dynamic link page""" page_id = str(uuid.uuid4()) page_data = { 'id': page_id, 'title': title, 'description': description, 'links': [], 'created_at': datetime.now().isoformat(), 'updated_at': datetime.now().isoformat(), 'view_count': 0, 'short_url': None, # Will be set when short URL is created 'short_code': None } self.link_pages_db[page_id] = page_data self._save_link_pages() # Persist to file return page_id def set_page_short_url(self, page_id, short_url, short_code): """Set the short URL for a link page""" if page_id in self.link_pages_db: self.link_pages_db[page_id]['short_url'] = short_url self.link_pages_db[page_id]['short_code'] = short_code self.link_pages_db[page_id]['updated_at'] = datetime.now().isoformat() self._save_link_pages() # Persist to file return True return False def add_link(self, page_id, title, url, description="", enable_shortener=False, custom_short_code=None): """Add a link to a page with optional URL shortening""" print(f"DEBUG: LinkManager.add_link called for page {page_id}") print(f"DEBUG: Current pages in memory: {list(self.link_pages_db.keys())}") if page_id not in self.link_pages_db: print(f"DEBUG: Page {page_id} not found in memory, reloading from file") self.link_pages_db = self._load_link_pages() print(f"DEBUG: After reload, pages: {list(self.link_pages_db.keys())}") if page_id not in self.link_pages_db: print(f"DEBUG: Page {page_id} still not found after reload") return False # Ensure URL has protocol if not url.startswith(('http://', 'https://')): url = f'https://{url}' # Create the link data link_data = { 'id': str(uuid.uuid4()), 'title': title, 'url': url, 'description': description, 'created_at': datetime.now().isoformat(), 'short_url': None, 'short_code': None, 'clicks': 0 } # Generate short URL if enabled if enable_shortener: print(f"DEBUG: Creating short URL for {url}") try: short_result = self.url_shortener.create_short_url( url, custom_code=custom_short_code, title=title ) print(f"DEBUG: Short URL created: {short_result}") link_data['short_url'] = short_result['short_url'] link_data['short_code'] = short_result['short_code'] except Exception as e: # If shortening fails, continue without it print(f"DEBUG: URL shortening failed: {e}") print(f"DEBUG: Adding link to page data: {link_data}") self.link_pages_db[page_id]['links'].append(link_data) self.link_pages_db[page_id]['updated_at'] = datetime.now().isoformat() print(f"DEBUG: Saving link pages to file") self._save_link_pages() # Persist to file print(f"DEBUG: Link added successfully") return True def update_link(self, page_id, link_id, title=None, url=None, description=None, enable_shortener=None, custom_short_code=None): """Update a specific link with optional URL shortening""" if page_id not in self.link_pages_db: return False for link in self.link_pages_db[page_id]['links']: if link['id'] == link_id: if title is not None: link['title'] = title if url is not None: link['url'] = url if url.startswith(('http://', 'https://')) else f'https://{url}' if description is not None: link['description'] = description # Handle URL shortening update if enable_shortener is not None: if enable_shortener and not link.get('short_url'): # Create new short URL try: short_result = self.url_shortener.create_short_url( link['url'], custom_code=custom_short_code, title=link['title'] ) link['short_url'] = short_result['short_url'] link['short_code'] = short_result['short_code'] except Exception as e: print(f"URL shortening failed: {e}") elif not enable_shortener and link.get('short_code'): # Remove short URL if link.get('short_code'): self.url_shortener.delete_url(link['short_code']) link['short_url'] = None link['short_code'] = None self.link_pages_db[page_id]['updated_at'] = datetime.now().isoformat() self._save_link_pages() # Persist to file return True return False def delete_link(self, page_id, link_id): """Delete a specific link""" if page_id not in self.link_pages_db: return False links = self.link_pages_db[page_id]['links'] for link in links: if link['id'] == link_id and link.get('short_code'): # Delete the short URL if it exists self.url_shortener.delete_url(link['short_code']) self.link_pages_db[page_id]['links'] = [link for link in links if link['id'] != link_id] self.link_pages_db[page_id]['updated_at'] = datetime.now().isoformat() self._save_link_pages() # Persist to file return True def increment_view_count(self, page_id): """Increment view count for a page""" if page_id in self.link_pages_db: self.link_pages_db[page_id]['view_count'] += 1 self._save_link_pages() # Persist to file def get_page(self, page_id): """Get page data""" # Reload data from file to ensure we have the latest data self.link_pages_db = self._load_link_pages() return self.link_pages_db.get(page_id) def page_exists(self, page_id): """Check if page exists""" # Reload data from file to ensure we have the latest data self.link_pages_db = self._load_link_pages() return page_id in self.link_pages_db # URL Shortener management methods def create_standalone_short_url(self, url, title="", custom_code=None): """Create a standalone short URL (not tied to a link page)""" return self.url_shortener.create_short_url(url, custom_code, title) def get_short_url_stats(self, short_code): """Get statistics for a short URL""" return self.url_shortener.get_url_stats(short_code) def list_all_short_urls(self): """List all short URLs in the system""" return self.url_shortener.list_urls() def resolve_short_url(self, short_code): """Resolve a short URL to its original URL""" # Reload URLShortener data to ensure we have the latest URLs self.url_shortener = URLShortener() return self.url_shortener.get_original_url(short_code)