nodebb-plugin-niki-loyalty 1.5.7 → 1.5.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 CHANGED
@@ -4,6 +4,7 @@ const user = require.main.require('./src/user');
4
4
  const posts = require.main.require('./src/posts');
5
5
  const routeHelpers = require.main.require('./src/controllers/helpers');
6
6
  const nconf = require.main.require('nconf');
7
+ const meta = require.main.require('./src/meta');
7
8
  const socketHelpers = require.main.require('./src/socket.io/index');
8
9
  const SocketPlugins = require.main.require('./src/socket.io/plugins');
9
10
  const groups = require.main.require('./src/groups');
@@ -45,6 +46,65 @@ const REWARDS = [
45
46
 
46
47
  const TEST_MODE_UNLIMITED = false;
47
48
 
49
+ // =========================
50
+ // 📦 AYARLARI DB'DEN YÜKLE
51
+ // =========================
52
+ async function loadAndApplySettings() {
53
+ try {
54
+ console.log('[NIKI] Ayarlar DB\'den yükleniyor...');
55
+
56
+ const saved = await new Promise((resolve) => {
57
+ meta.settings.get('niki-loyalty', (err, settings) => {
58
+ if (err) {
59
+ console.error('[NIKI] meta.settings.get HATA:', err);
60
+ return resolve({});
61
+ }
62
+ resolve(settings || {});
63
+ });
64
+ });
65
+
66
+ console.log('[NIKI] DB\'den gelen ham veri:', JSON.stringify(saved, null, 2));
67
+
68
+ if (!saved || Object.keys(saved).length === 0) {
69
+ console.log('[NIKI] DB\'de kayıtlı ayar yok, varsayılanlar kullanılacak.');
70
+ return;
71
+ }
72
+
73
+ // Genel
74
+ if (saved.dailyCap) SETTINGS.dailyCap = parseInt(saved.dailyCap, 10) || SETTINGS.dailyCap;
75
+
76
+ // Aksiyonlar
77
+ ['login', 'new_topic', 'reply', 'read', 'like_given', 'like_taken'].forEach(key => {
78
+ if (saved[key + '_points'] !== undefined && saved[key + '_points'] !== '')
79
+ ACTIONS[key].points = parseFloat(saved[key + '_points']);
80
+ if (saved[key + '_limit'] !== undefined && saved[key + '_limit'] !== '')
81
+ ACTIONS[key].limit = parseInt(saved[key + '_limit'], 10);
82
+ });
83
+
84
+ // Ödüller
85
+ for (let i = 0; i < REWARDS.length; i++) {
86
+ if (saved['reward' + i + '_name']) REWARDS[i].name = saved['reward' + i + '_name'];
87
+ if (saved['reward' + i + '_cost'] !== undefined && saved['reward' + i + '_cost'] !== '')
88
+ REWARDS[i].cost = parseInt(saved['reward' + i + '_cost'], 10);
89
+ }
90
+
91
+ // Grup Bonusları
92
+ if (saved.bonus_premium !== undefined && saved.bonus_premium !== '')
93
+ GROUP_BONUSES['Premium'] = parseInt(saved.bonus_premium, 10);
94
+ if (saved.bonus_vip !== undefined && saved.bonus_vip !== '')
95
+ GROUP_BONUSES['VIP'] = parseInt(saved.bonus_vip, 10);
96
+
97
+ console.log('[NIKI] === UYGULANAN AYARLAR ===');
98
+ console.log('[NIKI] SETTINGS:', JSON.stringify(SETTINGS));
99
+ console.log('[NIKI] ACTIONS:', JSON.stringify(ACTIONS));
100
+ console.log('[NIKI] REWARDS:', JSON.stringify(REWARDS));
101
+ console.log('[NIKI] GROUP_BONUSES:', JSON.stringify(GROUP_BONUSES));
102
+
103
+ } catch (err) {
104
+ console.error('[NIKI] Ayarlar yüklenirken hata:', err);
105
+ }
106
+ }
107
+
48
108
  // =========================
49
109
  // 🛠 YARDIMCI FONKSİYONLAR
50
110
  // =========================
@@ -83,8 +143,9 @@ async function awardDailyAction(uid, actionKey) {
83
143
  const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
84
144
  const rule = ACTIONS[actionKey];
85
145
 
86
- if (!rule) {
146
+ console.log(`[NIKI] awardDailyAction => uid:${uid}, action:${actionKey}, rule:${JSON.stringify(rule)}, dailyCap:${SETTINGS.dailyCap}`);
87
147
 
148
+ if (!rule) {
88
149
  return { success: false, reason: 'unknown_action' };
89
150
  }
90
151
 
@@ -275,6 +336,16 @@ Plugin.init = async function (params) {
275
336
  const router = params.router;
276
337
  const middleware = params.middleware;
277
338
 
339
+ // DB'den ayarları yükle
340
+ await loadAndApplySettings();
341
+
342
+ // ADMIN PANEL ROTALARI
343
+ function renderAdmin(req, res) {
344
+ res.render('admin/plugins/niki-loyalty', { title: 'Niki Loyalty Ayarları' });
345
+ }
346
+ router.get('/admin/plugins/niki-loyalty', middleware.admin.buildHeader, renderAdmin);
347
+ router.get('/api/admin/plugins/niki-loyalty', renderAdmin);
348
+
278
349
  // 1) HEARTBEAT (Artık "Okuma" Puanı veriyor)
279
350
  // Client-side script her 30-60 saniyede bir bu adrese istek atmalıdır.
280
351
  router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
@@ -559,6 +630,15 @@ Plugin.addScripts = async function (scripts) {
559
630
  return scripts;
560
631
  };
561
632
 
633
+ Plugin.addAdminNavigation = async function (header) {
634
+ header.plugins.push({
635
+ route: '/plugins/niki-loyalty',
636
+ icon: 'fa-coffee',
637
+ name: 'Niki Loyalty',
638
+ });
639
+ return header;
640
+ };
641
+
562
642
  Plugin.addNavigation = async function (nav) {
563
643
  nav.push({
564
644
  route: '/niki-wallet',
@@ -890,6 +970,18 @@ Plugin.adminGetStats = async function (socket, data) {
890
970
  };
891
971
  };
892
972
 
973
+ // 6) AYARLARI YENİDEN YÜKLE (Admin panelden kaydet sonrası)
974
+ Plugin.reloadSettings = async function (socket) {
975
+ console.log('[NIKI] reloadSettings socket çağrıldı, uid:', socket.uid);
976
+ const uid = socket.uid;
977
+ if (!uid) throw new Error('Giriş yapmalısınız.');
978
+ const isAdmin = await user.isAdministrator(uid);
979
+ if (!isAdmin) throw new Error('Yetkisiz Erişim');
980
+ await loadAndApplySettings();
981
+ console.log('[NIKI] reloadSettings tamamlandı.');
982
+ return { success: true };
983
+ };
984
+
893
985
  // Soket'e kaydet (Client: socket.emit('plugins.niki.getUsers', ...))
894
986
  if (SocketPlugins) {
895
987
  SocketPlugins.niki = {
@@ -898,7 +990,8 @@ if (SocketPlugins) {
898
990
  getStats: Plugin.adminGetStats,
899
991
  scanQR: Plugin.socketScanQR,
900
992
  getKasaHistory: Plugin.socketKasaHistory,
901
- managePoints: Plugin.adminManagePoints
993
+ managePoints: Plugin.adminManagePoints,
994
+ reloadSettings: Plugin.reloadSettings
902
995
  };
903
996
  }
904
997
 
package/niki-prize.txt CHANGED
@@ -5,7 +5,7 @@
5
5
  <i class="fa fa-diamond gold-icon"></i>
6
6
  <span class="widget-title">GÜNLÜK HEDEF</span>
7
7
  </div>
8
- <span class="points-badge" id="widget-user-points">...</span>
8
+ <span class="points-badge" id="widget-user-points">0 ⭐</span>
9
9
  </div>
10
10
 
11
11
  <div class="progress-container">
@@ -13,8 +13,8 @@
13
13
  <div class="progress-bar-fill" id="widget-daily-progress" style="width: 0%;"></div>
14
14
  </div>
15
15
  <div class="progress-text">
16
- <span id="widget-daily-text" class="status-text">Yükleniyor...</span>
17
- <span class="target">Hedef: ...</span>
16
+ <span id="widget-daily-text" class="status-text">0/35 Puan</span>
17
+ <span class="target">Hedef: 35</span>
18
18
  </div>
19
19
  </div>
20
20
  </div>
@@ -24,45 +24,45 @@
24
24
  <div class="icon-box purple-theme"><i class="fa fa-sign-in"></i></div>
25
25
  <div class="item-details">
26
26
  <span class="item-name">Günlük Giriş 👋</span>
27
- <span class="item-sub" id="w-count-login">Giriş Yapılmadı</span>
27
+ <span class="item-sub" id="w-count-login">0/1 Giriş</span>
28
28
  </div>
29
- <div class="item-reward">...</div>
29
+ <div class="item-reward">+5</div>
30
30
  </div>
31
31
 
32
32
  <div class="list-item" id="item-new-topic">
33
33
  <div class="icon-box blue-theme"><i class="fa fa-pencil"></i></div>
34
34
  <div class="item-details">
35
35
  <span class="item-name">Yeni Konu 📝</span>
36
- <span class="item-sub" id="w-count-new_topic">...</span>
36
+ <span class="item-sub" id="w-count-new_topic">0/1 Konu</span>
37
37
  </div>
38
- <div class="item-reward">...</div>
38
+ <div class="item-reward">+5</div>
39
39
  </div>
40
40
 
41
41
  <div class="list-item" id="item-reply">
42
42
  <div class="icon-box green-theme"><i class="fa fa-commenting"></i></div>
43
43
  <div class="item-details">
44
44
  <span class="item-name">Yorum Yazma 💬</span>
45
- <span class="item-sub" id="w-count-reply">...</span>
45
+ <span class="item-sub" id="w-count-reply">0/2 Yorum</span>
46
46
  </div>
47
- <div class="item-reward">...</div>
47
+ <div class="item-reward">+5</div>
48
48
  </div>
49
49
 
50
50
  <div class="list-item" id="item-read">
51
51
  <div class="icon-box orange-theme"><i class="fa fa-book"></i></div>
52
52
  <div class="item-details">
53
53
  <span class="item-name">Konu Okuma 👀</span>
54
- <span class="item-sub" id="w-count-read">...</span>
54
+ <span class="item-sub" id="w-count-read">0/10 Okuma</span>
55
55
  </div>
56
- <div class="item-reward">...</div>
56
+ <div class="item-reward">+1</div>
57
57
  </div>
58
58
 
59
59
  <div class="list-item" id="item-like">
60
60
  <div class="icon-box pink-theme"><i class="fa fa-heart"></i></div>
61
61
  <div class="item-details">
62
62
  <span class="item-name">Beğeni Etkileşimi ❤️🌟</span>
63
- <span class="item-sub" id="w-count-like">...</span>
63
+ <span class="item-sub" id="w-count-like">0/2 Beğeni</span>
64
64
  </div>
65
- <div class="item-reward">...</div>
65
+ <div class="item-reward">+2.5 / +5</div>
66
66
  </div>
67
67
  </div>
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-niki-loyalty",
3
- "version": "1.5.7",
3
+ "version": "1.5.9",
4
4
  "description": "Niki The Cat Coffee Loyalty System - Earn points while studying on IEU Forum.",
5
5
  "main": "library.js",
6
6
  "nbbpm": {
package/plugin.json CHANGED
@@ -4,11 +4,18 @@
4
4
  "description": "Niki The Cat Coffee Loyalty System",
5
5
  "url": "https://forum.ieu.app",
6
6
  "library": "./library.js",
7
+ "modules": {
8
+ "../admin/plugins/niki-loyalty.js": "static/lib/admin.js"
9
+ },
7
10
  "hooks": [
8
11
  {
9
12
  "hook": "static:app.load",
10
13
  "method": "init"
11
14
  },
15
+ {
16
+ "hook": "filter:admin.header.build",
17
+ "method": "addAdminNavigation"
18
+ },
12
19
  {
13
20
  "hook": "filter:navigation.available",
14
21
  "method": "addNavigation"
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ define('admin/plugins/niki-loyalty', ['settings', 'alerts'], function (Settings, alerts) {
4
+ var ACP = {};
5
+
6
+ ACP.init = function () {
7
+ Settings.load('niki-loyalty', $('#niki-loyalty-settings'));
8
+
9
+ $('#save').on('click', function () {
10
+ Settings.save('niki-loyalty', $('#niki-loyalty-settings'), function () {
11
+ // Sunucu tarafında ayarları anında uygula
12
+ socket.emit('plugins.niki.reloadSettings', {}, function (err) {
13
+ if (err) {
14
+ return alerts.alert({
15
+ type: 'danger',
16
+ alert_id: 'niki-loyalty-error',
17
+ title: 'Hata',
18
+ message: 'Ayarlar kaydedildi ama sunucuya uygulanamadı. NodeBB\'yi yeniden başlatın.',
19
+ timeout: 5000,
20
+ });
21
+ }
22
+ alerts.alert({
23
+ type: 'success',
24
+ alert_id: 'niki-loyalty-saved',
25
+ title: 'Ayarlar Kaydedildi',
26
+ message: 'Niki Loyalty ayarları kaydedildi ve anında uygulandı.',
27
+ timeout: 2500,
28
+ });
29
+ });
30
+ });
31
+ });
32
+ };
33
+
34
+ return ACP;
35
+ });
@@ -0,0 +1,135 @@
1
+ <div class="acp-page-container">
2
+ <div class="col-12 col-md-10 col-lg-8 px-0 mx-auto">
3
+
4
+ <div class="d-flex justify-content-between align-items-center mb-4">
5
+ <h4 class="fw-bold mb-0"><i class="fa fa-coffee text-warning"></i> Niki Loyalty Ayarları</h4>
6
+ <button id="save" class="btn btn-primary btn-sm">
7
+ <i class="fa fa-save"></i> Kaydet
8
+ </button>
9
+ </div>
10
+
11
+ <form id="niki-loyalty-settings">
12
+
13
+ <!-- GENEL AYARLAR -->
14
+ <div class="card mb-4">
15
+ <div class="card-header fw-bold"><i class="fa fa-cog"></i> Genel Ayarlar</div>
16
+ <div class="card-body">
17
+ <div class="row">
18
+ <div class="col-md-6 mb-3">
19
+ <label class="form-label fw-semibold">Günlük Maksimum Puan Limiti</label>
20
+ <input type="number" class="form-control" data-key="dailyCap" placeholder="35">
21
+ <div class="form-text">Bir kullanıcının günde kazanabileceği maksimum puan.</div>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <!-- PUAN TABLOSU -->
28
+ <div class="card mb-4">
29
+ <div class="card-header fw-bold"><i class="fa fa-star text-warning"></i> Puan Tablosu</div>
30
+ <div class="card-body">
31
+ <div class="table-responsive">
32
+ <table class="table table-hover align-middle mb-0">
33
+ <thead>
34
+ <tr>
35
+ <th style="width:30%">Aksiyon</th>
36
+ <th style="width:35%">Puan</th>
37
+ <th style="width:35%">Günlük Limit</th>
38
+ </tr>
39
+ </thead>
40
+ <tbody>
41
+ <tr>
42
+ <td><i class="fa fa-sign-in text-purple"></i> Günlük Giriş</td>
43
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="login_points" placeholder="5"></td>
44
+ <td><input type="number" class="form-control form-control-sm" data-key="login_limit" placeholder="1"></td>
45
+ </tr>
46
+ <tr>
47
+ <td><i class="fa fa-pencil text-primary"></i> Yeni Konu</td>
48
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="new_topic_points" placeholder="5"></td>
49
+ <td><input type="number" class="form-control form-control-sm" data-key="new_topic_limit" placeholder="1"></td>
50
+ </tr>
51
+ <tr>
52
+ <td><i class="fa fa-commenting text-success"></i> Yorum Yazma</td>
53
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="reply_points" placeholder="5"></td>
54
+ <td><input type="number" class="form-control form-control-sm" data-key="reply_limit" placeholder="2"></td>
55
+ </tr>
56
+ <tr>
57
+ <td><i class="fa fa-book text-warning"></i> Konu Okuma</td>
58
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="read_points" placeholder="1"></td>
59
+ <td><input type="number" class="form-control form-control-sm" data-key="read_limit" placeholder="10"></td>
60
+ </tr>
61
+ <tr>
62
+ <td><i class="fa fa-heart text-danger"></i> Beğeni Atma</td>
63
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="like_given_points" placeholder="2.5"></td>
64
+ <td><input type="number" class="form-control form-control-sm" data-key="like_given_limit" placeholder="2"></td>
65
+ </tr>
66
+ <tr>
67
+ <td><i class="fa fa-star text-info"></i> Beğeni Alma</td>
68
+ <td><input type="number" step="0.5" class="form-control form-control-sm" data-key="like_taken_points" placeholder="5"></td>
69
+ <td><input type="number" class="form-control form-control-sm" data-key="like_taken_limit" placeholder="2"></td>
70
+ </tr>
71
+ </tbody>
72
+ </table>
73
+ </div>
74
+ <div class="form-text mt-2">Placeholder'daki değerler varsayılan değerlerdir. Boş bırakırsanız varsayılan kullanılır.</div>
75
+ </div>
76
+ </div>
77
+
78
+ <!-- ÖDÜLLER -->
79
+ <div class="card mb-4">
80
+ <div class="card-header fw-bold"><i class="fa fa-gift text-danger"></i> Ödüller</div>
81
+ <div class="card-body">
82
+ <div class="table-responsive">
83
+ <table class="table table-hover align-middle mb-0">
84
+ <thead>
85
+ <tr>
86
+ <th style="width:60%">Ödül Adı</th>
87
+ <th style="width:40%">Gerekli Puan</th>
88
+ </tr>
89
+ </thead>
90
+ <tbody>
91
+ <tr>
92
+ <td><input type="text" class="form-control form-control-sm" data-key="reward0_name" placeholder="Ücretsiz Kahve ☕"></td>
93
+ <td><input type="number" class="form-control form-control-sm" data-key="reward0_cost" placeholder="250"></td>
94
+ </tr>
95
+ <tr>
96
+ <td><input type="text" class="form-control form-control-sm" data-key="reward1_name" placeholder="%60 İndirimli Kahve"></td>
97
+ <td><input type="number" class="form-control form-control-sm" data-key="reward1_cost" placeholder="180"></td>
98
+ </tr>
99
+ <tr>
100
+ <td><input type="text" class="form-control form-control-sm" data-key="reward2_name" placeholder="%30 İndirimli Kahve"></td>
101
+ <td><input type="number" class="form-control form-control-sm" data-key="reward2_cost" placeholder="120"></td>
102
+ </tr>
103
+ <tr>
104
+ <td><input type="text" class="form-control form-control-sm" data-key="reward3_name" placeholder="1 Kurabiye 🍪"></td>
105
+ <td><input type="number" class="form-control form-control-sm" data-key="reward3_cost" placeholder="60"></td>
106
+ </tr>
107
+ </tbody>
108
+ </table>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <!-- GRUP BONUSLARI -->
114
+ <div class="card mb-4">
115
+ <div class="card-header fw-bold"><i class="fa fa-users text-success"></i> Grup Katılım Bonusları</div>
116
+ <div class="card-body">
117
+ <div class="row">
118
+ <div class="col-md-6 mb-3">
119
+ <label class="form-label fw-semibold">Premium Grup Bonusu</label>
120
+ <input type="number" class="form-control" data-key="bonus_premium" placeholder="30">
121
+ <div class="form-text">Premium grubuna katılan kullanıcıya verilecek bonus puan.</div>
122
+ </div>
123
+ <div class="col-md-6 mb-3">
124
+ <label class="form-label fw-semibold">VIP Grup Bonusu</label>
125
+ <input type="number" class="form-control" data-key="bonus_vip" placeholder="60">
126
+ <div class="form-text">VIP grubuna katılan kullanıcıya verilecek bonus puan.</div>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ </form>
133
+
134
+ </div>
135
+ </div>