| |
| """Login + navigate to settings + find and update bio.""" |
| import time, os, sys, json |
| import undetected_chromedriver as uc |
| from dotenv import load_dotenv |
| from selenium.webdriver.common.by import By |
| from selenium.webdriver.common.keys import Keys |
| from datetime import datetime, timezone |
|
|
| load_dotenv(os.path.join(os.path.dirname(__file__), ".env")) |
| load_dotenv() |
|
|
| USERNAME = os.getenv("RENTMASSEUR_USERNAME", "") |
| PASSWORD = os.getenv("RENTMASSEUR_PASSWORD", "") |
| BIO_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "content", "bios", "controlled_wolf_v1.md") |
|
|
| with open(BIO_FILE, "r") as f: |
| BIO_TEXT = f.read().strip() |
|
|
| options = uc.ChromeOptions() |
| options.add_argument("--window-size=1280,900") |
|
|
| driver = uc.Chrome(options=options, version_main=149) |
|
|
| try: |
| |
| print("[1] Login...") |
| driver.get("https://rentmasseur.com/login") |
| time.sleep(6) |
| driver.execute_script(""" |
| const pwd = document.querySelector('input[type="password"]'); |
| const user = document.querySelector('input[type="text"], input[type="email"]'); |
| const ns = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; |
| if (user) { ns.call(user, arguments[0]); user.dispatchEvent(new Event('input', {bubbles: true})); } |
| if (pwd) { ns.call(pwd, arguments[1]); pwd.dispatchEvent(new Event('input', {bubbles: true})); } |
| """, USERNAME, PASSWORD) |
| time.sleep(1) |
| driver.find_element(By.CSS_SELECTOR, 'input[type="password"]').send_keys(Keys.ENTER) |
| time.sleep(5) |
| print(f" URL: {driver.current_url}") |
| |
| |
| print("\n[2] Settings page...") |
| driver.get("https://rentmasseur.com/settings") |
| time.sleep(5) |
| print(f" URL: {driver.current_url}") |
| print(f" Title: {driver.title}") |
| |
| |
| info = driver.execute_script(""" |
| const r = {textareas: [], inputs: [], contenteditable: [], buttons: [], links: [], tabs: []}; |
| document.querySelectorAll('textarea').forEach(t => r.textareas.push({id:t.id,name:t.name,ph:t.placeholder,val:(t.value||'').substring(0,80),vis:t.offsetParent!==null})); |
| document.querySelectorAll('input').forEach(i => r.inputs.push({type:i.type,id:i.id,name:i.name,ph:i.placeholder,val:(i.value||'').substring(0,40),vis:i.offsetParent!==null})); |
| document.querySelectorAll('[contenteditable]').forEach(e => r.contenteditable.push({tag:e.tagName,id:e.id,cls:e.className,txt:(e.innerText||'').substring(0,80)})); |
| document.querySelectorAll('button, [role="button"]').forEach(b => r.buttons.push({txt:(b.innerText||'').trim().substring(0,30),type:b.type,id:b.id})); |
| document.querySelectorAll('a').forEach(a => {if(a.innerText.trim()) r.links.push({txt:a.innerText.trim().substring(0,30),href:a.href})}); |
| document.querySelectorAll('[role="tab"], .nav-link, .tab').forEach(t => r.tabs.push({txt:(t.innerText||'').trim(),href:t.getAttribute('href')||'',id:t.id})); |
| return r; |
| """) |
| |
| print(f"\nTextareas: {len(info['textareas'])}") |
| for t in info['textareas']: |
| print(f" id={t['id']} name={t['name']} ph={t['ph']} vis={t['vis']} val={t['val'][:60]}") |
| |
| print(f"\nInputs: {len(info['inputs'])}") |
| for i in info['inputs']: |
| print(f" type={i['type']} id={i['id']} name={i['name']} ph={i['ph']} vis={i['vis']}") |
| |
| print(f"\nContenteditable: {len(info['contenteditable'])}") |
| for c in info['contenteditable']: |
| print(f" {c['tag']} id={c['id']} cls={c['cls']} txt={c['txt'][:60]}") |
| |
| print(f"\nButtons: {len(info['buttons'])}") |
| for b in info['buttons']: |
| print(f" {b['txt']} type={b['type']} id={b['id']}") |
| |
| print(f"\nTabs: {len(info['tabs'])}") |
| for t in info['tabs']: |
| print(f" {t['txt']} href={t['href']} id={t['id']}") |
| |
| print(f"\nLinks: {len(info['links'])}") |
| for l in info['links'][:25]: |
| print(f" {l['txt']} -> {l['href']}") |
| |
| driver.save_screenshot("/Users/alep/Downloads/rentmasseur-optimizer/settings_page.png") |
| |
| |
| print("\n[3] Looking for bio tab...") |
| bio_tabs = [l for l in info['links'] if any(w in (l['txt']+l['href']).lower() for w in ['bio', 'about', 'profile', 'edit', 'content'])] |
| print(f" Bio-related links: {len(bio_tabs)}") |
| for bt in bio_tabs: |
| print(f" {bt['txt']} -> {bt['href']}") |
| |
| |
| for bt in bio_tabs: |
| print(f"\n Trying: {bt['href']}") |
| driver.get(bt['href']) |
| time.sleep(4) |
| textareas = driver.find_elements(By.CSS_SELECTOR, 'textarea') |
| editables = driver.find_elements(By.CSS_SELECTOR, '[contenteditable]') |
| print(f" textareas={len(textareas)} editables={len(editables)}") |
| if textareas: |
| for ta in textareas: |
| val = ta.get_attribute("value") or "" |
| print(f" textarea id={ta.get_attribute('id')} name={ta.get_attribute('name')} len={len(val)} preview={val[:80]}") |
| |
| |
| updated = driver.execute_script(""" |
| const tas = Array.from(document.querySelectorAll('textarea')); |
| let best = null, bestScore = 0; |
| for (const ta of tas) { |
| const ctx = (ta.id||'') + ' ' + (ta.name||'') + ' ' + (ta.placeholder||''); |
| if (/bio|about|description|profile/i.test(ctx)) { best = ta; break; } |
| if ((ta.value||'').length > bestScore) { bestScore = (ta.value||'').length; best = ta; } |
| } |
| if (!best && tas.length > 0) best = tas[0]; |
| if (!best) return {error: 'no_textarea'}; |
| const ns = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set; |
| ns.call(best, arguments[0]); |
| best.dispatchEvent(new Event('input', {bubbles: true})); |
| best.dispatchEvent(new Event('change', {bubbles: true})); |
| best.dispatchEvent(new Event('blur', {bubbles: true})); |
| return {id: best.id, name: best.name, new_len: arguments[0].length}; |
| """, BIO_TEXT) |
| print(f" Updated: {updated}") |
| |
| if isinstance(updated, dict) and 'error' not in updated: |
| time.sleep(1) |
| saved = driver.execute_script(""" |
| const btns = Array.from(document.querySelectorAll('button, input[type="submit"]')); |
| const sb = btns.find(b => /save|update|submit|apply|confirm/i.test((b.innerText||'')+' '+(b.value||''))); |
| if (sb) { sb.click(); return {ok: true, text: sb.innerText}; } |
| return {ok: false}; |
| """) |
| print(f" Save: {saved}") |
| time.sleep(5) |
| |
| |
| receipts_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "receipts") |
| os.makedirs(receipts_dir, exist_ok=True) |
| receipt = {"action": "bio_deploy", "bio_id": "controlled_wolf_v1", "experiment_id": "exp_001_targeted_wolf", "success": True, "timestamp": datetime.now(timezone.utc).isoformat(), "url": driver.current_url} |
| rpath = os.path.join(receipts_dir, f"deploy_controlled_wolf_v1_{receipt['timestamp'].replace(':','-')}.json") |
| with open(rpath, "w") as f: |
| json.dump(receipt, f, indent=2) |
| print(f"\n=== BIO DEPLOYED === Receipt: {rpath}") |
| break |
| if editables: |
| for e in editables: |
| txt = e.get_attribute("innerText") or "" |
| print(f" editable tag={e.tag_name} id={e.get_attribute('id')} txt={txt[:80]}") |
| |
| finally: |
| driver.quit() |
| print("\nDone.") |
|
|