SPB Git

spb/admin-ka

Public

Social: publication FB fiabilisee sur le noeud

- auto-clic Basculer (agir en tant que Page) si vue Gerer la Page
- fermeture auto des boites Plus tard / boost / onboarding
- fin de publication detectee sur disparition du composeur (pas un dialogue quelconque)
- verifie: post vrai-prix publie en direct depuis le noeud

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Aug 23, 2026) parent 0604e62 Browse files

1 changed file +65 −5

Unified Split
modified server/social.js +65 −5
@@ -139,6 +139,23 @@ async function gotoPage() {
139 `tell application "Safari"\nwith timeout of 20 seconds\nset URL of tab 1 of window id ${fbWinId} to "${PAGE_URL}"\nend timeout\nend tell`]); 139 `tell application "Safari"\nwith timeout of 20 seconds\nset URL of tab 1 of window id ${fbWinId} to "${PAGE_URL}"\nend timeout\nend tell`]);
140 } 140 }
141 141
142+// ferme les boîtes FB non bloquantes (« Plus tard », boost, onboarding…)
143+const DISMISS_JS = `(function(){
144+ var labels=['Plus tard','Pas maintenant','Non merci','Ignorer','Peut-être plus tard','Fermer','Terminer','OK','Continuer','Passer'];
145+ var clicked='';
146+ document.querySelectorAll('div[role=dialog] [role=button], [aria-label]').forEach(function(e){
147+ if(clicked) return;
148+ var t=(e.innerText||'').trim(); var al=e.getAttribute('aria-label')||'';
149+ for(var i=0;i<labels.length;i++){
150+ if(t===labels[i] || al===labels[i] || al==='Fermer' || al==='Fermer la boîte de dialogue'){
151+ ['mousedown','mouseup','click'].forEach(function(ev){e.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));});
152+ clicked=labels[i]||al; break;
153+ }
154+ }
155+ });
156+ return clicked||'NONE';
157+})();`;
158+
142 async function pollJS(jsCode, want, tries = 12, delay = 4000) { 159 async function pollJS(jsCode, want, tries = 12, delay = 4000) {
143 let last = ''; 160 let last = '';
144 for (let i = 0; i < tries; i++) { 161 for (let i = 0; i < tries; i++) {
@@ -149,6 +166,17 @@ async function pollJS(jsCode, want, tries = 12, delay = 4000) {
149 return last; 166 return last;
150 } 167 }
151 168
169+async function dismissModals(times) {
170+ times = times || 3;
171+ let any = false;
172+ for (let i = 0; i < times; i++) {
173+ let r = 'NONE';
174+ try { r = await osaJS(DISMISS_JS); } catch {}
175+ if (r && r !== 'NONE') { any = true; await sleep(1500); } else break;
176+ }
177+ return any;
178+}
179+
152 // vérifie que Facebook est connecté (sinon, l'auto-post est mis en pause) 180 // vérifie que Facebook est connecté (sinon, l'auto-post est mis en pause)
153 export function fbLoginState() { return withSafari(_fbLoginState); } 181 export function fbLoginState() { return withSafari(_fbLoginState); }
154 async function _fbLoginState() { 182 async function _fbLoginState() {
@@ -184,7 +212,24 @@ async function _publishToPage(caption, imagePath) {
184 ['mousedown','mouseup','click'].forEach(function(ev){btn.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));}); 212 ['mousedown','mouseup','click'].forEach(function(ev){btn.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));});
185 return 'opened'; 213 return 'opened';
186 })();`; 214 })();`;
187− const r1 = await pollJS(openComposer, v => v === 'opened', 10, 5000); 215+ // La Page peut s'ouvrir en vue « Gérer la Page » (contexte profil perso) sans
216+ // composeur : cliquer « Basculer » pour agir en tant que Page, puis réessayer.
217+ const basculer = `(function(){
218+ var btn=null;
219+ document.querySelectorAll('[role=button]').forEach(function(e){
220+ var t=(e.innerText||'').trim();
221+ if(!btn && (t==='Basculer' || t.indexOf('Basculer sur la Page')===0)) btn=e;
222+ });
223+ if(!btn) return 'NO_BTN';
224+ ['mousedown','mouseup','click'].forEach(function(ev){btn.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));});
225+ return 'switched';
226+ })();`;
227+ let r1 = await pollJS(openComposer, v => v === 'opened', 4, 4000);
228+ if (r1 !== 'opened') {
229+ const sw = await osaJS(basculer);
230+ if (sw === 'switched') { await sleep(9000); await dismissModals(3); }
231+ r1 = await pollJS(openComposer, v => v === 'opened', 8, 5000);
232+ }
188 if (r1 !== 'opened') throw new Error('composeur introuvable (' + r1 + ')'); 233 if (r1 !== 'opened') throw new Error('composeur introuvable (' + r1 + ')');
189 await sleep(3000); 234 await sleep(3000);
190 235
@@ -263,10 +308,25 @@ async function _publishToPage(caption, imagePath) {
263 const pub = await pollJS(clickBtn('Publier'), v => v === 'clicked', 6, 4000); 308 const pub = await pollJS(clickBtn('Publier'), v => v === 'clicked', 6, 4000);
264 if (pub !== 'clicked') throw new Error('bouton Publier indisponible (' + pub + ')'); 309 if (pub !== 'clicked') throw new Error('bouton Publier indisponible (' + pub + ')');
265 310
266− // 6) attendre la fermeture du dialogue (upload lent) 311+ // 6) attendre la disparition du COMPOSEUR (= publication soumise). Une boîte
267− const closedJS = `document.querySelector('div[role=dialog]') ? 'OPEN' : 'CLOSED';`; 312+ // « Plus tard » / boost peut apparaître ensuite : on la ferme, elle n'indique
268− const closed = await pollJS(closedJS, v => v === 'CLOSED', 18, 8000); 313+ // PAS un échec. On juge le succès sur l'absence de la zone de texte du composeur.
269− if (closed !== 'CLOSED') throw new Error('dialogue non fermé après Publier (doute — ne pas retenter)'); 314+ const composerGoneJS = `(function(){
315+ var open=false;
316+ document.querySelectorAll('div[role=dialog]').forEach(function(d){
317+ if(d.querySelector('div[contenteditable=true][role=textbox]')) open=true;
318+ });
319+ return open ? 'OPEN' : 'GONE';
320+ })();`;
321+ let gone = 'OPEN';
322+ for (let i = 0; i < 18; i++) {
323+ await sleep(8000);
324+ await dismissModals(2); // ferme toute boîte non bloquante en route
325+ try { gone = await osaJS(composerGoneJS); } catch (e) { gone = 'ERR'; }
326+ if (gone === 'GONE') break;
327+ }
328+ await dismissModals(3); // ferme la boîte « Plus tard » finale
329+ if (gone !== 'GONE') throw new Error('composeur toujours ouvert après Publier (doute — ne pas retenter)');
270 return true; 330 return true;
271 } 331 }
272 332
273 333
Menu

Theme