nodebb-plugin-openai 1.0.0 → 1.1.0

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.
@@ -0,0 +1,3 @@
1
+ {
2
+ "error.need-x-reputation-to-mention": "You need at least %1 reputation for mentioning chatgpt"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "error.need-x-reputation-to-mention": "You need at least %1 reputation for mentioning chatgpt"
3
+ }
@@ -1,9 +1,14 @@
1
1
  'use strict';
2
2
 
3
+ const groups = require.main.require('./src/groups');
4
+
3
5
  const Controllers = module.exports;
4
6
 
5
- Controllers.renderAdminPage = function (req, res/* , next */) {
7
+ Controllers.renderAdminPage = async function (req, res/* , next */) {
8
+ const groupsData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1);
9
+ groupsData.sort((a, b) => b.system - a.system);
6
10
  res.render('admin/plugins/openai', {
7
11
  title: 'OpenAI',
12
+ groups: groupsData,
8
13
  });
9
14
  };
package/library.js CHANGED
@@ -13,9 +13,22 @@ const topics = require.main.require('./src/topics');
13
13
  const user = require.main.require('./src/user');
14
14
  const messaging = require.main.require('./src/messaging');
15
15
  const api = require.main.require('./src/api');
16
+ const privileges = require.main.require('./src/privileges');
17
+ const groups = require.main.require('./src/groups');
18
+ const sockets = require.main.require('./src/socket.io');
16
19
 
17
20
  const plugin = module.exports;
18
21
 
