social-agent-cli 1.1.8 → 1.2.1
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/ai/planner.ts +3 -2
- package/ai/runner.ts +30 -0
- package/cli.ts +18 -6
- package/core/types.ts +1 -1
- package/maps/linkedin_post.json +3 -7
- package/maps/x_post.json +3 -3
- package/package.json +3 -2
package/ai/planner.ts
CHANGED
|
@@ -142,8 +142,9 @@ GÖREV: Bu komutu yerine getirmek için bir çalıştırma planı oluştur.
|
|
|
142
142
|
Kurallar:
|
|
143
143
|
- Mevcut map varsa "use_map" kullan, mapAction'a action adını yaz
|
|
144
144
|
- Mevcut map yoksa "learn_new" kullan, AI otomatik öğrenecek
|
|
145
|
-
-
|
|
146
|
-
-
|
|
145
|
+
- Mevcut map'in parametrelerini kontrol et. Komutta dosya/görsel/fotoğraf varsa ama map'te {{IMAGE}} parametresi yoksa, bu map yetersizdir - "learn_new" ile görsel destekli versiyonunu öğret
|
|
146
|
+
- Parametreleri doldur ({{TWEET_URL}}, {{USERNAME}}, {{CONTENT}}, {{IMAGE}} vb.)
|
|
147
|
+
- Belirli kişi/URL verilmemişse platformun keşif/öneri sayfalarını kullan
|
|
147
148
|
- Tekrar eden işlemler için "repeat" kullan
|
|
148
149
|
- Adımları doğru sırada planla
|
|
149
150
|
- Kısa ve net analiz yaz`;
|
package/ai/runner.ts
CHANGED
|
@@ -331,5 +331,35 @@ async function executeMapStep(
|
|
|
331
331
|
await page.keyboard.press(step.key || "Enter");
|
|
332
332
|
if (step.waitMs) await page.waitForTimeout(step.waitMs);
|
|
333
333
|
break;
|
|
334
|
+
|
|
335
|
+
case "upload": {
|
|
336
|
+
// Dosya yükleme - hidden file input'a dosya set et
|
|
337
|
+
const filePath = rp(step.value || "{{IMAGE}}");
|
|
338
|
+
if (!filePath || filePath.includes("{{")) break; // dosya yoksa atla
|
|
339
|
+
|
|
340
|
+
let uploaded = false;
|
|
341
|
+
for (const sel of selectors) {
|
|
342
|
+
try {
|
|
343
|
+
const input = await page.waitForSelector(sel, { timeout: 5000 });
|
|
344
|
+
await input.setInputFiles(filePath);
|
|
345
|
+
uploaded = true;
|
|
346
|
+
break;
|
|
347
|
+
} catch {}
|
|
348
|
+
}
|
|
349
|
+
if (!uploaded) {
|
|
350
|
+
// Hidden input bulunamazsa, file chooser ile dene
|
|
351
|
+
try {
|
|
352
|
+
const [fileChooser] = await Promise.all([
|
|
353
|
+
page.waitForEvent("filechooser", { timeout: 5000 }),
|
|
354
|
+
page.click(selectors[0] || "[data-testid='fileInput']"),
|
|
355
|
+
]);
|
|
356
|
+
await fileChooser.setFiles(filePath);
|
|
357
|
+
uploaded = true;
|
|
358
|
+
} catch {}
|
|
359
|
+
}
|
|
360
|
+
if (!uploaded) throw new Error(`Upload failed: ${filePath}`);
|
|
361
|
+
if (step.waitMs) await page.waitForTimeout(step.waitMs);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
334
364
|
}
|
|
335
365
|
}
|
package/cli.ts
CHANGED
|
@@ -131,17 +131,29 @@ async function cmdTest(platform: string) {
|
|
|
131
131
|
|
|
132
132
|
function cmdStatus() {
|
|
133
133
|
const config = loadConfig();
|
|
134
|
-
const
|
|
134
|
+
const { getSavedProfile } = require("./core/profiles.js");
|
|
135
135
|
|
|
136
136
|
console.log("\n Platform Durumu\n ───────────────");
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
|
|
138
|
+
// API platformları - config'de varsa göster
|
|
139
|
+
if (config.mastodon) console.log(` 🔗 mastodon (api) → ${config.mastodon.instanceUrl}`);
|
|
140
|
+
if (config.bluesky) console.log(` 🔗 bluesky (api) → ${config.bluesky.identifier}`);
|
|
141
|
+
if (config.telegram) console.log(` 🔗 telegram (api)`);
|
|
142
|
+
|
|
143
|
+
// Browser platformları - sadece login olmuşları göster
|
|
144
|
+
for (const [name] of Object.entries(BROWSER_PLATFORMS)) {
|
|
145
|
+
const profile = getSavedProfile(name);
|
|
146
|
+
if (profile) {
|
|
147
|
+
console.log(` 🌐 ${name} (browser) → ${profile.name} (${profile.email})`);
|
|
148
|
+
}
|
|
140
149
|
}
|
|
141
150
|
|
|
142
|
-
|
|
151
|
+
const hasAny = config.mastodon || config.bluesky || config.telegram ||
|
|
152
|
+
Object.keys(BROWSER_PLATFORMS).some(p => getSavedProfile(p));
|
|
153
|
+
|
|
154
|
+
if (!hasAny) {
|
|
143
155
|
console.log(" Hiçbir platform yapılandırılmamış.");
|
|
144
|
-
console.log("
|
|
156
|
+
console.log(" sa setup çalıştır.");
|
|
145
157
|
}
|
|
146
158
|
console.log();
|
|
147
159
|
}
|
package/core/types.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface SelectorMap {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export interface SelectorStep {
|
|
25
|
-
action: "click" | "type" | "wait" | "screenshot" | "keypress" | "goto";
|
|
25
|
+
action: "click" | "type" | "wait" | "screenshot" | "keypress" | "goto" | "upload";
|
|
26
26
|
description: string;
|
|
27
27
|
selector?: string;
|
|
28
28
|
value?: string; // for type action
|
package/maps/linkedin_post.json
CHANGED
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"fallbackSelectors": [
|
|
14
14
|
"[aria-label*='Start a post']",
|
|
15
15
|
"[aria-label*='Gönderi başlat']",
|
|
16
|
-
"button[aria-label*='post']"
|
|
17
|
-
".share-box-feed-entry__trigger"
|
|
16
|
+
"button[aria-label*='post']"
|
|
18
17
|
]
|
|
19
18
|
},
|
|
20
19
|
{
|
|
@@ -29,9 +28,7 @@
|
|
|
29
28
|
"fallbackSelectors": [
|
|
30
29
|
"[role='textbox'][contenteditable='true']",
|
|
31
30
|
".ql-editor[contenteditable='true']",
|
|
32
|
-
"[aria-label*='Metin düzenleyici']"
|
|
33
|
-
"[data-placeholder*='What do you want']",
|
|
34
|
-
"[data-placeholder*='Ne hakkında']"
|
|
31
|
+
"[aria-label*='Metin düzenleyici']"
|
|
35
32
|
]
|
|
36
33
|
},
|
|
37
34
|
{
|
|
@@ -57,8 +54,7 @@
|
|
|
57
54
|
"[aria-label='Post']",
|
|
58
55
|
"[aria-label='Gönder']",
|
|
59
56
|
"button[aria-label*='Post']",
|
|
60
|
-
"button[aria-label*='Paylaş']"
|
|
61
|
-
"button.artdeco-button--primary[type='button']"
|
|
57
|
+
"button[aria-label*='Paylaş']"
|
|
62
58
|
]
|
|
63
59
|
},
|
|
64
60
|
{
|
package/maps/x_post.json
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"fallbackSelectors": [
|
|
14
14
|
"a[href='/compose/post']",
|
|
15
15
|
"[aria-label*='Post'][role='link']",
|
|
16
|
-
"[aria-label*='Gönder'][role='link']"
|
|
16
|
+
"[aria-label*='Gönder'][role='link']",
|
|
17
|
+
"[data-testid='FloatingActionButton']"
|
|
17
18
|
]
|
|
18
19
|
},
|
|
19
20
|
{
|
|
@@ -27,8 +28,7 @@
|
|
|
27
28
|
"selector": "[data-testid='tweetTextarea_0']",
|
|
28
29
|
"fallbackSelectors": [
|
|
29
30
|
"[role='textbox'][contenteditable='true']",
|
|
30
|
-
".public-DraftEditor-content"
|
|
31
|
-
"[data-testid='tweetTextarea_0RichTextInputContainer'] [contenteditable]"
|
|
31
|
+
".public-DraftEditor-content"
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
{
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "social-agent-cli",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "AI-powered social media agent - free APIs + browser automation with self-healing selectors",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"social-agent": "./bin/social-agent.js"
|
|
7
|
+
"social-agent": "./bin/social-agent.js",
|
|
8
|
+
"sa": "./bin/social-agent.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
11
|
"postinstall": "node bin/postinstall.js",
|