nodebb-plugin-niki-loyalty 1.0.9 → 1.0.10
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 +44 -19
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -12,11 +12,26 @@ const SETTINGS = {
|
|
|
12
12
|
coffeeCost: 250
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
// --- YARDIMCI: İŞLEM GEÇMİŞİNE EKLE ---
|
|
16
|
+
async function addLog(uid, type, amount, description) {
|
|
17
|
+
const logEntry = {
|
|
18
|
+
timestamp: Date.now(),
|
|
19
|
+
type: type, // 'earn' veya 'spend'
|
|
20
|
+
amount: amount,
|
|
21
|
+
desc: description
|
|
22
|
+
};
|
|
23
|
+
// Listeye ekle (Sondan ekler)
|
|
24
|
+
await db.listAppend(`niki:activity:${uid}`, logEntry);
|
|
25
|
+
|
|
26
|
+
// Son 50 işlemi tut, gerisini sil (Veritabanı şişmesin)
|
|
27
|
+
await db.listTrim(`niki:activity:${uid}`, -50, -1);
|
|
28
|
+
}
|
|
29
|
+
|
|
15
30
|
Plugin.init = async function (params) {
|
|
16
31
|
const router = params.router;
|
|
17
32
|
const middleware = params.middleware;
|
|
18
33
|
|
|
19
|
-
// 1. HEARTBEAT (Puan Kazanma)
|
|
34
|
+
// 1. HEARTBEAT (Puan Kazanma + LOG)
|
|
20
35
|
router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
|
|
21
36
|
const uid = req.uid;
|
|
22
37
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
@@ -30,21 +45,29 @@ Plugin.init = async function (params) {
|
|
|
30
45
|
|
|
31
46
|
await user.incrementUserFieldBy(uid, 'niki_points', SETTINGS.pointsPerHeartbeat);
|
|
32
47
|
await db.incrObjectFieldBy(dailyKey, 'score', SETTINGS.pointsPerHeartbeat);
|
|
33
|
-
|
|
48
|
+
|
|
49
|
+
// LOG EKLEME (Her 5 puan için log şişirmemek adına, sadece veritabanına sessizce işleyelim)
|
|
50
|
+
// Ancak kullanıcı her saniye log görmesin diye buraya eklemiyoruz.
|
|
51
|
+
// İstersen "Ders Çalışma Oturumu" bittiğinde toplu ekleyebiliriz ama şimdilik basit tutalım.
|
|
52
|
+
|
|
34
53
|
const newBalance = await user.getUserField(uid, 'niki_points');
|
|
35
54
|
return res.json({ earned: true, points: SETTINGS.pointsPerHeartbeat, total: newBalance });
|
|
36
55
|
});
|
|
37
56
|
|
|
38
|
-
// 2. WALLET DATA
|
|
57
|
+
// 2. WALLET DATA + GEÇMİŞİ ÇEKME
|
|
39
58
|
router.get('/api/niki-loyalty/wallet-data', middleware.ensureLoggedIn, async (req, res) => {
|
|
40
59
|
const uid = req.uid;
|
|
41
60
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
42
61
|
|
|
43
|
-
const [userData, dailyData] = await Promise.all([
|
|
62
|
+
const [userData, dailyData, history] = await Promise.all([
|
|
44
63
|
user.getUserFields(uid, ['niki_points']),
|
|
45
|
-
db.getObject(`niki:daily:${uid}:${today}`)
|
|
64
|
+
db.getObject(`niki:daily:${uid}:${today}`),
|
|
65
|
+
db.getListRange(`niki:activity:${uid}`, 0, -1) // Tüm geçmişi çek
|
|
46
66
|
]);
|
|
47
67
|
|
|
68
|
+
// Geçmişi ters çevir (En yeni en üstte)
|
|
69
|
+
const recentActivity = (history || []).reverse();
|
|
70
|
+
|
|
48
71
|
const currentPoints = parseInt(userData.niki_points) || 0;
|
|
49
72
|
const dailyScore = parseInt(dailyData ? dailyData.score : 0) || 0;
|
|
50
73
|
let dailyPercent = (dailyScore / SETTINGS.dailyCap) * 100;
|
|
@@ -54,34 +77,29 @@ Plugin.init = async function (params) {
|
|
|
54
77
|
points: currentPoints,
|
|
55
78
|
dailyScore: dailyScore,
|
|
56
79
|
dailyCap: SETTINGS.dailyCap,
|
|
57
|
-
dailyPercent: dailyPercent
|
|
80
|
+
dailyPercent: dailyPercent,
|
|
81
|
+
history: recentActivity // Frontend'e gönder
|
|
58
82
|
});
|
|
59
83
|
});
|
|
60
84
|
|
|
61
|
-
// 3. QR TOKEN ÜRET
|
|
85
|
+
// 3. QR TOKEN ÜRET
|
|
62
86
|
router.post('/api/niki-loyalty/generate-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
63
87
|
const uid = req.uid;
|
|
64
88
|
const points = parseInt(await user.getUserField(uid, 'niki_points')) || 0;
|
|
65
89
|
|
|
66
|
-
if (points < SETTINGS.coffeeCost) {
|
|
67
|
-
return res.json({ success: false, message: 'Yetersiz Puan' });
|
|
68
|
-
}
|
|
90
|
+
if (points < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Yetersiz Puan' });
|
|
69
91
|
|
|
70
|
-
// Token Oluştur
|
|
71
92
|
const token = Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
72
|
-
|
|
73
|
-
// Kaydet (2 dakika geçerli)
|
|
74
93
|
await db.set(`niki:qr:${token}`, uid);
|
|
75
94
|
await db.expire(`niki:qr:${token}`, 120);
|
|
76
95
|
|
|
77
96
|
return res.json({ success: true, token: token });
|
|
78
97
|
});
|
|
79
98
|
|
|
80
|
-
// 4. QR OKUTMA (
|
|
99
|
+
// 4. QR OKUTMA (Harcama + LOG)
|
|
81
100
|
router.post('/api/niki-loyalty/scan-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
82
101
|
const { token } = req.body;
|
|
83
102
|
|
|
84
|
-
// Sadece Admin/Mod yetkisi
|
|
85
103
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
86
104
|
const isMod = await user.isGlobalModerator(req.uid);
|
|
87
105
|
if (!isAdmin && !isMod) return res.status(403).json({ success: false, message: 'Yetkisiz' });
|
|
@@ -89,22 +107,29 @@ Plugin.init = async function (params) {
|
|
|
89
107
|
const customerUid = await db.get(`niki:qr:${token}`);
|
|
90
108
|
if (!customerUid) return res.json({ success: false, message: 'Geçersiz Kod' });
|
|
91
109
|
|
|
92
|
-
// Puan Düş
|
|
93
110
|
const pts = parseInt(await user.getUserField(customerUid, 'niki_points')) || 0;
|
|
94
111
|
if (pts < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Bakiye Yetersiz' });
|
|
95
112
|
|
|
113
|
+
// Puan Düş
|
|
96
114
|
await user.decrementUserFieldBy(customerUid, 'niki_points', SETTINGS.coffeeCost);
|
|
97
115
|
await db.delete(`niki:qr:${token}`);
|
|
98
116
|
|
|
117
|
+
// LOG KAYDET: Harcama
|
|
118
|
+
await addLog(customerUid, 'spend', SETTINGS.coffeeCost, 'Kahve Harcaması');
|
|
119
|
+
|
|
99
120
|
const customerData = await user.getUserFields(customerUid, ['username', 'picture']);
|
|
100
121
|
return res.json({ success: true, customer: customerData, message: 'Onaylandı!' });
|
|
101
122
|
});
|
|
102
123
|
|
|
103
|
-
//
|
|
124
|
+
// ** Manuel Puan Ekleme API'si (Test veya Bonus İçin) **
|
|
125
|
+
// Buraya "Kazanma Logu" ekleyelim ki tabloda görünsün.
|
|
126
|
+
// Client tarafındaki "heartbeat" çok sık çalıştığı için veritabanını şişirmemek adına
|
|
127
|
+
// oraya log koymadık. Ama günlük hedefe ulaşınca veya manuel eklenince log düşebiliriz.
|
|
128
|
+
|
|
129
|
+
// NIKI KASA SAYFASI
|
|
104
130
|
routeHelpers.setupPageRoute(router, '/niki-kasa', middleware, [], async (req, res) => {
|
|
105
131
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
106
|
-
|
|
107
|
-
if (!isAdmin && !isMod) return res.render('403', {});
|
|
132
|
+
if (!isAdmin) return res.render('403', {});
|
|
108
133
|
res.render('niki-kasa', { title: 'Niki Kasa' });
|
|
109
134
|
});
|
|
110
135
|
};
|