ilml-plugin-linkedin 1.17.2 → 1.18.0

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/dist/readPost.mjs CHANGED
@@ -1,16 +1,16 @@
1
- var ee=Object.defineProperty;var te=(n,e)=>()=>(n&&(e=n(n=0)),e);var oe=(n,e)=>{for(var u in e)ee(n,u,{get:e[u],enumerable:!0})};var V={};oe(V,{graph:()=>le});import{createGraphClient as re,resolveToken as ae}from"@ilivemylife/graph-sdk";import{config as ce}from"dotenv";var K,le,X=te(()=>{ce();K=ae()||process.env.TOKEN;K||(console.error(`
1
+ var ue=Object.defineProperty;var de=(t,s)=>()=>(t&&(s=t(t=0)),s);var pe=(t,s)=>{for(var e in s)ue(t,e,{get:s[e],enumerable:!0})};var ie={};pe(ie,{graph:()=>Se});import{createGraphClient as xe,resolveToken as we}from"@ilivemylife/graph-sdk";import{config as ke}from"dotenv";var se,Se,re=de(()=>{ke();se=we()||process.env.TOKEN;se||(console.error(`
2
2
  [FATAL] No iLiveMyLife token found.`),console.error(" The bot uses Lifebot AI to decide which jobs to apply for"),console.error(` and how to fill application forms. It cannot work without it.
3
3
  `),console.error(" Easiest way:"),console.error(" 1. npm install -g @ilivemylife/graph-sdk"),console.error(` 2. ilml login your@email.com yourpassword
4
4
  `),console.error(` Or add ILML_TOKEN=... to .env
5
- `),process.exit(1));le=re({token:K})});import"dotenv/config";import me from"puppeteer";var F=n=>new Promise(e=>setTimeout(e,n));function G(n){return n?n.split("?")[0].split("#")[0]:""}async function H(n,e,u={}){let S=u.commentPasses??4,m=u.skipComments??!1,y=Number.isFinite(u.commentsMax)?u.commentsMax:1/0;if(await n.goto(e,{waitUntil:"domcontentloaded",timeout:6e4}),await F(4e3),await n.evaluate(()=>/\/login|\/authwall|\/checkpoint|\/uas\//.test(location.pathname)||!!document.querySelector('input[name="session_key"]')))return{authWall:!0};let d=m?2:6;for(let o=0;o<d;o++)await n.evaluate(()=>window.scrollBy(0,1200)),await F(m?500:1e3);if(m)await n.evaluate(()=>{for(let o of document.querySelectorAll("button")){let a=`${o.innerText||""} ${o.getAttribute("aria-label")||""}`;if(/^(see more|…more|show more)$/i.test(a.trim()))try{o.click()}catch{}}}),await F(500);else for(let o=0;o<S;o++){let a=await n.evaluate(()=>{let l=0;for(let r of document.querySelectorAll("button")){let g=`${r.innerText||""} ${r.getAttribute("aria-label")||""}`;if(/see more|…more|show more|load more comments|more comments|previous replies|more replies|показать ещё|ещё|загрузить ещё|показать предыдущие/i.test(g))try{r.click(),l++}catch{}}return l});if(await F(1800),!a)break}let t=await n.evaluate(()=>{let o=(p,f)=>{for(let $ of f){let w=p&&p.querySelector($);if(w&&(w.innerText||"").trim())return w.innerText.trim()}return""},a=(p,f)=>{for(let $ of f){let w=p&&p.querySelector($);if(w&&w.href)return w.href}return""},l=document.querySelector("main")||document.body,r=document.querySelector(".fie-impression-container")||document.querySelector(".feed-shared-update-v2")||l,g={name:o(r,['.update-components-actor__title span[aria-hidden="true"]','.update-components-actor__name span[aria-hidden="true"]',".update-components-actor__title",".update-components-actor__name"]),profileUrl:a(r,['.update-components-actor__container a[href*="/in/"]','.update-components-actor__meta a[href*="/in/"]','a.app-aware-link[href*="/in/"]']),headline:o(r,[".update-components-actor__description"])},C=o(r,[".update-components-update-v2__commentary",".feed-shared-update-v2__description",".update-components-text"]),I=o(r,['.update-components-actor__sub-description span[aria-hidden="true"]',".update-components-actor__sub-description"]),E=o(document,[".social-details-social-counts__reactions-count",".social-details-social-counts__social-proof-fallback-number"]),P=o(document,['button[aria-label*="comment" i] span',".social-details-social-counts__comments"]),T=o(document,['button[aria-label*="repost" i] span',".social-details-social-counts__reposts",".social-details-social-counts__shares"]),c=r.querySelector(".update-components-update-v2__commentary")||r.querySelector(".update-components-text")||r,O=Array.from(c?.querySelectorAll?.('a[href*="/in/"], a[href*="/company/"]')||[]),A=[],U=new Set;for(let p of O){let f=(p.href||"").split("?")[0].replace(/\/$/,"");if(!f||U.has(f))continue;U.add(f);let $=(p.textContent||"").trim(),w=f.includes("/company/")?"company":"person";A.push({kind:w,url:f,label:$||null})}let M=Array.from(new Set(((C||"")+" "+(c?.textContent||"")).match(/#[\p{L}\p{N}_]{2,40}/gu)||[])),W={hasImage:!!r.querySelector(".update-components-image, img.feed-shared-image__image"),hasVideo:!!r.querySelector("video, .update-components-video, .feed-shared-update-v2__content video"),hasArticle:!!r.querySelector(".update-components-article, .feed-shared-article"),hasDocument:!!r.querySelector(".feed-shared-document, .update-components-document"),hasPoll:!!r.querySelector(".update-components-poll, .feed-shared-poll")},R=document.querySelectorAll("article.comments-comment-entity, .comments-comment-entity, .comments-comment-item"),i=[];for(let p of R){let f=o(p,[".comments-comment-meta__description-title",'.comments-post-meta__name-text span[aria-hidden="true"]',".comments-post-meta__name-text"]),$=o(p,[".comments-comment-item__main-content",".comments-comment-entity__content .update-components-text",".comments-comment-entity__content",".update-components-text"]);!f&&!$||i.push({author:{name:f,profileUrl:a(p,['a[href*="/in/"]']),headline:o(p,[".comments-comment-meta__description-subtitle",".comments-post-meta__headline"])},text:$})}let j=new Set,Z=i.filter(p=>{let f=`${p.author.name}|${p.text.slice(0,80)}`;return j.has(f)?!1:(j.add(f),!0)});return{url:location.href,author:g,text:C,postedAt:I,reactions:E,commentCount:P,repostCount:T,hashtags:M,mentions:A,media:W,comments:Z,fullText:(l.innerText||"").replace(/\n{3,}/g,`
5
+ `),process.exit(1));Se=xe({token:se})});import"dotenv/config";import _e from"puppeteer";var q=t=>new Promise(s=>setTimeout(s,t));function J(t){return t?t.split("?")[0].split("#")[0]:""}async function K(t,s,e={}){let p=e.commentPasses??4,g=e.skipComments??!1,l=Number.isFinite(e.commentsMax)?e.commentsMax:1/0;if(await t.goto(s,{waitUntil:"domcontentloaded",timeout:6e4}),await q(4e3),await t.evaluate(()=>/\/login|\/authwall|\/checkpoint|\/uas\//.test(location.pathname)||!!document.querySelector('input[name="session_key"]')))return{authWall:!0};let b=g?2:6;for(let n=0;n<b;n++)await t.evaluate(()=>window.scrollBy(0,1200)),await q(g?500:1e3);if(g)await t.evaluate(()=>{for(let n of document.querySelectorAll("button")){let u=`${n.innerText||""} ${n.getAttribute("aria-label")||""}`;if(/^(see more|…more|show more)$/i.test(u.trim()))try{n.click()}catch{}}}),await q(500);else for(let n=0;n<p;n++){let u=await t.evaluate(()=>{let r=0;for(let c of document.querySelectorAll("button")){let f=`${c.innerText||""} ${c.getAttribute("aria-label")||""}`;if(/see more|…more|show more|load more comments|more comments|previous replies|more replies|показать ещё|ещё|загрузить ещё|показать предыдущие/i.test(f))try{c.click(),r++}catch{}}return r});if(await q(1800),!u)break}let o=await t.evaluate(()=>{let n=(d,h)=>{for(let _ of h){let w=d&&d.querySelector(_);if(w&&(w.innerText||"").trim())return w.innerText.trim()}return""},u=(d,h)=>{for(let _ of h){let w=d&&d.querySelector(_);if(w&&w.href)return w.href}return""},r=document.querySelector("main")||document.body,c=document.querySelector(".fie-impression-container")||document.querySelector(".feed-shared-update-v2")||r,f={name:n(c,['.update-components-actor__title span[aria-hidden="true"]','.update-components-actor__name span[aria-hidden="true"]',".update-components-actor__title",".update-components-actor__name"]),profileUrl:u(c,['.update-components-actor__container a[href*="/in/"]','.update-components-actor__meta a[href*="/in/"]','a.app-aware-link[href*="/in/"]']),headline:n(c,[".update-components-actor__description"])},L=n(c,[".update-components-update-v2__commentary",".feed-shared-update-v2__description",".update-components-text"]),P=n(c,['.update-components-actor__sub-description span[aria-hidden="true"]',".update-components-actor__sub-description"]),R=n(document,[".social-details-social-counts__reactions-count",".social-details-social-counts__social-proof-fallback-number"]),U=n(document,['button[aria-label*="comment" i] span',".social-details-social-counts__comments"]),S=n(document,['button[aria-label*="repost" i] span',".social-details-social-counts__reposts",".social-details-social-counts__shares"]),m=c.querySelector(".update-components-update-v2__commentary")||c.querySelector(".update-components-text")||c,O=Array.from(m?.querySelectorAll?.('a[href*="/in/"], a[href*="/company/"]')||[]),C=[],M=new Set;for(let d of O){let h=(d.href||"").split("?")[0].replace(/\/$/,"");if(!h||M.has(h))continue;M.add(h);let _=(d.textContent||"").trim(),w=h.includes("/company/")?"company":"person";C.push({kind:w,url:h,label:_||null})}let j=Array.from(new Set(((L||"")+" "+(m?.textContent||"")).match(/#[\p{L}\p{N}_]{2,40}/gu)||[])),H={hasImage:!!c.querySelector(".update-components-image, img.feed-shared-image__image"),hasVideo:!!c.querySelector("video, .update-components-video, .feed-shared-update-v2__content video"),hasArticle:!!c.querySelector(".update-components-article, .feed-shared-article"),hasDocument:!!c.querySelector(".feed-shared-document, .update-components-document"),hasPoll:!!c.querySelector(".update-components-poll, .feed-shared-poll")},D=document.querySelectorAll("article.comments-comment-entity, .comments-comment-entity, .comments-comment-item"),a=[];for(let d of D){let h=n(d,[".comments-comment-meta__description-title",'.comments-post-meta__name-text span[aria-hidden="true"]',".comments-post-meta__name-text"]),_=n(d,[".comments-comment-item__main-content",".comments-comment-entity__content .update-components-text",".comments-comment-entity__content",".update-components-text"]);!h&&!_||a.push({author:{name:h,profileUrl:u(d,['a[href*="/in/"]']),headline:n(d,[".comments-comment-meta__description-subtitle",".comments-post-meta__headline"])},text:_})}let F=new Set,me=a.filter(d=>{let h=`${d.author.name}|${d.text.slice(0,80)}`;return F.has(h)?!1:(F.add(h),!0)});return{url:location.href,author:f,text:L,postedAt:P,reactions:R,commentCount:U,repostCount:S,hashtags:j,mentions:C,media:H,comments:me,fullText:(r.innerText||"").replace(/\n{3,}/g,`
6
6
 
7
- `)}});m?(t.comments=[],t.commentsTruncated=!0,t.commentsTruncatedReason="skipComments"):Number.isFinite(y)&&t.comments.length>y?(t.commentsTruncated=!0,t.commentsTruncatedReason=`commentsMax=${y}`,t.commentsTruncatedOriginalCount=t.comments.length,t.comments=t.comments.slice(0,y)):t.commentsTruncated=!1,t.author.profileUrl=G(t.author.profileUrl),t.comments=t.comments.map(o=>({...o,author:{...o.author,profileUrl:G(o.author.profileUrl)}}));let s=t.fullText||"";if(!t.author.name){let o=s.match(/\n\s*Feed post\s*\n+\s*([^\n]+)/i);o&&(t.author.name=o[1].trim())}if(!t.reactions){let o=s.match(/([\d,]+)\s+reactions?/i);o&&(t.reactions=o[1])}if(!t.commentCount){let o=s.match(/([\d,]+)\s+comments?/i);o&&(t.commentCount=o[1])}let x=s,N=x.search(/\n\s*Feed post\s*\n/i);if(N>=0&&(x=x.slice(N).replace(/^\s*Feed post\s*\n/i,"")),x=x.replace(/\n\s*About\s*\n+\s*Accessibility[\s\S]*$/i,"").replace(/\n\s*LinkedIn Corporation ©[\s\S]*$/i,"").trim(),t.cleanText=x,t.cleanText){let o=t.cleanText.split(`
8
- `).map(l=>l.trim()),a=o.findIndex(l=>/^\d+\s*[mhdwy]\s*•/i.test(l));if(a>=0&&(t.postedAt||(t.postedAt=o[a].replace(/\s*•\s*$/,"").trim()),!t.text)){let l=[];for(let r=a+1;r<o.length;r++){let g=o[r];if(/^(Most relevant|Top comments|Comments|All comments|\d+ comments?)\b/i.test(g)||/^[\d,]+$/.test(g)&&/^[\d,]+$/.test(o[r+1]||""))break;l.push(g)}t.text=l.join(`
7
+ `)}});g?(o.comments=[],o.commentsTruncated=!0,o.commentsTruncatedReason="skipComments"):Number.isFinite(l)&&o.comments.length>l?(o.commentsTruncated=!0,o.commentsTruncatedReason=`commentsMax=${l}`,o.commentsTruncatedOriginalCount=o.comments.length,o.comments=o.comments.slice(0,l)):o.commentsTruncated=!1,o.author.profileUrl=J(o.author.profileUrl),o.comments=o.comments.map(n=>({...n,author:{...n.author,profileUrl:J(n.author.profileUrl)}}));let y=o.fullText||"";if(!o.author.name){let n=y.match(/\n\s*Feed post\s*\n+\s*([^\n]+)/i);n&&(o.author.name=n[1].trim())}if(!o.reactions){let n=y.match(/([\d,]+)\s+reactions?/i);n&&(o.reactions=n[1])}if(!o.commentCount){let n=y.match(/([\d,]+)\s+comments?/i);n&&(o.commentCount=n[1])}let i=y,I=i.search(/\n\s*Feed post\s*\n/i);if(I>=0&&(i=i.slice(I).replace(/^\s*Feed post\s*\n/i,"")),i=i.replace(/\n\s*About\s*\n+\s*Accessibility[\s\S]*$/i,"").replace(/\n\s*LinkedIn Corporation ©[\s\S]*$/i,"").trim(),o.cleanText=i,o.cleanText){let n=o.cleanText.split(`
8
+ `).map(r=>r.trim()),u=n.findIndex(r=>/^\d+\s*[mhdwy]\s*•/i.test(r));if(u>=0&&(o.postedAt||(o.postedAt=n[u].replace(/\s*•\s*$/,"").trim()),!o.text)){let r=[];for(let c=u+1;c<n.length;c++){let f=n[c];if(/^(Most relevant|Top comments|Comments|All comments|\d+ comments?)\b/i.test(f)||/^[\d,]+$/.test(f)&&/^[\d,]+$/.test(n[c+1]||""))break;r.push(f)}o.text=r.join(`
9
9
  `).replace(/\n{3,}/g,`
10
10
 
11
- `).trim()}}if(!m&&t.comments.length===0&&t.cleanText){let o=t.cleanText.split(`
12
- `).map(l=>l.trim()),a=o.findIndex(l=>/^(Most relevant|Top comments|Recent comments)$/i.test(l));if(a>=0){let l=o.slice(a+1),r=[],g=[];for(let c of l){if(/^\d+\s+reactions?/i.test(c)){g.length>0&&r.push(g),g=[];continue}g.push(c)}g.length>0&&r.push(g);let C=c=>/Premium Profile|Verified Profile/i.test(c),I=c=>/[·•]\s*\d+(?:st|nd|rd|th)\+?/i.test(c),E=c=>/^\d+$/.test(c),P=c=>/^(Reactions|Reply|Like|Author|See translation|Show \d+)$/i.test(c),T=[];for(let c of r){let O=c.findIndex(i=>i==="Follow");if(O<0)continue;let A=(c.find(i=>i&&!C(i)&&!I(i)&&!E(i)&&!P(i))||"").trim(),U=c.find(i=>/^\d+[hmsdwy]$/.test(i))||"",M=c.slice(0,O).filter(i=>i&&i!==A&&i!==U&&!C(i)&&!I(i)&&!E(i)&&!P(i));M.sort((i,j)=>j.length-i.length);let W=M[0]||"",R=c.slice(O+1).filter(i=>i&&i!=="Reply"&&i!=="Like"&&i!=="Reactions").join(`
13
- `).trim();A&&R&&T.push({author:{name:A,headline:W,profileUrl:""},text:R})}if(T.length>0){let c=Number.isFinite(y)?T.slice(0,y):T;t.comments=c,t.commentsFromCleanTextFallback=!0,c.length<T.length&&(t.commentsTruncated=!0,t.commentsTruncatedReason=`commentsMax=${y}`,t.commentsTruncatedOriginalCount=T.length)}}}if(t.text&&Array.isArray(t.mentions)&&t.mentions.length>0){let o=t.text.toLowerCase(),a=t.mentions.filter(l=>l.label?o.includes(l.label.toLowerCase()):!1);t.mentionsFilteredFromDOM=t.mentions.length-a.length,t.mentions=a}let h=e.match(/(?:activity-|share-)(\d{6,})/);return t.urn=h?h[1]:"",t}import J from"fs";import ne from"path";var se="cookies.json";function ie(){let n=process.env.ILML_SCOPE_DIR;return n?ne.join(n,"plugins-state","linkedin","cookies.json"):se}function B(){let n=ie();if(!J.existsSync(n))throw new Error(`Cookies not found at ${n}. Run: ilml linkedin login`);let e;try{e=J.readFileSync(n,"utf-8")}catch(S){throw new Error(`Failed to read cookies at ${n}: ${S.message}. Run: ilml linkedin login`)}let u;try{u=JSON.parse(e)}catch{throw new Error(`Cookies file at ${n} is corrupted (invalid JSON). Run: ilml linkedin login`)}if(!Array.isArray(u)||u.length===0)throw new Error(`Cookies file at ${n} is empty or not an array. Run: ilml linkedin login`);return u}var _=process.argv.slice(2),ue=_.includes("--help")||_.includes("-h"),z=_.includes("--json"),L=_.find(n=>n.startsWith("--save-to-graph="))?.split("=")[1]||null,D=_.find(n=>n.startsWith("--out="))?.split("=")[1]||null,de=_.includes("--no-comments"),Y=_.find(n=>n.startsWith("--comments-max="))?.split("=")[1],pe=Y!=null?parseInt(Y,10):null,b=_.find(n=>n.startsWith("http")),k=z?(...n)=>console.error(...n):(...n)=>console.log(...n);function Q(){console.log(`
11
+ `).trim()}}if(!g&&o.comments.length===0&&o.cleanText){let n=o.cleanText.split(`
12
+ `).map(r=>r.trim()),u=n.findIndex(r=>/^(Most relevant|Top comments|Recent comments)$/i.test(r));if(u>=0){let r=n.slice(u+1),c=[],f=[];for(let m of r){if(/^\d+\s+reactions?/i.test(m)){f.length>0&&c.push(f),f=[];continue}f.push(m)}f.length>0&&c.push(f);let L=m=>/Premium Profile|Verified Profile/i.test(m),P=m=>/[·•]\s*\d+(?:st|nd|rd|th)\+?/i.test(m),R=m=>/^\d+$/.test(m),U=m=>/^(Reactions|Reply|Like|Author|See translation|Show \d+)$/i.test(m),S=[];for(let m of c){let O=m.findIndex(a=>a==="Follow");if(O<0)continue;let C=(m.find(a=>a&&!L(a)&&!P(a)&&!R(a)&&!U(a))||"").trim(),M=m.find(a=>/^\d+[hmsdwy]$/.test(a))||"",j=m.slice(0,O).filter(a=>a&&a!==C&&a!==M&&!L(a)&&!P(a)&&!R(a)&&!U(a));j.sort((a,F)=>F.length-a.length);let H=j[0]||"",D=m.slice(O+1).filter(a=>a&&a!=="Reply"&&a!=="Like"&&a!=="Reactions").join(`
13
+ `).trim();C&&D&&S.push({author:{name:C,headline:H,profileUrl:""},text:D})}if(S.length>0){let m=Number.isFinite(l)?S.slice(0,l):S;o.comments=m,o.commentsFromCleanTextFallback=!0,m.length<S.length&&(o.commentsTruncated=!0,o.commentsTruncatedReason=`commentsMax=${l}`,o.commentsTruncatedOriginalCount=S.length)}}}if(o.text&&Array.isArray(o.mentions)&&o.mentions.length>0){let n=o.text.toLowerCase(),u=o.mentions.filter(r=>r.label?n.includes(r.label.toLowerCase()):!1);o.mentionsFilteredFromDOM=o.mentions.length-u.length,o.mentions=u}let E=s.match(/(?:activity-|share-)(\d{6,})/);return o.urn=E?E[1]:"",o}import x from"fs";import T from"path";var he="cookies.json";function B(){let t=process.env.ILML_SCOPE_DIR;return t?T.join(t,"plugins-state","linkedin","cookies.json"):he}function V(){let t=B();if(!x.existsSync(t))throw new Error(`Cookies not found at ${t}. Run: ilml linkedin login`);let s;try{s=x.readFileSync(t,"utf-8")}catch(p){throw new Error(`Failed to read cookies at ${t}: ${p.message}. Run: ilml linkedin login`)}let e;try{e=JSON.parse(s)}catch{throw new Error(`Cookies file at ${t} is corrupted (invalid JSON). Run: ilml linkedin login`)}if(!Array.isArray(e)||e.length===0)throw new Error(`Cookies file at ${t} is empty or not an array. Run: ilml linkedin login`);return e}function Y(){return x.existsSync(B())}function fe(){let t=process.env.ILML_SCOPE_DIR;return t?T.join(t,"plugins-state","linkedin"):"."}function X(t){let s=String(t||"").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,80);return/[a-zA-Z0-9]/.test(s)?s:"default"}function ge(){let t=process.env.MY_LINKEDIN_URL,s=t&&t.match(/\/in\/([^/?#]+)/);return s&&s[1]?X(s[1]):"default"}function z(t){let s=process.env.LINKEDIN_CHROME_PROFILE_DIR;if(s)return x.existsSync(s)||x.mkdirSync(s,{recursive:!0}),T.resolve(s);let e=X(t||ge()),p=T.join(fe(),"chrome-profile",e);return x.existsSync(p)||x.mkdirSync(p,{recursive:!0}),T.resolve(p)}var Z=".ilml-seeded";function Q(t){return!x.existsSync(T.join(t,Z))}function ee(t){try{x.writeFileSync(T.join(t,Z),new Date().toISOString())}catch{}}function te(t){let s=0;for(let e of["SingletonLock","SingletonCookie","SingletonSocket"])try{x.rmSync(T.join(t,e),{force:!0}),s++}catch{}return s}var ye={headless:!1,defaultViewport:null,protocolTimeout:3e5};async function oe(t,s={}){let e=z(),p={...ye,...s,userDataDir:e},g;try{g=await t.launch(p)}catch{te(e);try{g=await t.launch(p)}catch($){throw new Error(`Could not open the LinkedIn automation Chrome profile at ${e}. If a LinkedIn automation window is already open, close it and retry. (Chrome: ${$.message})`)}}return{browser:g,profileDir:e,needsSeed:Q(e)}}async function ne(t,s){if(!s||!s.needsSeed)return!1;if(!Y())return console.warn(" \u26A0 No saved LinkedIn session found. If this command comes back empty or redirects to login, run: ilml linkedin login"),!1;try{return await t.setCookie(...V()),ee(s.profileDir),console.log(" (seeded persistent profile from saved cookies \u2014 one-time)"),!0}catch{return!1}}var v=process.argv.slice(2),Te=v.includes("--help")||v.includes("-h"),ce=v.includes("--json"),N=v.find(t=>t.startsWith("--save-to-graph="))?.split("=")[1]||null,G=v.find(t=>t.startsWith("--out="))?.split("=")[1]||null,ve=v.includes("--no-comments"),ae=v.find(t=>t.startsWith("--comments-max="))?.split("=")[1],$e=ae!=null?parseInt(ae,10):null,A=v.find(t=>t.startsWith("http")),k=ce?(...t)=>console.error(...t):(...t)=>console.log(...t);function le(){console.log(`
14
14
  read-post \u2014 read ONE LinkedIn post by URL (analysis-first; saving is opt-in)
15
15
 
16
16
  DEFAULT USE CASE
@@ -71,6 +71,6 @@ WHAT YOU GET ON ONE PAGE LOAD (no extra cost regardless of flags)
71
71
  BAN RISK
72
72
  Low. One post view = a single page load = normal human browsing.
73
73
  --no-comments is even quieter (skips the load-more-comments scroll loop).
74
- `)}ue&&(Q(),process.exit(0));b||(Q(),process.exit(1));/linkedin\.com\/(posts|feed|in)\/|linkedin\.com\/.*(activity|update)/i.test(b)||(console.error(`URL doesn't look like a LinkedIn post: ${b}`),console.error("Expected something like:"),console.error(" https://www.linkedin.com/posts/<slug>-activity-<id>-xxxx"),console.error(" https://www.linkedin.com/feed/update/urn:li:activity:<id>"),process.exit(1));k("");k(` read-post \u2014 ${b}`);k("");var q=null;try{q=await me.launch({headless:!1,defaultViewport:null,protocolTimeout:3e5});let n=await q.newPage();await n.setCookie(...B());let e=await H(n,b,{skipComments:de,commentsMax:pe});e.authWall&&(console.error(" \u26D4 Auth wall \u2014 cookies expired or not logged in."),console.error(" Run 'ilml linkedin login' (or: node src/saveLoginState.mjs) and retry."),process.exit(2));let u=null;if(L){let m=e.author||{},y=e.text||e.cleanText||e.fullText||"",v=(y.replace(/\s+/g," ").trim()||"(empty post)").slice(0,80),d=`${m.name||"unknown"} \u2014 ${v}${v.length===80?"\u2026":""}`,t={url:e.url||b,urn:e.urn||null,author:e.author||null,text:e.text||null,postedAt:e.postedAt||null,hashtags:e.hashtags||[],mentions:e.mentions||[],media:e.media||null,capturedAt:new Date().toISOString()},s=[];m.name&&s.push(`**Author:** ${m.name}${m.headline?` \u2014 ${m.headline}`:""}`),m.profileUrl&&s.push(`**Profile:** ${m.profileUrl}`),e.postedAt&&s.push(`**Posted:** ${e.postedAt}`),s.push(`**Source:** ${b}`),s.push(`**Captured:** ${t.capturedAt.slice(0,10)}`),s.push(""),s.push("---"),s.push(""),s.push(y||"(post text not extracted)"),e.hashtags?.length&&(s.push(""),s.push(`**Hashtags:** ${e.hashtags.join(" ")}`)),e.mentions?.length&&(s.push(""),s.push(`**Mentions:** ${e.mentions.map(h=>`[${h.label||h.kind}](${h.url})`).join(", ")}`));let x=Object.entries(e.media||{}).filter(([,h])=>h).map(([h])=>h.replace(/^has/,"").toLowerCase());x.length&&(s.push(""),s.push(`**Media:** ${x.join(", ")}`)),s.push(""),s.push("---"),s.push(""),s.push("*Live engagement (reactions / comments / reposts) is intentionally NOT saved here \u2014 those drift. Re-run `read-post --json` on the source URL for current numbers.*"),s.push(""),s.push("```json"),s.push(JSON.stringify(t,null,2)),s.push("```");let N=s.join(`
75
- `);try{let{graph:h}=await Promise.resolve().then(()=>(X(),V)),o=await h.addItem(L,{title:d,description:N,tags:["linkedin-post"]}),a=o?.id||o?.item?.id||null;u={parentId:L,nodeId:a,url:a?`https://app.ilivemylife.io/item/${a}`:null},k(""),k(` \u2713 Saved to graph as child of ${L}`),k(` New node: ${a||"(id not returned by SDK)"}`),a&&k(` URL: https://app.ilivemylife.io/item/${a}`),k("")}catch(h){u={parentId:L,error:h.message?.slice(0,200)},console.error(""),console.error(` \u26A0 Failed to save to graph: ${h.message?.slice(0,200)}`),console.error(" The post was still extracted successfully \u2014 printing below."),console.error("")}}let S={...e,...u!==null&&{savedToGraph:u}};if(D&&((await import("fs")).writeFileSync(D,JSON.stringify(S,null,2)),k(` \u2713 Wrote ${(JSON.stringify(S).length/1024).toFixed(1)}KB to ${D}`)),z)console.log(JSON.stringify(S,null,2));else{let m=e.author||{};console.log(" \u2500\u2500\u2500 POST \u2500\u2500\u2500"),console.log(` Author: ${m.name||"(unknown)"}${m.headline?` \u2014 ${m.headline}`:""}`),m.profileUrl&&console.log(` Profile: ${m.profileUrl}`),e.postedAt&&console.log(` Posted: ${e.postedAt}`);let y=[`${e.reactions||"0"} reactions`,`${e.commentCount||e.comments.length||"0"} comments`,e.repostCount?`${e.repostCount} reposts`:null].filter(Boolean).join(" ");console.log(` Engagement: ${y}`);let v=Object.entries(e.media||{}).filter(([,d])=>d).map(([d])=>d.replace(/^has/,"").toLowerCase());if(v.length&&console.log(` Media: ${v.join(", ")}`),e.hashtags?.length&&console.log(` Hashtags: ${e.hashtags.join(" ")}`),e.mentions?.length&&console.log(` Mentions: ${e.mentions.map(d=>`${d.label||d.url} (${d.kind})`).join(", ")}`),console.log(""),e.commentsTruncated){let d=e.commentsTruncatedReason==="skipComments"?"(comments skipped via --no-comments)":`(showing first ${e.comments.length} of ${e.commentsTruncatedOriginalCount} \u2014 capped via --comments-max)`;console.log(` Note: ${d}`),console.log("")}if(e.comments.length){console.log(e.text||"(post text not parsed \u2014 see cleanText below)"),console.log(""),console.log(` \u2500\u2500\u2500 COMMENTS (${e.comments.length}) \u2500\u2500\u2500`);for(let d of e.comments){let t=d.author||{};console.log(""),console.log(` \u2022 ${t.name||"(unknown)"}${t.headline?` \u2014 ${t.headline}`:""}`),d.text&&console.log(` ${d.text.replace(/\n+/g,`
76
- `)}`)}}else console.log(e.cleanText||e.fullText||"(no content extracted)");console.log(""),console.log(" (use --json for the full structured object)")}}catch(n){console.error(" Error:",n.message),process.exit(1)}finally{q&&await q.close().catch(()=>{})}
74
+ `)}Te&&(le(),process.exit(0));A||(le(),process.exit(1));/linkedin\.com\/(posts|feed|in)\/|linkedin\.com\/.*(activity|update)/i.test(A)||(console.error(`URL doesn't look like a LinkedIn post: ${A}`),console.error("Expected something like:"),console.error(" https://www.linkedin.com/posts/<slug>-activity-<id>-xxxx"),console.error(" https://www.linkedin.com/feed/update/urn:li:activity:<id>"),process.exit(1));k("");k(` read-post \u2014 ${A}`);k("");var W=null;try{let t=await oe(_e);W=t.browser;let s=await W.newPage();await ne(s,t);let e=await K(s,A,{skipComments:ve,commentsMax:$e});e.authWall&&(console.error(" \u26D4 Auth wall \u2014 cookies expired or not logged in."),console.error(" Run 'ilml linkedin login' (or: node src/saveLoginState.mjs) and retry."),process.exit(2));let p=null;if(N){let l=e.author||{},$=e.text||e.cleanText||e.fullText||"",b=($.replace(/\s+/g," ").trim()||"(empty post)").slice(0,80),o=`${l.name||"unknown"} \u2014 ${b}${b.length===80?"\u2026":""}`,y={url:e.url||A,urn:e.urn||null,author:e.author||null,text:e.text||null,postedAt:e.postedAt||null,hashtags:e.hashtags||[],mentions:e.mentions||[],media:e.media||null,capturedAt:new Date().toISOString()},i=[];l.name&&i.push(`**Author:** ${l.name}${l.headline?` \u2014 ${l.headline}`:""}`),l.profileUrl&&i.push(`**Profile:** ${l.profileUrl}`),e.postedAt&&i.push(`**Posted:** ${e.postedAt}`),i.push(`**Source:** ${A}`),i.push(`**Captured:** ${y.capturedAt.slice(0,10)}`),i.push(""),i.push("---"),i.push(""),i.push($||"(post text not extracted)"),e.hashtags?.length&&(i.push(""),i.push(`**Hashtags:** ${e.hashtags.join(" ")}`)),e.mentions?.length&&(i.push(""),i.push(`**Mentions:** ${e.mentions.map(n=>`[${n.label||n.kind}](${n.url})`).join(", ")}`));let I=Object.entries(e.media||{}).filter(([,n])=>n).map(([n])=>n.replace(/^has/,"").toLowerCase());I.length&&(i.push(""),i.push(`**Media:** ${I.join(", ")}`)),i.push(""),i.push("---"),i.push(""),i.push("*Live engagement (reactions / comments / reposts) is intentionally NOT saved here \u2014 those drift. Re-run `read-post --json` on the source URL for current numbers.*"),i.push(""),i.push("```json"),i.push(JSON.stringify(y,null,2)),i.push("```");let E=i.join(`
75
+ `);try{let{graph:n}=await Promise.resolve().then(()=>(re(),ie)),u=await n.addItem(N,{title:o,description:E,tags:["linkedin-post"]}),r=u?.id||u?.item?.id||null;p={parentId:N,nodeId:r,url:r?`https://app.ilivemylife.io/item/${r}`:null},k(""),k(` \u2713 Saved to graph as child of ${N}`),k(` New node: ${r||"(id not returned by SDK)"}`),r&&k(` URL: https://app.ilivemylife.io/item/${r}`),k("")}catch(n){p={parentId:N,error:n.message?.slice(0,200)},console.error(""),console.error(` \u26A0 Failed to save to graph: ${n.message?.slice(0,200)}`),console.error(" The post was still extracted successfully \u2014 printing below."),console.error("")}}let g={...e,...p!==null&&{savedToGraph:p}};if(G&&((await import("fs")).writeFileSync(G,JSON.stringify(g,null,2)),k(` \u2713 Wrote ${(JSON.stringify(g).length/1024).toFixed(1)}KB to ${G}`)),ce)console.log(JSON.stringify(g,null,2));else{let l=e.author||{};console.log(" \u2500\u2500\u2500 POST \u2500\u2500\u2500"),console.log(` Author: ${l.name||"(unknown)"}${l.headline?` \u2014 ${l.headline}`:""}`),l.profileUrl&&console.log(` Profile: ${l.profileUrl}`),e.postedAt&&console.log(` Posted: ${e.postedAt}`);let $=[`${e.reactions||"0"} reactions`,`${e.commentCount||e.comments.length||"0"} comments`,e.repostCount?`${e.repostCount} reposts`:null].filter(Boolean).join(" ");console.log(` Engagement: ${$}`);let b=Object.entries(e.media||{}).filter(([,o])=>o).map(([o])=>o.replace(/^has/,"").toLowerCase());if(b.length&&console.log(` Media: ${b.join(", ")}`),e.hashtags?.length&&console.log(` Hashtags: ${e.hashtags.join(" ")}`),e.mentions?.length&&console.log(` Mentions: ${e.mentions.map(o=>`${o.label||o.url} (${o.kind})`).join(", ")}`),console.log(""),e.commentsTruncated){let o=e.commentsTruncatedReason==="skipComments"?"(comments skipped via --no-comments)":`(showing first ${e.comments.length} of ${e.commentsTruncatedOriginalCount} \u2014 capped via --comments-max)`;console.log(` Note: ${o}`),console.log("")}if(e.comments.length){console.log(e.text||"(post text not parsed \u2014 see cleanText below)"),console.log(""),console.log(` \u2500\u2500\u2500 COMMENTS (${e.comments.length}) \u2500\u2500\u2500`);for(let o of e.comments){let y=o.author||{};console.log(""),console.log(` \u2022 ${y.name||"(unknown)"}${y.headline?` \u2014 ${y.headline}`:""}`),o.text&&console.log(` ${o.text.replace(/\n+/g,`
76
+ `)}`)}}else console.log(e.cleanText||e.fullText||"(no content extracted)");console.log(""),console.log(" (use --json for the full structured object)")}}catch(t){console.error(" Error:",t.message),process.exit(1)}finally{W&&await W.close().catch(()=>{})}