nodebb-plugin-niki-loyalty 1.5.0 → 1.5.5
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/library.js +69 -98
- package/niki-admin.txt +120 -143
- package/niki-kasa.txt +52 -22
- package/niki-prize.txt +200 -0
- package/niki-wallet.txt +415 -0
- package/package.json +1 -1
- package/static/lib/client.js +33 -26
- package/yeedek +313 -0
package/library.js
CHANGED
|
@@ -6,8 +6,12 @@ const routeHelpers = require.main.require('./src/controllers/helpers');
|
|
|
6
6
|
const nconf = require.main.require('nconf');
|
|
7
7
|
const socketHelpers = require.main.require('./src/socket.io/index');
|
|
8
8
|
const SocketPlugins = require.main.require('./src/socket.io/plugins');
|
|
9
|
+
const groups = require.main.require('./src/groups');
|
|
9
10
|
const Plugin = {};
|
|
10
11
|
|
|
12
|
+
// Ödül kullanabilecek gruplar
|
|
13
|
+
const WALLET_GROUPS = ['Premium', 'Lite', 'VIP'];
|
|
14
|
+
|
|
11
15
|
// =========================
|
|
12
16
|
// ⚙️ AYARLAR & KURALLAR (GAME LOGIC)
|
|
13
17
|
// =========================
|
|
@@ -80,7 +84,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
80
84
|
const rule = ACTIONS[actionKey];
|
|
81
85
|
|
|
82
86
|
if (!rule) {
|
|
83
|
-
|
|
87
|
+
|
|
84
88
|
return { success: false, reason: 'unknown_action' };
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -88,7 +92,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
88
92
|
const dailyScoreKey = `niki:daily:${uid}:${today}`;
|
|
89
93
|
const currentDailyScore = parseFloat((await db.getObjectField(dailyScoreKey, 'score')) || 0);
|
|
90
94
|
if (currentDailyScore >= SETTINGS.dailyCap) {
|
|
91
|
-
|
|
95
|
+
|
|
92
96
|
return { success: false, reason: 'daily_cap_reached' };
|
|
93
97
|
}
|
|
94
98
|
|
|
@@ -96,7 +100,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
96
100
|
const actionCountKey = `niki:daily:${uid}:${today}:counts`;
|
|
97
101
|
const currentActionCount = parseInt((await db.getObjectField(actionCountKey, actionKey)) || 0, 10);
|
|
98
102
|
if (currentActionCount >= rule.limit) {
|
|
99
|
-
|
|
103
|
+
|
|
100
104
|
return { success: false, reason: 'action_limit_reached' };
|
|
101
105
|
}
|
|
102
106
|
|
|
@@ -121,9 +125,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
121
125
|
// Logla
|
|
122
126
|
await addUserLog(uid, 'earn', pointsToGive, rule.name);
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// ✅ Kullanıcıya Bildirim Gönder (Socket Emit) - Güçlendirilmiş
|
|
128
|
+
// Kullanıcıya Bildirim Gönder (Socket Emit)
|
|
127
129
|
try {
|
|
128
130
|
if (socketHelpers && socketHelpers.server && socketHelpers.server.sockets) {
|
|
129
131
|
const newTotal = parseFloat((await user.getUserField(uid, 'niki_points')) || 0);
|
|
@@ -132,18 +134,14 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
132
134
|
message: `${rule.name} işleminden <strong style="color:#ffd700">+${pointsToGive} Puan</strong> kazandın!`,
|
|
133
135
|
newTotal: newTotal
|
|
134
136
|
});
|
|
135
|
-
console.log(`[Niki-Loyalty] 📢 Socket bildirim gönderildi. UID: ${uid}`);
|
|
136
|
-
} else {
|
|
137
|
-
console.log(`[Niki-Loyalty] ⚠️ Socket server hazır değil, bildirim gönderilemedi.`);
|
|
138
137
|
}
|
|
139
138
|
} catch (socketErr) {
|
|
140
|
-
console.error(`[Niki-Loyalty] Socket emit hatası:`, socketErr.message);
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
return { success: true, points: pointsToGive };
|
|
144
142
|
|
|
145
143
|
} catch (err) {
|
|
146
|
-
|
|
144
|
+
|
|
147
145
|
return { success: false, reason: 'error', error: err.message };
|
|
148
146
|
}
|
|
149
147
|
}
|
|
@@ -181,67 +179,41 @@ Plugin.onPostCreate = async function (data) {
|
|
|
181
179
|
// 4. BEĞENİ (Like Atma ve Alma) - Spam Korumalı + Debug Loglı
|
|
182
180
|
// NodeBB upvote hook'u { pid, uid, ... } formatında data gönderir (post nesnesi değil!)
|
|
183
181
|
Plugin.onUpvote = async function (data) {
|
|
184
|
-
console.log('[Niki-Loyalty] 👍 Upvote hook tetiklendi. Raw Data:', JSON.stringify(data));
|
|
185
|
-
|
|
186
|
-
// NodeBB bazen farklı formatlar gönderebilir, hepsini kontrol et
|
|
187
182
|
const pid = data.pid || (data.post && data.post.pid);
|
|
188
183
|
const voterUid = data.uid || (data.current && data.current.uid);
|
|
189
184
|
|
|
190
|
-
if (!pid)
|
|
191
|
-
console.log('[Niki-Loyalty] ⚠️ Post PID bulunamadı, işlem iptal.');
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (!voterUid) {
|
|
196
|
-
console.log('[Niki-Loyalty] ⚠️ Voter UID bulunamadı, işlem iptal.');
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
185
|
+
if (!pid || !voterUid) return;
|
|
199
186
|
|
|
200
|
-
// Post sahibini bul (NodeBB upvote hook'u post sahibini göndermez!)
|
|
201
187
|
let postOwnerUid;
|
|
202
188
|
try {
|
|
203
189
|
postOwnerUid = await posts.getPostField(pid, 'uid');
|
|
204
|
-
console.log(`[Niki-Loyalty] Post sahibi bulundu: PID=${pid}, Owner UID=${postOwnerUid}`);
|
|
205
190
|
} catch (err) {
|
|
206
|
-
console.log('[Niki-Loyalty] ⚠️ Post sahibi bulunamadı:', err.message);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (!postOwnerUid) {
|
|
211
|
-
console.log('[Niki-Loyalty] ⚠️ Post sahibi UID boş, işlem iptal.');
|
|
212
191
|
return;
|
|
213
192
|
}
|
|
193
|
+
if (!postOwnerUid) return;
|
|
214
194
|
|
|
215
195
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
216
196
|
|
|
217
|
-
// Like Atan Kazanır
|
|
197
|
+
// Like Atan Kazanır
|
|
218
198
|
const likeGivenKey = `niki:liked:${voterUid}:${today}`;
|
|
219
199
|
const alreadyLiked = await db.isSetMember(likeGivenKey, pid.toString());
|
|
220
200
|
|
|
221
|
-
console.log(`[Niki-Loyalty] Like Atan: UID=${voterUid}, PID=${pid}, Daha önce beğenmiş mi=${alreadyLiked}`);
|
|
222
|
-
|
|
223
201
|
if (!alreadyLiked) {
|
|
224
|
-
|
|
225
|
-
console.log('[Niki-Loyalty] like_given sonuç:', result);
|
|
202
|
+
await awardDailyAction(voterUid, 'like_given');
|
|
226
203
|
await db.setAdd(likeGivenKey, pid.toString());
|
|
227
204
|
await db.expire(likeGivenKey, 86400);
|
|
228
205
|
}
|
|
229
206
|
|
|
230
|
-
// Like Alan Kazanır (
|
|
207
|
+
// Like Alan Kazanır (kendine beğeni atamaz)
|
|
231
208
|
if (postOwnerUid && String(postOwnerUid) !== String(voterUid)) {
|
|
232
209
|
const likeTakenKey = `niki:liked_taken:${postOwnerUid}:${today}`;
|
|
233
210
|
const alreadyTaken = await db.isSetMember(likeTakenKey, pid.toString());
|
|
234
211
|
|
|
235
|
-
console.log(`[Niki-Loyalty] Like Alan: UID=${postOwnerUid}, PID=${pid}, Daha önce puan almış mı=${alreadyTaken}`);
|
|
236
|
-
|
|
237
212
|
if (!alreadyTaken) {
|
|
238
|
-
|
|
239
|
-
console.log('[Niki-Loyalty] like_taken sonuç:', result);
|
|
213
|
+
await awardDailyAction(postOwnerUid, 'like_taken');
|
|
240
214
|
await db.setAdd(likeTakenKey, pid.toString());
|
|
241
215
|
await db.expire(likeTakenKey, 86400);
|
|
242
216
|
}
|
|
243
|
-
} else {
|
|
244
|
-
console.log('[Niki-Loyalty] ⚠️ Kullanıcı kendi postunu beğenmiş veya post sahibi bulunamadı. Post owner:', postOwnerUid, 'Voter:', voterUid);
|
|
245
217
|
}
|
|
246
218
|
};
|
|
247
219
|
|
|
@@ -260,7 +232,6 @@ Plugin.onGroupJoin = async function (data) {
|
|
|
260
232
|
const flagKey = `niki:group_bonus:${uid}:${groupName}`;
|
|
261
233
|
const alreadyClaimed = await db.get(flagKey);
|
|
262
234
|
if (alreadyClaimed) {
|
|
263
|
-
console.log(`[Niki-Loyalty] Grup bonusu zaten alınmış. UID: ${uid}, Group: ${groupName}`);
|
|
264
235
|
return;
|
|
265
236
|
}
|
|
266
237
|
|
|
@@ -268,8 +239,6 @@ Plugin.onGroupJoin = async function (data) {
|
|
|
268
239
|
await db.set(flagKey, '1');
|
|
269
240
|
await addUserLog(uid, 'earn', bonus, `${groupName} Grubu Katılım Bonusu 🎉`);
|
|
270
241
|
|
|
271
|
-
console.log(`[Niki-Loyalty] ✅ GRUP BONUSU! UID: ${uid}, Group: ${groupName}, Points: +${bonus}`);
|
|
272
|
-
|
|
273
242
|
// Socket bildirimi
|
|
274
243
|
try {
|
|
275
244
|
if (socketHelpers && socketHelpers.server && socketHelpers.server.sockets) {
|
|
@@ -279,10 +248,8 @@ Plugin.onGroupJoin = async function (data) {
|
|
|
279
248
|
});
|
|
280
249
|
}
|
|
281
250
|
} catch (socketErr) {
|
|
282
|
-
console.error('[Niki-Loyalty] Socket emit hatası:', socketErr.message);
|
|
283
251
|
}
|
|
284
252
|
} catch (err) {
|
|
285
|
-
console.error('[Niki-Loyalty] Grup bonus hatası:', err);
|
|
286
253
|
}
|
|
287
254
|
};
|
|
288
255
|
|
|
@@ -293,33 +260,6 @@ Plugin.init = async function (params) {
|
|
|
293
260
|
const router = params.router;
|
|
294
261
|
const middleware = params.middleware;
|
|
295
262
|
|
|
296
|
-
// 🔄 1 SEFERLİK MİGRASYON: 180+ puanlı herkesten 50 puan düş
|
|
297
|
-
try {
|
|
298
|
-
const migrationKey = 'niki:migration:deduct50_from_180plus_v1';
|
|
299
|
-
const alreadyDone = await db.get(migrationKey);
|
|
300
|
-
if (!alreadyDone) {
|
|
301
|
-
console.log('[Niki-Loyalty] Migration başlıyor: 180+ puanlı kullanıcılardan 50 puan düşülecek...');
|
|
302
|
-
const allUids = await db.getSortedSetRange('users:joindate', 0, -1);
|
|
303
|
-
if (allUids && allUids.length > 0) {
|
|
304
|
-
const usersData = await user.getUsersFields(allUids, ['uid', 'niki_points', 'username']);
|
|
305
|
-
let affected = 0;
|
|
306
|
-
for (const u of usersData) {
|
|
307
|
-
const pts = parseFloat(u.niki_points || 0);
|
|
308
|
-
if (pts >= 180) {
|
|
309
|
-
await user.decrementUserFieldBy(u.uid, 'niki_points', 50);
|
|
310
|
-
await addUserLog(u.uid, 'admin_adjust', 50, 'Sistem düzenlemesi: -50 puan (dengeleme)');
|
|
311
|
-
affected++;
|
|
312
|
-
console.log(`[Niki-Loyalty] Migration: ${u.username} (UID:${u.uid}) ${pts} → ${pts - 50} puan`);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
console.log(`[Niki-Loyalty] Migration tamamlandı. Etkilenen kullanıcı: ${affected}`);
|
|
316
|
-
}
|
|
317
|
-
await db.set(migrationKey, Date.now().toString());
|
|
318
|
-
}
|
|
319
|
-
} catch (migErr) {
|
|
320
|
-
console.error('[Niki-Loyalty] Migration hatası:', migErr);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
263
|
// 1) HEARTBEAT (Artık "Okuma" Puanı veriyor)
|
|
324
264
|
// Client-side script her 30-60 saniyede bir bu adrese istek atmalıdır.
|
|
325
265
|
router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
|
|
@@ -368,13 +308,18 @@ Plugin.init = async function (params) {
|
|
|
368
308
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
369
309
|
|
|
370
310
|
// Veritabanından verileri çek
|
|
371
|
-
const [userData, dailyData, actionCounts, historyRaw] = await Promise.all([
|
|
311
|
+
const [userData, dailyData, actionCounts, historyRaw, memberChecks] = await Promise.all([
|
|
372
312
|
user.getUserFields(uid, ['niki_points']),
|
|
373
313
|
db.getObject(`niki:daily:${uid}:${today}`),
|
|
374
|
-
db.getObject(`niki:daily:${uid}:${today}:counts`),
|
|
314
|
+
db.getObject(`niki:daily:${uid}:${today}:counts`),
|
|
375
315
|
db.getListRange(`niki:activity:${uid}`, 0, -1),
|
|
316
|
+
Promise.all(WALLET_GROUPS.map(g => groups.isMember(uid, g))),
|
|
376
317
|
]);
|
|
377
318
|
|
|
319
|
+
// Kullanıcı WALLET_GROUPS'dan herhangi birinde mi?
|
|
320
|
+
const canRedeem = memberChecks.some(Boolean);
|
|
321
|
+
const userGroup = canRedeem ? WALLET_GROUPS[memberChecks.indexOf(true)] : null;
|
|
322
|
+
|
|
378
323
|
const dailyScore = parseFloat(dailyData?.score || 0);
|
|
379
324
|
let dailyPercent = (dailyScore / SETTINGS.dailyCap) * 100;
|
|
380
325
|
if (dailyPercent > 100) dailyPercent = 100;
|
|
@@ -386,9 +331,13 @@ Plugin.init = async function (params) {
|
|
|
386
331
|
dailyScore,
|
|
387
332
|
dailyCap: SETTINGS.dailyCap,
|
|
388
333
|
dailyPercent,
|
|
389
|
-
counts: actionCounts || {},
|
|
334
|
+
counts: actionCounts || {},
|
|
335
|
+
actions: ACTIONS,
|
|
390
336
|
history,
|
|
391
337
|
rewards: REWARDS,
|
|
338
|
+
canRedeem,
|
|
339
|
+
userGroup,
|
|
340
|
+
walletGroups: WALLET_GROUPS,
|
|
392
341
|
});
|
|
393
342
|
} catch (err) {
|
|
394
343
|
return res.status(500).json({ points: 0, history: [] });
|
|
@@ -499,7 +448,6 @@ Plugin.init = async function (params) {
|
|
|
499
448
|
hasMore: enriched.length > 100
|
|
500
449
|
});
|
|
501
450
|
} catch (e) {
|
|
502
|
-
console.error('[Niki-Loyalty] Kasa history error:', e);
|
|
503
451
|
return res.status(500).json({ error: 'Sunucu hatası' });
|
|
504
452
|
}
|
|
505
453
|
});
|
|
@@ -508,43 +456,63 @@ Plugin.init = async function (params) {
|
|
|
508
456
|
router.post('/api/niki-loyalty/generate-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
509
457
|
try {
|
|
510
458
|
const uid = req.uid;
|
|
459
|
+
|
|
460
|
+
// Grup kontrolü
|
|
461
|
+
const memberChecks = await Promise.all(WALLET_GROUPS.map(g => groups.isMember(uid, g)));
|
|
462
|
+
if (!memberChecks.some(Boolean)) {
|
|
463
|
+
return res.json({ success: false, message: 'Ödül kullanmak için Premium, Lite veya VIP grubuna katılmalısın.' });
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const rewardIndex = parseInt(req.body.rewardIndex, 10);
|
|
511
467
|
const points = parseFloat((await user.getUserField(uid, 'niki_points')) || 0);
|
|
512
|
-
const minCost = REWARDS[REWARDS.length - 1].cost; // En ucuz ödül
|
|
513
468
|
|
|
514
|
-
|
|
515
|
-
|
|
469
|
+
// Seçilen ödülü bul
|
|
470
|
+
if (isNaN(rewardIndex) || rewardIndex < 0 || rewardIndex >= REWARDS.length) {
|
|
471
|
+
return res.json({ success: false, message: 'Geçersiz ödül seçimi.' });
|
|
472
|
+
}
|
|
473
|
+
const selectedReward = REWARDS[rewardIndex];
|
|
474
|
+
|
|
475
|
+
if (!TEST_MODE_UNLIMITED && points < selectedReward.cost) {
|
|
476
|
+
return res.json({ success: false, message: `Yetersiz Puan. ${selectedReward.name} için ${selectedReward.cost} puan gerekli.` });
|
|
516
477
|
}
|
|
517
478
|
const token = crypto.randomBytes(16).toString('hex');
|
|
518
|
-
|
|
479
|
+
// Token'a kullanıcı ve seçilen ödül bilgisini kaydet
|
|
480
|
+
await db.setObject(`niki:qr:${token}`, { uid: String(uid), rewardIndex: String(rewardIndex) });
|
|
519
481
|
await db.expire(`niki:qr:${token}`, 120); // 2 dakika geçerli
|
|
520
|
-
return res.json({ success: true, token });
|
|
482
|
+
return res.json({ success: true, token, rewardName: selectedReward.name, rewardCost: selectedReward.cost });
|
|
521
483
|
} catch (e) { return res.status(500).json({ success: false }); }
|
|
522
484
|
});
|
|
523
485
|
|
|
524
486
|
// 5) QR TARATMA (Kasa İşlemi)
|
|
525
487
|
router.post('/api/niki-loyalty/scan-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
526
|
-
// ... (Mevcut kodunun aynısı)
|
|
527
488
|
try {
|
|
528
489
|
const token = req.body.token;
|
|
529
490
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
530
491
|
const isMod = await user.isGlobalModerator(req.uid);
|
|
531
492
|
if (!isAdmin && !isMod) return res.status(403).json({ success: false, message: 'Yetkisiz' });
|
|
532
493
|
|
|
533
|
-
const
|
|
534
|
-
if (!
|
|
494
|
+
const qrData = await db.getObject(`niki:qr:${token}`);
|
|
495
|
+
if (!qrData || !qrData.uid) return res.json({ success: false, message: 'Geçersiz Kod' });
|
|
535
496
|
|
|
497
|
+
const custUid = qrData.uid;
|
|
498
|
+
const rewardIndex = parseInt(qrData.rewardIndex, 10);
|
|
536
499
|
const pts = parseFloat(await user.getUserField(custUid, 'niki_points') || 0);
|
|
537
500
|
|
|
538
501
|
let selectedReward = null;
|
|
539
502
|
if (!TEST_MODE_UNLIMITED) {
|
|
540
|
-
|
|
541
|
-
|
|
503
|
+
// Token'daki ödül index'ini kullan
|
|
504
|
+
if (!isNaN(rewardIndex) && rewardIndex >= 0 && rewardIndex < REWARDS.length) {
|
|
505
|
+
selectedReward = REWARDS[rewardIndex];
|
|
506
|
+
} else {
|
|
507
|
+
// Fallback: en yüksek ödülü seç
|
|
508
|
+
for (const r of REWARDS) {
|
|
509
|
+
if (pts >= r.cost) { selectedReward = r; break; }
|
|
510
|
+
}
|
|
542
511
|
}
|
|
543
512
|
if (!selectedReward) return res.json({ success: false, message: 'Puan Yetersiz' });
|
|
544
513
|
} else { selectedReward = REWARDS[0]; }
|
|
545
514
|
|
|
546
515
|
if (!TEST_MODE_UNLIMITED) {
|
|
547
|
-
// Negatif bakiye kontrolü - önce kontrol, sonra düş
|
|
548
516
|
if (pts < selectedReward.cost) {
|
|
549
517
|
await db.delete(`niki:qr:${token}`);
|
|
550
518
|
return res.json({ success: false, message: 'Puan yetersiz, işlem iptal edildi.' });
|
|
@@ -603,13 +571,11 @@ Plugin.adminGetUsers = async function (socket, data) {
|
|
|
603
571
|
|
|
604
572
|
// TÜM kullanıcıları al (limit yok: -1)
|
|
605
573
|
const uids = await db.getSortedSetRevRange('users:joindate', 0, -1);
|
|
606
|
-
console.log('[Niki-Admin] Çekilen UID sayısı:', uids ? uids.length : 0);
|
|
607
574
|
|
|
608
575
|
if (!uids || uids.length === 0) return [];
|
|
609
576
|
|
|
610
577
|
// Kullanıcı bilgilerini al
|
|
611
578
|
const usersData = await user.getUsersFields(uids, ['uid', 'username', 'userslug', 'picture', 'niki_points', 'icon:bgColor']);
|
|
612
|
-
console.log('[Niki-Admin] Kullanıcı verisi alındı:', usersData ? usersData.length : 0);
|
|
613
579
|
|
|
614
580
|
// Puanları işle ve sırala (puanı yüksek olan önce)
|
|
615
581
|
const result = usersData
|
|
@@ -624,10 +590,8 @@ Plugin.adminGetUsers = async function (socket, data) {
|
|
|
624
590
|
}))
|
|
625
591
|
.sort((a, b) => b.points - a.points); // Yüksekten düşüğe sırala
|
|
626
592
|
|
|
627
|
-
console.log('[Niki-Admin] Döndürülen kullanıcı sayısı:', result.length);
|
|
628
593
|
return result;
|
|
629
594
|
} catch (err) {
|
|
630
|
-
console.error('[Niki-Admin] adminGetUsers HATA:', err.message);
|
|
631
595
|
throw err;
|
|
632
596
|
}
|
|
633
597
|
};
|
|
@@ -650,15 +614,21 @@ Plugin.socketScanQR = async function (socket, data) {
|
|
|
650
614
|
const token = data.token;
|
|
651
615
|
if (!token) throw new Error('Geçersiz Token');
|
|
652
616
|
|
|
653
|
-
const
|
|
654
|
-
if (!
|
|
617
|
+
const qrData = await db.getObject(`niki:qr:${token}`);
|
|
618
|
+
if (!qrData || !qrData.uid) throw new Error('QR Kod Geçersiz veya Süresi Dolmuş');
|
|
655
619
|
|
|
620
|
+
const custUid = qrData.uid;
|
|
621
|
+
const rewardIndex = parseInt(qrData.rewardIndex, 10);
|
|
656
622
|
const pts = parseFloat((await user.getUserField(custUid, 'niki_points')) || 0);
|
|
657
623
|
|
|
658
624
|
let selectedReward = null;
|
|
659
625
|
if (!TEST_MODE_UNLIMITED) {
|
|
660
|
-
|
|
661
|
-
|
|
626
|
+
if (!isNaN(rewardIndex) && rewardIndex >= 0 && rewardIndex < REWARDS.length) {
|
|
627
|
+
selectedReward = REWARDS[rewardIndex];
|
|
628
|
+
} else {
|
|
629
|
+
for (const r of REWARDS) {
|
|
630
|
+
if (pts >= r.cost) { selectedReward = r; break; }
|
|
631
|
+
}
|
|
662
632
|
}
|
|
663
633
|
if (!selectedReward) throw new Error('Puan Yetersiz');
|
|
664
634
|
} else { selectedReward = REWARDS[0]; }
|
|
@@ -758,6 +728,7 @@ Plugin.adminManagePoints = async function (socket, data) {
|
|
|
758
728
|
// Denetim Logu
|
|
759
729
|
const auditLog = { ts: Date.now(), adminUid: uid, adminName: adminUserData.username, targetUid: targetUid, action: action, amount: amount, reason: reason };
|
|
760
730
|
await db.listAppend('niki:audit:admin_points', JSON.stringify(auditLog));
|
|
731
|
+
await db.listTrim('niki:audit:admin_points', -500, -1);
|
|
761
732
|
|
|
762
733
|
const newPoints = await user.getUserField(targetUid, 'niki_points');
|
|
763
734
|
return { success: true, newPoints: parseFloat(newPoints) };
|