22
+ const defaults = {
23
+ apikey: '',
24
+ 'chatgpt-username': '',
25
+ enablePrivateMessages: 'off',
26
+ model: 'gpt-3.5-turbo',
27
+ minimumReputation: 0,
28
+ allowedGroups: '[]',
29
+ };
30
+
31
+
19
32
  plugin.init = async (params) => {
20
33
  const { router /* , middleware , controllers */ } = params;
21
34
  const settings = await meta.settings.get('openai')
@@ -28,6 +41,11 @@ plugin.init = async (params) => {
28
41
  routeHelpers.setupAdminPageRoute(router, '/admin/plugins/openai', controllers.renderAdminPage);
29
42
  };
30
43
 
44
+ async function getSettings() {
45
+ const settings = await meta.settings.get('openai')
46
+ return {...defaults, ...settings };
47
+ }
48
+
31
49
  plugin.actionMentionsNotify = async function (hookData) {
32
50
  try {
33
51
  const { notification } = hookData;
@@ -35,13 +53,21 @@ plugin.actionMentionsNotify = async function (hookData) {
35
53
  return;
36
54
  }
37
55
 
38
- const settings = (await meta.settings.get('openai')) || {};
56
+ const settings = await getSettings();
57
+ if (!await canUseOpenAI(notification.from, settings)) {
58
+ return;
59
+ }
60
+
39
61
  const chatgptusername = settings['chatgpt-username'];
40
62
  const chatgptUid = await user.getUidByUsername(chatgptusername);
41
63
  if (!chatgptUid) {
42
64
  return;
43
65
  }
44
66
  if (notification.tid && notification.bodyLong.startsWith(`@${chatgptusername}`)) {
67
+ const canReply = await privileges.topics.can('topics:reply', notification.tid, chatgptUid);
68
+ if (!canReply) {
69
+ return;
70
+ }
45
71
  const message = notification.bodyLong.replace(new RegExp(`^@${chatgptusername}`), '');
46
72
  if (message.length) {
47
73
  const response = await chatComplete(message);
@@ -74,7 +100,11 @@ plugin.actionMessagingSave = async function (hookData) {
74
100
  if (message.system) {
75
101
  return;
76
102
  }
77
- const settings = (await meta.settings.get('openai')) || {};
103
+ const settings = await getSettings();
104
+ if (!await canUseOpenAI(message.fromuid, settings)) {
105
+ return;
106
+ }
107
+
78
108
  const chatgptusername = settings['chatgpt-username'];
79
109
  const chatgptUid = await user.getUidByUsername(chatgptusername);
80
110
  const { roomId, content, fromuid } = message;
@@ -135,6 +165,55 @@ plugin.actionMessagingSave = async function (hookData) {
135
165
  }
136
166
  };
137
167
 
168
+ async function canUseOpenAI(uid, settings) {
169
+ if (!await checkReputation(uid, settings)) {
170
+ return false;
171
+ }
172
+ if (!await checkGroupMembership(uid, settings)) {
173
+ return false;
174
+ }
175
+ return true;
176
+ }
177
+
178
+ async function checkReputation(uid, settings) {
179
+ const reputation = await user.getUserField(uid, 'reputation');
180
+ const hasEnoughRep = parseInt(settings.minimumReputation, 10) === 0 || parseInt(reputation, 10) >= parseInt(settings.minimumReputation, 10);
181
+
182
+ if (!hasEnoughRep) {
183
+ sockets.server.in(`uid_${uid}`).emit('event:alert', {
184
+ type: 'danger',
185
+ title: '[[global:alert.error]]',
186
+ message: `[[openai:error.need-x-reputation-to-mention, ${settings.minimumReputation}]]`,
187
+ });
188
+ }
189
+ return hasEnoughRep;
190
+ }
191
+
192
+ async function checkGroupMembership(uid, settings) {
193
+ let allowedGroups = [];
194
+ try {
195
+ allowedGroups = JSON.parse(settings.allowedGroups) || [];
196
+ } catch (err) {
197
+ console.error(err);
198
+ allowedGroups = [];
199
+ }
200
+
201
+ if (!allowedGroups.length) {
202
+ return true;
203
+ }
204
+
205
+ const isMembers = await groups.isMemberOfGroups(uid, allowedGroups);
206
+ const memberOfAny = isMembers.includes(true);
207
+ if (!memberOfAny) {
208
+ sockets.server.in(`uid_${uid}`).emit('event:alert', {
209
+ type: 'danger',
210
+ title: '[[global:alert.error]]',
211
+ message: `[[error:no-privileges]]`,
212
+ });
213
+ }
214
+ return memberOfAny;
215
+ }
216
+
138
217
  async function getMessageIds(roomId, uid, start, stop) {
139
218
  const isPublic = await db.getObjectField(`chat:room:${roomId}`, 'public');
140
219
  if (parseInt(isPublic, 10) === 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-openai",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A NodeBB OpenAI plugin",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "compatibility": "^3.2.0"
34
34
  },
35
35
  "dependencies": {
36
- "openai": "4.53.0"
36
+ "openai": "4.53.2"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@commitlint/cli": "19.3.0",
package/plugin.json CHANGED
@@ -11,5 +11,6 @@
11
11
  "modules": {
12
12
  "../admin/plugins/openai.js": "./public/lib/admin.js"
13
13
  },
14
- "templates": "templates"
14
+ "templates": "templates",
15
+ "languages": "languages"
15
16
  }
@@ -41,6 +41,28 @@
41
41
  </select>
42
42
  </div>
43
43
  </div>
44
+ <div class="">
45
+ <h5 class="fw-bold tracking-tight settings-header">Restrictions</h5>
46
+
47
+ <div class="mb-3">
48
+ <label class="form-label" for="minimumReputation">Minimum Reputation</label>
49
+ <input type="text" id="minimumReputation" name="minimumReputation" title="Minimum Reputation" class="form-control">
50
+ <p class="form-text">
51
+ Minimum reputation required to mention chatgpt user. (0 to disable)
52
+ </p>
53
+ </div>
54
+ <div class="mb-3">
55
+ <label class="form-label" form="allowedGroups">Allowed Groups</label>
56
+ <select class="form-select" multiple id="allowedGroups" name="allowedGroups" size="10">
57
+ {{{ each groups }}}
58
+ <option value="{./displayName}">{./displayName}</option>
59
+ {{{ end }}}
60
+ </select>
61
+ <p class="form-text">
62
+ Only users in these groups will be able to mention the chatgpt user. Leave blank to allow all groups.
63
+ </p>
64
+ </div>
65
+ </div>
44
66
  </form>
45
67
  </div>
46
68