social-autoposter 1.6.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "social-autoposter",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Automated social posting pipeline for Reddit, X/Twitter, LinkedIn, and Moltbook. Install as a Claude Code agent skill.",
5
5
  "bin": {
6
6
  "social-autoposter": "bin/cli.js"
@@ -40,7 +40,24 @@ LOCK_EXPIRY = 300 # process-level mutex TTL; refreshed during long ops
40
40
  LOCK_WAIT_MAX = 45 # seconds to wait for lock to free before giving up
41
41
  LOCK_POLL_INTERVAL = 2
42
42
  VIEWPORT = {"width": 911, "height": 1016}
43
- OUR_HANDLE = "m13v_"
43
+
44
+ # Posting handle. Resolved at call time from AUTOPOSTER_TWITTER_HANDLE env
45
+ # var (set by per-account launchd/systemd units) or config.json
46
+ # accounts.twitter.handle. The "m13v_" fallback keeps the Mac default working
47
+ # when neither source is set, but on the VMs the env var MUST be set so the
48
+ # DOM scrape + CDP URL build target the right profile.
49
+ _DEFAULT_HANDLE = "m13v_"
50
+
51
+ def our_handle():
52
+ try:
53
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
54
+ import account_resolver
55
+ h = account_resolver.resolve("twitter")
56
+ if h:
57
+ return h
58
+ except Exception:
59
+ pass
60
+ return _DEFAULT_HANDLE
44
61
 
45
62
  # DM encryption passcode from .env
46
63
  DM_PASSCODE = os.environ.get("TWITTER_DM_PASSCODE", "")
@@ -468,12 +485,13 @@ def _rate_limit_response(reason, counter=None, url=None):
468
485
 
469
486
 
470
487
  def _collect_our_reply_links(page):
471
- """Collect all /OUR_HANDLE/status/ links currently in the DOM."""
488
+ """Collect all /<our_handle>/status/ links currently in the DOM."""
489
+ handle = our_handle()
472
490
  return set(page.evaluate(f"""() => {{
473
491
  const links = new Set();
474
- document.querySelectorAll('a[href*="/{OUR_HANDLE}/status/"]').forEach(a => {{
492
+ document.querySelectorAll('a[href*="/{handle}/status/"]').forEach(a => {{
475
493
  const href = a.getAttribute('href');
476
- if (href && /\\/{OUR_HANDLE}\\/status\\/\\d+$/.test(href))
494
+ if (href && /\\/{handle}\\/status\\/\\d+$/.test(href))
477
495
  links.add(href);
478
496
  }});
479
497
  return [...links];
@@ -684,7 +702,7 @@ def reply_to_tweet(tweet_url, text, apply_campaigns=True):
684
702
 
685
703
  # Method 1: CDP network interception (most reliable)
686
704
  if _created_tweet_ids:
687
- reply_url = f"https://x.com/{OUR_HANDLE}/status/{_created_tweet_ids[-1]}"
705
+ reply_url = f"https://x.com/{our_handle()}/status/{_created_tweet_ids[-1]}"
688
706
  print(f"[reply_url] captured via CDP+response-listener: {reply_url}", file=sys.stderr)
689
707
 
690
708
  # Method 2: DOM diff (check if new reply links appeared)
@@ -1185,7 +1203,7 @@ def read_conversation(thread_url, max_messages=20):
1185
1203
  messages: recent,
1186
1204
  total_found: messages.length,
1187
1205
  };
1188
- }""", {"maxMessages": max_messages, "ourHandle": OUR_HANDLE})
1206
+ }""", {"maxMessages": max_messages, "ourHandle": our_handle()})
1189
1207
 
1190
1208
  return result
1191
1209