#!/usr/bin/env python3 """ DBA.dk bud/besked-tool — sender besked til sælger via Playwright. Kræver at du er logget ind (gemmer session i ~/.openclaw/dba-session.json). Brug: python3 dba-bid.py "" python3 dba-bid.py --login (åbn browser og log ind manuelt) python3 dba-bid.py --check-login (test om session er aktiv) Eksempel: python3 dba-bid.py https://www.dba.dk/recommerce/forsale/item/16276129 \ "Hej, vil du tage 5000 kr? Kan afhente i weekenden." """ import sys, os, json, time, argparse SESSION_FILE = os.path.expanduser('~/.openclaw/dba-session.json') DBA_BASE = 'https://www.dba.dk' def get_item_url(item_ref: str) -> str: """Konverterer item-id eller fuld URL til fuld URL.""" if item_ref.startswith('http'): return item_ref # Bare et ID return f"{DBA_BASE}/recommerce/forsale/item/{item_ref}" def login_interactive(): """Åbn browser så brugeren kan logge ind, gem session bagefter.""" from playwright.sync_api import sync_playwright print("Åbner DBA.dk — log ind og tryk Enter her bagefter...") with sync_playwright() as p: browser = p.chromium.launch(headless=False, slow_mo=100) ctx = browser.new_context() page = ctx.new_page() page.goto(f"{DBA_BASE}/login/", wait_until='networkidle') input("Tryk Enter efter du er logget ind...") # Gem cookies cookies = ctx.cookies() with open(SESSION_FILE, 'w') as f: json.dump(cookies, f, indent=2) print(f"Session gemt ({len(cookies)} cookies) → {SESSION_FILE}") browser.close() def check_login() -> bool: """Tjek om session er aktiv.""" from playwright.sync_api import sync_playwright if not os.path.exists(SESSION_FILE): return False with open(SESSION_FILE) as f: cookies = json.load(f) # Tjek om auth-cookies er der og ikke tomme auth = [c for c in cookies if c.get('name') in ('id-jwt', 'schacc-session', 'login-webapp_jsession')] if not auth or all(not c.get('value') for c in auth): return False with sync_playwright() as p: browser = p.chromium.launch(headless=True) ctx = browser.new_context() ctx.add_cookies(cookies) page = ctx.new_page() page.goto(f"{DBA_BASE}/recommerce/forsale/search?q=test", wait_until='domcontentloaded', timeout=15000) # Tjek om vi er logget ind (profilikon/knap) logged_in = page.locator('[data-testid="profile-button"], [aria-label*="profil"], .user-avatar').count() > 0 browser.close() return logged_in def send_message(item_ref: str, message: str, dry_run: bool = False) -> dict: """Send besked til sælger på DBA.""" from playwright.sync_api import sync_playwright item_url = get_item_url(item_ref) if not os.path.exists(SESSION_FILE): return {'success': False, 'error': 'Ikke logget ind. Kør: python3 dba-bid.py --login'} with open(SESSION_FILE) as f: cookies = json.load(f) with sync_playwright() as p: browser = p.chromium.launch(headless=True) ctx = browser.new_context( user_agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/131 Safari/537.36' ) ctx.add_cookies(cookies) page = ctx.new_page() try: page.goto(item_url, wait_until='domcontentloaded', timeout=20000) time.sleep(2) # Find "Skriv til sælger" knap contact_btn = page.locator( 'button:has-text("Skriv til sælger"), ' 'button:has-text("Kontakt sælger"), ' 'a:has-text("Skriv til sælger"), ' '[data-testid="contact-seller-button"]' ).first if contact_btn.count() == 0: # Tag screenshot til debug page.screenshot(path='/tmp/dba-debug.png') browser.close() return {'success': False, 'error': 'Kunne ikke finde "Skriv til sælger" knap. Screenshot: /tmp/dba-debug.png'} if dry_run: browser.close() return {'success': True, 'dry_run': True, 'message': message, 'url': item_url} contact_btn.click() time.sleep(2) # Find tekstfelt og skriv besked textarea = page.locator( 'textarea[name*="message"], textarea[placeholder*="besked"], ' 'textarea[placeholder*="Message"], #message, [data-testid="message-input"]' ).first if textarea.count() == 0: page.screenshot(path='/tmp/dba-debug.png') browser.close() return {'success': False, 'error': 'Tekstfelt ikke fundet. Screenshot: /tmp/dba-debug.png'} textarea.fill(message) time.sleep(1) # Find Send-knap send_btn = page.locator( 'button[type="submit"]:has-text("Send"), ' 'button:has-text("Send besked"), ' '[data-testid="send-message-button"]' ).first if send_btn.count() == 0: page.screenshot(path='/tmp/dba-debug.png') browser.close() return {'success': False, 'error': 'Send-knap ikke fundet. Screenshot: /tmp/dba-debug.png'} send_btn.click() time.sleep(2) # Bekræft page.screenshot(path='/tmp/dba-sent.png') browser.close() return {'success': True, 'message': message, 'url': item_url, 'screenshot': '/tmp/dba-sent.png'} except Exception as e: try: page.screenshot(path='/tmp/dba-error.png') except Exception: pass browser.close() return {'success': False, 'error': str(e)} def main(): parser = argparse.ArgumentParser(description='DBA.dk bud/besked tool') parser.add_argument('item', nargs='?', help='Item URL eller ID') parser.add_argument('message', nargs='?', help='Besked til sælger') parser.add_argument('--login', action='store_true', help='Log ind interaktivt og gem session') parser.add_argument('--check-login', action='store_true', help='Tjek om session er aktiv') parser.add_argument('--dry-run', action='store_true', help='Test uden at sende') parser.add_argument('--json', action='store_true', help='Output som JSON') args = parser.parse_args() if args.login: login_interactive() return if args.check_login: ok = check_login() if args.json: print(json.dumps({'logged_in': ok})) else: print('Logget ind ✓' if ok else 'Ikke logget ind ✗') return if not args.item or not args.message: parser.print_help() sys.exit(1) result = send_message(args.item, args.message, dry_run=args.dry_run) if args.json: print(json.dumps(result, ensure_ascii=False, indent=2)) else: if result['success']: if result.get('dry_run'): print(f"[DRY-RUN] Ville sende: {result['message']}") print(f"Til: {result['url']}") else: print(f"Besked sendt til {result['url']}") print(f"Screenshot: {result.get('screenshot','')}") else: print(f"Fejl: {result['error']}", file=sys.stderr) sys.exit(1) if __name__ == '__main__': main()