nodebb-plugin-niki-loyalty 1.0.8 → 1.0.9
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 +110 -116
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -1,128 +1,122 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<span class="niki-lbl">PUANIM</span>
|
|
15
|
-
<span class="niki-val" id="niki-live-points">...</span>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
`;
|
|
20
|
-
|
|
21
|
-
// 1. Widget Başlatma ve Veri Yönetimi
|
|
22
|
-
function initNikiWidget() {
|
|
23
|
-
if (!app.user.uid || app.user.uid <= 0) return;
|
|
24
|
-
|
|
25
|
-
// Widget yoksa ekle
|
|
26
|
-
if ($('#niki-floating-widget').length === 0) {
|
|
27
|
-
$('body').append(widgetHtml);
|
|
28
|
-
}
|
|
3
|
+
const db = require.main.require('./src/database');
|
|
4
|
+
const user = require.main.require('./src/user');
|
|
5
|
+
const routeHelpers = require.main.require('./src/controllers/helpers');
|
|
6
|
+
|
|
7
|
+
const Plugin = {};
|
|
8
|
+
|
|
9
|
+
const SETTINGS = {
|
|
10
|
+
pointsPerHeartbeat: 5,
|
|
11
|
+
dailyCap: 250,
|
|
12
|
+
coffeeCost: 250
|
|
13
|
+
};
|
|
29
14
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
Plugin.init = async function (params) {
|
|
16
|
+
const router = params.router;
|
|
17
|
+
const middleware = params.middleware;
|
|
18
|
+
|
|
19
|
+
// 1. HEARTBEAT (Puan Kazanma)
|
|
20
|
+
router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
|
|
21
|
+
const uid = req.uid;
|
|
22
|
+
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
23
|
+
const dailyKey = `niki:daily:${uid}:${today}`;
|
|
24
|
+
|
|
25
|
+
const currentDailyScore = await db.getObjectField(dailyKey, 'score') || 0;
|
|
26
|
+
|
|
27
|
+
if (parseInt(currentDailyScore) >= SETTINGS.dailyCap) {
|
|
28
|
+
return res.json({ earned: false, reason: 'daily_cap' });
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
31
|
+
await user.incrementUserFieldBy(uid, 'niki_points', SETTINGS.pointsPerHeartbeat);
|
|
32
|
+
await db.incrObjectFieldBy(dailyKey, 'score', SETTINGS.pointsPerHeartbeat);
|
|
33
|
+
|
|
34
|
+
const newBalance = await user.getUserField(uid, 'niki_points');
|
|
35
|
+
return res.json({ earned: true, points: SETTINGS.pointsPerHeartbeat, total: newBalance });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// 2. WALLET DATA (Bilgi Çekme)
|
|
39
|
+
router.get('/api/niki-loyalty/wallet-data', middleware.ensureLoggedIn, async (req, res) => {
|
|
40
|
+
const uid = req.uid;
|
|
41
|
+
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
42
|
+
|
|
43
|
+
const [userData, dailyData] = await Promise.all([
|
|
44
|
+
user.getUserFields(uid, ['niki_points']),
|
|
45
|
+
db.getObject(`niki:daily:${uid}:${today}`)
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
const currentPoints = parseInt(userData.niki_points) || 0;
|
|
49
|
+
const dailyScore = parseInt(dailyData ? dailyData.score : 0) || 0;
|
|
50
|
+
let dailyPercent = (dailyScore / SETTINGS.dailyCap) * 100;
|
|
51
|
+
if (dailyPercent > 100) dailyPercent = 100;
|
|
52
|
+
|
|
53
|
+
res.json({
|
|
54
|
+
points: currentPoints,
|
|
55
|
+
dailyScore: dailyScore,
|
|
56
|
+
dailyCap: SETTINGS.dailyCap,
|
|
57
|
+
dailyPercent: dailyPercent
|
|
61
58
|
});
|
|
62
|
-
}
|
|
59
|
+
});
|
|
63
60
|
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
// 3. QR TOKEN ÜRET (Öğrenci Butona Basınca)
|
|
62
|
+
router.post('/api/niki-loyalty/generate-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
63
|
+
const uid = req.uid;
|
|
64
|
+
const points = parseInt(await user.getUserField(uid, 'niki_points')) || 0;
|
|
65
|
+
|
|
66
|
+
if (points < SETTINGS.coffeeCost) {
|
|
67
|
+
return res.json({ success: false, message: 'Yetersiz Puan' });
|
|
69
68
|
}
|
|
70
|
-
}
|
|
71
69
|
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
// Token Oluştur
|
|
71
|
+
const token = Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
72
|
+
|
|
73
|
+
// Kaydet (2 dakika geçerli)
|
|
74
|
+
await db.set(`niki:qr:${token}`, uid);
|
|
75
|
+
await db.expire(`niki:qr:${token}`, 120);
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
$(window).on('action:ajaxify.end', function () {
|
|
77
|
-
initNikiWidget();
|
|
78
|
-
setTimeout(fixLogo, 500); // 0.5sn sonra son bir kontrol
|
|
77
|
+
return res.json({ success: true, token: token });
|
|
79
78
|
});
|
|
80
79
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
toast.removeClass('show');
|
|
125
|
-
setTimeout(() => toast.remove(), 3000);
|
|
126
|
-
}, 3000);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
80
|
+
// 4. QR OKUTMA (Personel Tarayınca)
|
|
81
|
+
router.post('/api/niki-loyalty/scan-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
82
|
+
const { token } = req.body;
|
|
83
|
+
|
|
84
|
+
// Sadece Admin/Mod yetkisi
|
|
85
|
+
const isAdmin = await user.isAdministrator(req.uid);
|
|
86
|
+
const isMod = await user.isGlobalModerator(req.uid);
|
|
87
|
+
if (!isAdmin && !isMod) return res.status(403).json({ success: false, message: 'Yetkisiz' });
|
|
88
|
+
|
|
89
|
+
const customerUid = await db.get(`niki:qr:${token}`);
|
|
90
|
+
if (!customerUid) return res.json({ success: false, message: 'Geçersiz Kod' });
|
|
91
|
+
|
|
92
|
+
// Puan Düş
|
|
93
|
+
const pts = parseInt(await user.getUserField(customerUid, 'niki_points')) || 0;
|
|
94
|
+
if (pts < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Bakiye Yetersiz' });
|
|
95
|
+
|
|
96
|
+
await user.decrementUserFieldBy(customerUid, 'niki_points', SETTINGS.coffeeCost);
|
|
97
|
+
await db.delete(`niki:qr:${token}`);
|
|
98
|
+
|
|
99
|
+
const customerData = await user.getUserFields(customerUid, ['username', 'picture']);
|
|
100
|
+
return res.json({ success: true, customer: customerData, message: 'Onaylandı!' });
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// 5. NIKI KASA SAYFASI (Erişim Kontrolü)
|
|
104
|
+
routeHelpers.setupPageRoute(router, '/niki-kasa', middleware, [], async (req, res) => {
|
|
105
|
+
const isAdmin = await user.isAdministrator(req.uid);
|
|
106
|
+
const isMod = await user.isGlobalModerator(req.uid);
|
|
107
|
+
if (!isAdmin && !isMod) return res.render('403', {});
|
|
108
|
+
res.render('niki-kasa', { title: 'Niki Kasa' });
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
Plugin.addScripts = async function (scripts) {
|
|
113
|
+
scripts.push('plugins/nodebb-plugin-niki-loyalty/static/lib/client.js');
|
|
114
|
+
return scripts;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
Plugin.addNavigation = async function (nav) {
|
|
118
|
+
nav.push({ route: "/niki-wallet", title: "Niki Cüzdan", enabled: true, iconClass: "fa-coffee", text: "Niki Cüzdan" });
|
|
119
|
+
return nav;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
module.exports = Plugin;
|