nodebb-plugin-niki-loyalty 1.5.1 → 1.5.6
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 +51 -77
- package/package.json +1 -1
- package/static/lib/client.js +0 -10
package/library.js
CHANGED
|
@@ -32,7 +32,7 @@ const ACTIONS = {
|
|
|
32
32
|
// Grup Katılım Bonusları
|
|
33
33
|
const GROUP_BONUSES = {
|
|
34
34
|
'Premium': 30,
|
|
35
|
-
'VIP':
|
|
35
|
+
'VIP': 60,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
// Ödüller
|
|
@@ -84,7 +84,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
84
84
|
const rule = ACTIONS[actionKey];
|
|
85
85
|
|
|
86
86
|
if (!rule) {
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
return { success: false, reason: 'unknown_action' };
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -92,7 +92,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
92
92
|
const dailyScoreKey = `niki:daily:${uid}:${today}`;
|
|
93
93
|
const currentDailyScore = parseFloat((await db.getObjectField(dailyScoreKey, 'score')) || 0);
|
|
94
94
|
if (currentDailyScore >= SETTINGS.dailyCap) {
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
return { success: false, reason: 'daily_cap_reached' };
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -100,7 +100,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
100
100
|
const actionCountKey = `niki:daily:${uid}:${today}:counts`;
|
|
101
101
|
const currentActionCount = parseInt((await db.getObjectField(actionCountKey, actionKey)) || 0, 10);
|
|
102
102
|
if (currentActionCount >= rule.limit) {
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
return { success: false, reason: 'action_limit_reached' };
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -125,9 +125,7 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
125
125
|
// Logla
|
|
126
126
|
await addUserLog(uid, 'earn', pointsToGive, rule.name);
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// ✅ Kullanıcıya Bildirim Gönder (Socket Emit) - Güçlendirilmiş
|
|
128
|
+
// Kullanıcıya Bildirim Gönder (Socket Emit)
|
|
131
129
|
try {
|
|
132
130
|
if (socketHelpers && socketHelpers.server && socketHelpers.server.sockets) {
|
|
133
131
|
const newTotal = parseFloat((await user.getUserField(uid, 'niki_points')) || 0);
|
|
@@ -136,18 +134,14 @@ async function awardDailyAction(uid, actionKey) {
|
|
|
136
134
|
message: `${rule.name} işleminden <strong style="color:#ffd700">+${pointsToGive} Puan</strong> kazandın!`,
|
|
137
135
|
newTotal: newTotal
|
|
138
136
|
});
|
|
139
|
-
console.log(`[Niki-Loyalty] 📢 Socket bildirim gönderildi. UID: ${uid}`);
|
|
140
|
-
} else {
|
|
141
|
-
console.log(`[Niki-Loyalty] ⚠️ Socket server hazır değil, bildirim gönderilemedi.`);
|
|
142
137
|
}
|
|
143
138
|
} catch (socketErr) {
|
|
144
|
-
console.error(`[Niki-Loyalty] Socket emit hatası:`, socketErr.message);
|
|
145
139
|
}
|
|
146
140
|
|
|
147
141
|
return { success: true, points: pointsToGive };
|
|
148
142
|
|
|
149
143
|
} catch (err) {
|
|
150
|
-
|
|
144
|
+
|
|
151
145
|
return { success: false, reason: 'error', error: err.message };
|
|
152
146
|
}
|
|
153
147
|
}
|
|
@@ -185,67 +179,41 @@ Plugin.onPostCreate = async function (data) {
|
|
|
185
179
|
// 4. BEĞENİ (Like Atma ve Alma) - Spam Korumalı + Debug Loglı
|
|
186
180
|
// NodeBB upvote hook'u { pid, uid, ... } formatında data gönderir (post nesnesi değil!)
|
|
187
181
|
Plugin.onUpvote = async function (data) {
|
|
188
|
-
console.log('[Niki-Loyalty] 👍 Upvote hook tetiklendi. Raw Data:', JSON.stringify(data));
|
|
189
|
-
|
|
190
|
-
// NodeBB bazen farklı formatlar gönderebilir, hepsini kontrol et
|
|
191
182
|
const pid = data.pid || (data.post && data.post.pid);
|
|
192
183
|
const voterUid = data.uid || (data.current && data.current.uid);
|
|
193
184
|
|
|
194
|
-
if (!pid)
|
|
195
|
-
console.log('[Niki-Loyalty] ⚠️ Post PID bulunamadı, işlem iptal.');
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
185
|
+
if (!pid || !voterUid) return;
|
|
198
186
|
|
|
199
|
-
if (!voterUid) {
|
|
200
|
-
console.log('[Niki-Loyalty] ⚠️ Voter UID bulunamadı, işlem iptal.');
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Post sahibini bul (NodeBB upvote hook'u post sahibini göndermez!)
|
|
205
187
|
let postOwnerUid;
|
|
206
188
|
try {
|
|
207
189
|
postOwnerUid = await posts.getPostField(pid, 'uid');
|
|
208
|
-
console.log(`[Niki-Loyalty] Post sahibi bulundu: PID=${pid}, Owner UID=${postOwnerUid}`);
|
|
209
190
|
} catch (err) {
|
|
210
|
-
console.log('[Niki-Loyalty] ⚠️ Post sahibi bulunamadı:', err.message);
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (!postOwnerUid) {
|
|
215
|
-
console.log('[Niki-Loyalty] ⚠️ Post sahibi UID boş, işlem iptal.');
|
|
216
191
|
return;
|
|
217
192
|
}
|
|
193
|
+
if (!postOwnerUid) return;
|
|
218
194
|
|
|
219
195
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
220
196
|
|
|
221
|
-
// Like Atan Kazanır
|
|
197
|
+
// Like Atan Kazanır
|
|
222
198
|
const likeGivenKey = `niki:liked:${voterUid}:${today}`;
|
|
223
199
|
const alreadyLiked = await db.isSetMember(likeGivenKey, pid.toString());
|
|
224
200
|
|
|
225
|
-
console.log(`[Niki-Loyalty] Like Atan: UID=${voterUid}, PID=${pid}, Daha önce beğenmiş mi=${alreadyLiked}`);
|
|
226
|
-
|
|
227
201
|
if (!alreadyLiked) {
|
|
228
|
-
|
|
229
|
-
console.log('[Niki-Loyalty] like_given sonuç:', result);
|
|
202
|
+
await awardDailyAction(voterUid, 'like_given');
|
|
230
203
|
await db.setAdd(likeGivenKey, pid.toString());
|
|
231
204
|
await db.expire(likeGivenKey, 86400);
|
|
232
205
|
}
|
|
233
206
|
|
|
234
|
-
// Like Alan Kazanır (
|
|
207
|
+
// Like Alan Kazanır (kendine beğeni atamaz)
|
|
235
208
|
if (postOwnerUid && String(postOwnerUid) !== String(voterUid)) {
|
|
236
209
|
const likeTakenKey = `niki:liked_taken:${postOwnerUid}:${today}`;
|
|
237
210
|
const alreadyTaken = await db.isSetMember(likeTakenKey, pid.toString());
|
|
238
211
|
|
|
239
|
-
console.log(`[Niki-Loyalty] Like Alan: UID=${postOwnerUid}, PID=${pid}, Daha önce puan almış mı=${alreadyTaken}`);
|
|
240
|
-
|
|
241
212
|
if (!alreadyTaken) {
|
|
242
|
-
|
|
243
|
-
console.log('[Niki-Loyalty] like_taken sonuç:', result);
|
|
213
|
+
await awardDailyAction(postOwnerUid, 'like_taken');
|
|
244
214
|
await db.setAdd(likeTakenKey, pid.toString());
|
|
245
215
|
await db.expire(likeTakenKey, 86400);
|
|
246
216
|
}
|
|
247
|
-
} else {
|
|
248
|
-
console.log('[Niki-Loyalty] ⚠️ Kullanıcı kendi postunu beğenmiş veya post sahibi bulunamadı. Post owner:', postOwnerUid, 'Voter:', voterUid);
|
|
249
217
|
}
|
|
250
218
|
};
|
|
251
219
|
|
|
@@ -253,40 +221,50 @@ Plugin.onUpvote = async function (data) {
|
|
|
253
221
|
// 5. GRUP KATILIM BONUSU (Premium / VIP)
|
|
254
222
|
Plugin.onGroupJoin = async function (data) {
|
|
255
223
|
try {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
224
|
+
if (!data) return;
|
|
225
|
+
|
|
226
|
+
// NodeBB sürümüne göre groupName string veya array gelebilir
|
|
227
|
+
const groupNames = Array.isArray(data.groupName) ? data.groupName
|
|
228
|
+
: data.groupNames ? (Array.isArray(data.groupNames) ? data.groupNames : [data.groupNames])
|
|
229
|
+
: data.groupName ? [data.groupName]
|
|
230
|
+
: [];
|
|
231
|
+
|
|
232
|
+
// uid tek veya array olabilir (ACP toplu ekleme)
|
|
233
|
+
const uids = Array.isArray(data.uid) ? data.uid : data.uid ? [data.uid] : [];
|
|
234
|
+
|
|
235
|
+
for (const rawGroupName of groupNames) {
|
|
236
|
+
if (!rawGroupName) continue;
|
|
237
|
+
|
|
238
|
+
// Grup adını GROUP_BONUSES'da bul (case-insensitive)
|
|
239
|
+
let matchedGroup = null;
|
|
240
|
+
let bonus = 0;
|
|
241
|
+
for (const key of Object.keys(GROUP_BONUSES)) {
|
|
242
|
+
if (key.toLowerCase() === String(rawGroupName).toLowerCase()) {
|
|
243
|
+
matchedGroup = key;
|
|
244
|
+
bonus = GROUP_BONUSES[key];
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!matchedGroup || !bonus) continue;
|
|
270
249
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
await addUserLog(uid, 'earn', bonus, `${groupName} Grubu Katılım Bonusu 🎉`);
|
|
250
|
+
for (const uid of uids) {
|
|
251
|
+
if (!uid) continue;
|
|
274
252
|
|
|
275
|
-
|
|
253
|
+
await user.incrementUserFieldBy(uid, 'niki_points', bonus);
|
|
254
|
+
await addUserLog(uid, 'earn', bonus, `${matchedGroup} Grubu Katılım Bonusu 🎉`);
|
|
276
255
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
256
|
+
try {
|
|
257
|
+
if (socketHelpers && socketHelpers.server && socketHelpers.server.sockets) {
|
|
258
|
+
socketHelpers.server.sockets.in('uid_' + uid).emit('event:niki_award', {
|
|
259
|
+
title: 'Grup Bonusu! 🎉',
|
|
260
|
+
message: `${matchedGroup} grubuna katıldığın için <strong style="color:#ffd700">+${bonus} Puan</strong> kazandın!`,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
} catch (socketErr) {
|
|
264
|
+
}
|
|
284
265
|
}
|
|
285
|
-
} catch (socketErr) {
|
|
286
|
-
console.error('[Niki-Loyalty] Socket emit hatası:', socketErr.message);
|
|
287
266
|
}
|
|
288
267
|
} catch (err) {
|
|
289
|
-
console.error('[Niki-Loyalty] Grup bonus hatası:', err);
|
|
290
268
|
}
|
|
291
269
|
};
|
|
292
270
|
|
|
@@ -485,7 +463,6 @@ Plugin.init = async function (params) {
|
|
|
485
463
|
hasMore: enriched.length > 100
|
|
486
464
|
});
|
|
487
465
|
} catch (e) {
|
|
488
|
-
console.error('[Niki-Loyalty] Kasa history error:', e);
|
|
489
466
|
return res.status(500).json({ error: 'Sunucu hatası' });
|
|
490
467
|
}
|
|
491
468
|
});
|
|
@@ -609,13 +586,11 @@ Plugin.adminGetUsers = async function (socket, data) {
|
|
|
609
586
|
|
|
610
587
|
// TÜM kullanıcıları al (limit yok: -1)
|
|
611
588
|
const uids = await db.getSortedSetRevRange('users:joindate', 0, -1);
|
|
612
|
-
console.log('[Niki-Admin] Çekilen UID sayısı:', uids ? uids.length : 0);
|
|
613
589
|
|
|
614
590
|
if (!uids || uids.length === 0) return [];
|
|
615
591
|
|
|
616
592
|
// Kullanıcı bilgilerini al
|
|
617
593
|
const usersData = await user.getUsersFields(uids, ['uid', 'username', 'userslug', 'picture', 'niki_points', 'icon:bgColor']);
|
|
618
|
-
console.log('[Niki-Admin] Kullanıcı verisi alındı:', usersData ? usersData.length : 0);
|
|
619
594
|
|
|
620
595
|
// Puanları işle ve sırala (puanı yüksek olan önce)
|
|
621
596
|
const result = usersData
|
|
@@ -630,10 +605,8 @@ Plugin.adminGetUsers = async function (socket, data) {
|
|
|
630
605
|
}))
|
|
631
606
|
.sort((a, b) => b.points - a.points); // Yüksekten düşüğe sırala
|
|
632
607
|
|
|
633
|
-
console.log('[Niki-Admin] Döndürülen kullanıcı sayısı:', result.length);
|
|
634
608
|
return result;
|
|
635
609
|
} catch (err) {
|
|
636
|
-
console.error('[Niki-Admin] adminGetUsers HATA:', err.message);
|
|
637
610
|
throw err;
|
|
638
611
|
}
|
|
639
612
|
};
|
|
@@ -770,6 +743,7 @@ Plugin.adminManagePoints = async function (socket, data) {
|
|
|
770
743
|
// Denetim Logu
|
|
771
744
|
const auditLog = { ts: Date.now(), adminUid: uid, adminName: adminUserData.username, targetUid: targetUid, action: action, amount: amount, reason: reason };
|
|
772
745
|
await db.listAppend('niki:audit:admin_points', JSON.stringify(auditLog));
|
|
746
|
+
await db.listTrim('niki:audit:admin_points', -500, -1);
|
|
773
747
|
|
|
774
748
|
const newPoints = await user.getUserField(targetUid, 'niki_points');
|
|
775
749
|
return { success: true, newPoints: parseFloat(newPoints) };
|
package/package.json
CHANGED
package/static/lib/client.js
CHANGED
|
@@ -82,7 +82,6 @@ $(document).ready(function () {
|
|
|
82
82
|
}, 300);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
console.log('[Niki-Loyalty] Toast gösterildi:', message);
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
// Fonksiyonu global yap (Konsoldan test için)
|
|
@@ -105,10 +104,8 @@ $(document).ready(function () {
|
|
|
105
104
|
if (data && typeof data.points !== 'undefined') {
|
|
106
105
|
var points = Math.floor(data.points);
|
|
107
106
|
$('#widget-user-points').text(points);
|
|
108
|
-
console.log('[Niki-Loyalty] Widget puanı güncellendi:', points);
|
|
109
107
|
}
|
|
110
108
|
}).fail(function () {
|
|
111
|
-
console.log('[Niki-Loyalty] Widget puanı yüklenemedi.');
|
|
112
109
|
});
|
|
113
110
|
}
|
|
114
111
|
// Fonksiyonu global yap
|
|
@@ -147,7 +144,6 @@ $(document).ready(function () {
|
|
|
147
144
|
if (response && response.success) {
|
|
148
145
|
// Puan kazanıldı! Bildirim göster
|
|
149
146
|
showNikiToast('Günlük giriş için <strong style="color:#ffd700">+' + response.earned + ' Puan</strong> kazandın! 👋');
|
|
150
|
-
console.log('[Niki-Loyalty] Günlük giriş puanı alındı. Yeni Toplam:', response.total);
|
|
151
147
|
|
|
152
148
|
// Widget'ı güncelle
|
|
153
149
|
if (typeof updateSidebarWidget === 'function') {
|
|
@@ -158,7 +154,6 @@ $(document).ready(function () {
|
|
|
158
154
|
localStorage.setItem(storageKey, today);
|
|
159
155
|
}).fail(function () {
|
|
160
156
|
// Hata durumunda sessizce devam et
|
|
161
|
-
console.log('[Niki-Loyalty] Günlük giriş kontrolü başarısız.');
|
|
162
157
|
});
|
|
163
158
|
}
|
|
164
159
|
|
|
@@ -177,13 +172,11 @@ $(document).ready(function () {
|
|
|
177
172
|
// ============================================================
|
|
178
173
|
// Sadece 'topic' (konu) sayfasındaysak sayaç çalışsın.
|
|
179
174
|
if (ajaxify.data && ajaxify.data.template && ajaxify.data.template.name === 'topic') {
|
|
180
|
-
console.log('[Niki-Loyalty] Konu sayfası algılandı, sayaç başlatılıyor...');
|
|
181
175
|
|
|
182
176
|
// 10 Dakikada bir tetikle (Günde 10 limit var backendde)
|
|
183
177
|
heartbeatInterval = setInterval(function () {
|
|
184
178
|
if (document.hidden) return; // Sekme aktif değilse sayma
|
|
185
179
|
|
|
186
|
-
console.log('[Niki-Loyalty] 10dk doldu. Puan isteniyor...');
|
|
187
180
|
|
|
188
181
|
$.post('/api/niki-loyalty/heartbeat', { _csrf: config.csrf_token }, function (response) {
|
|
189
182
|
if (response && response.earned) {
|
|
@@ -191,11 +184,9 @@ $(document).ready(function () {
|
|
|
191
184
|
if (typeof showNikiToast === 'function') {
|
|
192
185
|
showNikiToast('Konu okuduğun için <strong style="color:#ffd700">+1 Puan</strong> kazandın! 🐈');
|
|
193
186
|
}
|
|
194
|
-
console.log('[Niki-Loyalty] Heartbeat başarılı. Yeni Puan:', response.total);
|
|
195
187
|
// Widget'ı hemen güncelle
|
|
196
188
|
updateSidebarWidget();
|
|
197
189
|
} else {
|
|
198
|
-
console.log('[Niki-Loyalty] Puan gelmedi (Günlük okuma limiti dolmuş olabilir).');
|
|
199
190
|
}
|
|
200
191
|
});
|
|
201
192
|
}, 600000); // 10 Dakika = 600.000 ms
|
|
@@ -389,7 +380,6 @@ $(document).ready(function () {
|
|
|
389
380
|
});
|
|
390
381
|
});
|
|
391
382
|
}).fail(function () {
|
|
392
|
-
console.log('[Niki-Loyalty] Cüzdan verileri yüklenemedi.');
|
|
393
383
|
});
|
|
394
384
|
}
|
|
395
385
|
|