@myk794/adly 1.2.0 → 1.4.3

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.
Files changed (2) hide show
  1. package/adly.js +78 -28
  2. package/package.json +1 -1
package/adly.js CHANGED
@@ -131,7 +131,13 @@ function cmdConfig(args) {
131
131
  async function cmdStatus() {
132
132
  const { token } = loadConfig();
133
133
  if (!token) return fail("önce: adly login <email>");
134
- const me = await api("/api/developer/me", { token });
134
+ let me;
135
+ try {
136
+ me = await api("/api/developer/me", { token });
137
+ } catch {
138
+ return fail("backend'e ulaşılamadı: " + loadConfig().api + " (ağ/zaman aşımı — tekrar dene)");
139
+ }
140
+ if (!me || me.error) return fail("durum alınamadı: " + (me && me.error ? me.error : "bilinmiyor"));
135
141
  console.log(`${sym().dev} ${me.email}`);
136
142
  console.log(` Bakiye: ${me.balance_try} TRY`);
137
143
  console.log(` Gösterim: ${me.impressions}`);
@@ -180,16 +186,17 @@ async function cmdLine() {
180
186
  // Önceki reklamı bu turun token'ıyla faturala.
181
187
  if (st.impressionToken && tokens > 0) {
182
188
  const imp = await api("/api/ads/impression", { method: "POST", token, body: { impressionToken: st.impressionToken, tokens } });
183
- if (imp && imp.ok) { st.balance = imp.balance_try; st.lastTokens = tokens; }
189
+ if (imp && imp.ok) { st.balance = imp.balance_try; all._balance = imp.balance_try; st.lastTokens = tokens; }
184
190
  }
185
191
  // Sonraki tur için yeni reklam al.
186
192
  const s = await api("/api/ads/serve", { token });
187
193
  if (s && !s.empty && s.campaign) {
188
194
  st.line = s.campaign.text; st.url = s.campaign.url; st.impressionToken = s.impressionToken; st.clickPath = s.click_path || null;
189
- // Gösterilen reklamın tıklama linki — `adly open` ve OSC 8 link bunu kullanır.
195
+ // Gösterilen reklamın tıklama linki — `adly open` bunu kullanır.
190
196
  if (s.click_path) all._lastClick = { path: s.click_path, text: st.line, url: st.url };
197
+ setSpinnerVerb(s.campaign.text); // reklamı düşünme spinner'ına yaz (sonraki oturum)
191
198
  }
192
- else { st.line = `${S.bolt} Adly: aktif reklam yok`; st.impressionToken = null; st.clickPath = null; }
199
+ else { st.line = null; st.impressionToken = null; st.clickPath = null; }
193
200
  st.lastSig = sig;
194
201
  all[sessionId] = st; writeJSON(STATE_PATH, all);
195
202
  } else if (!st.impressionToken) {
@@ -198,6 +205,7 @@ async function cmdLine() {
198
205
  if (s && !s.empty && s.campaign) {
199
206
  st.line = s.campaign.text; st.url = s.campaign.url; st.impressionToken = s.impressionToken; st.clickPath = s.click_path || null;
200
207
  if (s.click_path) all._lastClick = { path: s.click_path, text: st.line, url: st.url };
208
+ setSpinnerVerb(s.campaign.text); // reklamı düşünme spinner'ına yaz (sonraki oturum)
201
209
  }
202
210
  if (sig != null) st.lastSig = sig;
203
211
  all[sessionId] = st; writeJSON(STATE_PATH, all);
@@ -206,29 +214,42 @@ async function cmdLine() {
206
214
  // Ağ hatası: son bilinen satırı bas, çökme yok.
207
215
  }
208
216
 
209
- const adText = st.line || S.bolt + " Adly";
217
+ // Kimlik + bakiye önbelleği: e-posta config'te (ham), bakiye state'te global tutulur.
218
+ // (loadConfig() yalnız api/token döndürür; email'i ham dosyadan okuruz.)
219
+ // Eksikse bir kez /me'den çekip kaydet → sonraki render'lar ağ çağrısı yapmaz.
220
+ let raw = readJSON(CONFIG_PATH, {});
221
+ if (!raw.email || all._balance == null) {
222
+ try {
223
+ const me = await api("/api/developer/me", { token });
224
+ if (me && !me.error) {
225
+ if (me.email && !raw.email) { raw = { ...raw, email: me.email }; writeJSON(CONFIG_PATH, raw); }
226
+ if (me.balance_try != null) { all._balance = me.balance_try; writeJSON(STATE_PATH, all); }
227
+ }
228
+ } catch { /* ağ hatası: önbellek neyse onu göster */ }
229
+ }
230
+
210
231
  const fx = useFx();
211
232
  const frame = Math.floor(Date.now() / 130); // ~7-8 fps; statusLine yenilemesi arası kare ilerler
212
233
 
213
- // Reklam metni: fx açıksa kayan parıltı, kapalıysa düz.
214
- let line = fx ? shimmer(adText, frame) : adText;
215
- // İstenirse OSC 8 ile tıklanabilir yap (parıltı SGR kodları anchor içinde kalır).
216
- if (useLinks() && st.clickPath && st.line) {
217
- const url = loadConfig().api + st.clickPath;
218
- line = `\x1b]8;;${url}\x07${line}\x1b]8;;\x07`; // OSC 8: ESC ]8;;URL BEL metin ESC ]8;;BEL
219
- }
220
- // İkon: fx açıksa nabız atar.
221
- const icon = fx ? pulse(S.money, frame) : S.money;
222
- // Baş tarafta dönen spinner, reklamdan sonra parıldayan yıldız (yalnız fx + gerçek reklam).
223
- const lead = fx ? pulse(spinSym(frame), frame) + " " : "";
224
- const tw = fx && st.line ? " " + star(twinkleSym(frame), frame) : "";
225
- // Kazanç rozeti: fx açıksa yeşil nabız.
226
- let bal = "";
227
- if (st.balance) {
228
- const raw = `${S.sep} ${S.lira}${st.balance}`;
229
- bal = fx ? ` ${badge(raw, frame)}` : ` ${raw}`;
234
+ // statusLine = KAZANÇ + İPUCU. (Reklam artık düşünme spinner'ında — spinnerVerbs.)
235
+ // 1) Kazanç: nabız atan ikon + yeşil bakiye rozeti (oturum üstü global önbellek).
236
+ const bal = st.balance || all._balance;
237
+ let earn = "";
238
+ if (bal) {
239
+ earn = fx
240
+ ? `${pulse(S.money, frame)} ${badge(`${S.lira}${bal}`, frame)}`
241
+ : `${S.money} ${S.lira}${bal}`;
230
242
  }
231
- process.stdout.write(`${lead}${icon} ${line}${tw}${bal}`);
243
+
244
+ // 2) İpucu/marka: detay için komutu söyler + satırın Adly'ye ait olduğunu belirtir.
245
+ // "adly status" ember'la vurgulanır; gerisi sönük.
246
+ const hint = fx
247
+ ? dim("use ") + rgb(168, 120, 72) + "adly status" + RST + dim(" for info")
248
+ : "use 'adly status' for info";
249
+
250
+ const sep = ` ${fx ? dim(S.sep) : S.sep} `;
251
+ const out = [earn, hint].filter(Boolean).join(sep);
252
+ process.stdout.write(out);
232
253
  }
233
254
 
234
255
  // OSC 8 tıklanabilir link: env ADLY_LINKS → config.links → varsayılan KAPALI.
@@ -257,6 +278,7 @@ function useFx() {
257
278
  const RST = "\x1b[0m";
258
279
  const BOLD = "\x1b[1m";
259
280
  function rgb(r, g, b) { return `\x1b[38;2;${r | 0};${g | 0};${b | 0}m`; }
281
+ function dim(s) { return rgb(140, 138, 148) + s + RST; }
260
282
  function mix(a, b, t) { return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t]; }
261
283
  // Metni soldan sağa kayan ember parıltısıyla boya (sönük gri zemin, sıcak hale).
262
284
  function shimmer(text, frame) {
@@ -350,10 +372,28 @@ async function cmdWatch() {
350
372
  }
351
373
  }
352
374
 
353
- function cmdInstallStatusline() {
375
+ // Reklamı Claude Code'un DÜŞÜNME SPINNER'INA koy. CC 2.1.143+ resmi ayarı:
376
+ // settings.json'daki `spinnerVerbs` fiil havuzunu ("Baking…") verilen listeyle
377
+ // değiştirir. CC açılışta okur → spinner reklamı sonraki oturumda görünür.
378
+ // Güvenli: settings.json düz JSON değilse (yorum/JSONC → parse hatası) DOKUNMAZ;
379
+ // eski CC sürümü anahtarı sessizce yok sayar. Yalnız değişince yazar.
380
+ function setSpinnerVerb(adText) {
381
+ if (!adText) return;
382
+ try {
383
+ if (!fs.existsSync(CLAUDE_SETTINGS)) return;
384
+ const s = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS, "utf8"));
385
+ const desired = { mode: "replace", verbs: [adText] };
386
+ if (JSON.stringify(s.spinnerVerbs) === JSON.stringify(desired)) return;
387
+ s.spinnerVerbs = desired;
388
+ fs.writeFileSync(CLAUDE_SETTINGS, JSON.stringify(s, null, 2));
389
+ } catch { /* statusLine'ı asla kırma */ }
390
+ }
391
+
392
+ async function cmdInstallStatusline() {
354
393
  const selfPath = path.resolve(__filename);
355
394
  const settings = readJSON(CLAUDE_SETTINGS, {});
356
- if (fs.existsSync(CLAUDE_SETTINGS)) {
395
+ // Yedeği YALNIZ bir kez al (yoksa) — tekrar kurulum temiz/orijinal yedeği ezmesin.
396
+ if (fs.existsSync(CLAUDE_SETTINGS) && !fs.existsSync(CLAUDE_SETTINGS + ".adly-bak")) {
357
397
  fs.copyFileSync(CLAUDE_SETTINGS, CLAUDE_SETTINGS + ".adly-bak");
358
398
  }
359
399
  settings.statusLine = {
@@ -361,19 +401,29 @@ function cmdInstallStatusline() {
361
401
  command: `node "${selfPath}" line`,
362
402
  padding: 0,
363
403
  };
404
+ // İlk reklamı spinner'a yerleştir (girişliyse) → ilk yeni oturumda görünür.
405
+ const { token } = loadConfig();
406
+ if (token) {
407
+ try {
408
+ const s = await api("/api/ads/serve", { token });
409
+ if (s && !s.empty && s.campaign) settings.spinnerVerbs = { mode: "replace", verbs: [s.campaign.text] };
410
+ } catch { /* ağ yoksa adly line sonra doldurur */ }
411
+ }
364
412
  fs.mkdirSync(path.dirname(CLAUDE_SETTINGS), { recursive: true });
365
413
  fs.writeFileSync(CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
366
- console.log(`${sym().ok} Claude Code statusLine'a Adly eklendi.`);
414
+ console.log(`${sym().ok} Claude Code'a Adly eklendi.`);
367
415
  console.log(" Ayar: " + CLAUDE_SETTINGS + " (yedek: .adly-bak)");
368
- console.log(" Yeni bir Claude Code oturumu başlat sponsorlu satır en altta görünecek.");
416
+ console.log(" statusLine (alt satır) = e-posta + kazanç · spinner (düşünme fiili) = reklam.");
417
+ console.log(" Yeni bir Claude Code oturumu başlat — spinner'da reklam, altta kazanç görünür.");
369
418
  }
370
419
 
371
420
  function cmdUninstallStatusline() {
372
421
  const settings = readJSON(CLAUDE_SETTINGS, null);
373
422
  if (!settings) return fail("settings.json yok");
374
423
  delete settings.statusLine;
424
+ delete settings.spinnerVerbs; // spinner reklamını da kaldır → CC stock fiillere döner
375
425
  fs.writeFileSync(CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
376
- console.log(`${sym().ok} statusLine kaldırıldı.`);
426
+ console.log(`${sym().ok} Adly kaldırıldı (statusLine + spinner reklamı). Yeni oturumda CC'nin kendi fiilleri döner.`);
377
427
  }
378
428
 
379
429
  // ---------- yardımcılar ----------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myk794/adly",
3
- "version": "1.2.0",
3
+ "version": "1.4.3",
4
4
  "description": "Adly CLI — Claude Code statusLine'ını sponsorlu satıra çevirir; izledikçe kazanırsın.",
5
5
  "bin": {
6
6
  "adly": "adly.js"