ep_chat_log_join_leave 1.0.2 → 1.0.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.
@@ -85,3 +85,7 @@ jobs:
85
85
  - run: npm publish
86
86
  env:
87
87
  NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
88
+ - name: Add package to etherpad organization
89
+ run: npm access grant read-write etherpad:developers
90
+ env:
91
+ NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ ![Publish Status](https://github.com/ether/ep_chat_log_join_leave/workflows/Node.js%20Package/badge.svg) ![Backend Tests Status](https://github.com/ether/ep_chat_log_join_leave/workflows/Backend%20tests/badge.svg)
2
+
1
3
  # ep_chat_log_join_leave
2
4
 
3
5
  Etherpad plugin to log user joins and leaves in the chat history.
package/index.js CHANGED
@@ -7,11 +7,17 @@ const ChatMessage = (() => {
7
7
  return null;
8
8
  }
9
9
  })();
10
+ const assert = require('assert').strict;
10
11
  const log4js = require('ep_etherpad-lite/node_modules/log4js');
11
12
  const padMessageHandler = require('ep_etherpad-lite/node/handler/PadMessageHandler');
12
13
 
13
14
  const logger = log4js.getLogger('ep_chat_log_join_leave');
14
15
 
16
+ if (ChatMessage == null) {
17
+ logger.error('This version of Etherpad is unsupported. ' +
18
+ 'Please upgrade to Etherpad v1.8.15 or later to use this plugin.');
19
+ }
20
+
15
21
  /**
16
22
  * How long to wait until a disconnected user is declared gone. (Network flakiness could cause a
17
23
  * user to briefly disconnect and reconnect. Those shouldn't appear in the chat history.)
@@ -21,56 +27,76 @@ const logger = log4js.getLogger('ep_chat_log_join_leave');
21
27
  const timeout = 10000;
22
28
 
23
29
  /**
24
- * Maps a pad ID to another map that maps an author ID to null (if the user is currently connected)
25
- * or to a timeout ID for a timeout that will fire when the user has been gone long enough to inform
26
- * users (if the user recently disconnected).
27
- *
28
- * @type {Map<string, Map<string, number>>}
30
+ * Maps a {padId, authorId} pair to null (if the user is currently connected) or to an ID for a
31
+ * timeout that will fire when the recently disconnected user has been gone long enough to inform
32
+ * users about the departure.
29
33
  */
30
- const activeUsersPerPad = new Map();
34
+ const activeUsers = new class {
35
+ constructor() {
36
+ /**
37
+ * Maps a pad ID to another map that maps an author ID to null or a timeout ID.
38
+ *
39
+ * @type {Map<string, Map<string, number>>}
40
+ */
41
+ this._users = new Map();
42
+ }
43
+
44
+ has(padId, authorId) {
45
+ return this._users.has(padId) && this._users.get(padId).has(authorId);
46
+ }
47
+
48
+ get(padId, authorId) {
49
+ const m = this._users.get(padId);
50
+ return m && m.get(authorId);
51
+ }
52
+
53
+ set(padId, authorId, value) {
54
+ if (!this._users.has(padId)) this._users.set(padId, new Map());
55
+ this._users.get(padId).set(authorId, value);
56
+ }
57
+
58
+ delete(padId, authorId) {
59
+ const m = this._users.get(padId);
60
+ if (m == null) return;
61
+ m.delete(authorId);
62
+ if (m.size === 0) this._users.delete(padId);
63
+ }
64
+ }();
31
65
 
32
66
  exports.eejsBlock_styles = (hookName, context) => {
67
+ if (ChatMessage == null) return;
33
68
  const css = 'ep_chat_log_join_leave/static/css/index.css';
34
69
  context.content += `<link href="../static/plugins/${css}" rel="stylesheet">`;
35
70
  };
36
71
 
37
72
  exports.userJoin = async (hookName, {authorId, padId}) => {
38
- if (!activeUsersPerPad.has(padId)) activeUsersPerPad.set(padId, new Map());
39
- const activeUsers = activeUsersPerPad.get(padId);
40
- if (activeUsers.has(authorId)) {
73
+ if (ChatMessage == null) return;
74
+ assert.equal(typeof authorId, 'string');
75
+ assert.equal(typeof padId, 'string');
76
+ const timeout = activeUsers.get(padId, authorId);
77
+ if (timeout) {
41
78
  clearTimeout(activeUsers.get(authorId));
42
- } else if (ChatMessage != null) {
43
- // Etherpad >= v1.8.15.
79
+ } else {
44
80
  const msg = new ChatMessage('', authorId, Date.now());
45
81
  msg.ep_chat_log_join_leave = 'join';
46
82
  await padMessageHandler.sendChatMessageToPadClients(msg, padId);
47
- } else {
48
- // Etherpad <= v1.8.14.
49
- logger.warn('This version of Etherpad does not support custom chat message rendering. ' +
50
- 'Please upgrade to Etherpad v1.8.15 or later.');
51
- const txt = 'joined the pad'; // User must upgrade Etherpad to >= v1.8.15 to localize this.
52
- await padMessageHandler.sendChatMessageToPadClients(Date.now(), authorId, txt, padId);
53
83
  }
54
- activeUsers.set(authorId, null);
84
+ activeUsers.set(padId, authorId, null);
55
85
  };
56
86
 
57
87
  exports.userLeave = async (hookName, {authorId, padId}) => {
58
- // TODO: l10n
59
- const activeUsers = activeUsersPerPad.get(padId);
60
- clearTimeout(activeUsers.get(authorId));
61
- activeUsers.set(authorId, setTimeout(async () => {
62
- activeUsers.delete(authorId);
63
- if (activeUsers.size === 0) activeUsersPerPad.delete(padId);
88
+ if (ChatMessage == null) return;
89
+ // With Etherpad <= v1.8.14, the userLeave event can fire with a nullish padId if the user
90
+ // disconnected before sending a CLIENT_READY message.
91
+ if (padId == null) return;
92
+ assert.equal(typeof authorId, 'string');
93
+ assert.equal(typeof padId, 'string');
94
+ clearTimeout(activeUsers.get(padId, authorId));
95
+ activeUsers.set(padId, authorId, setTimeout(async () => {
96
+ activeUsers.delete(padId, authorId);
64
97
  const when = Date.now() - timeout;
65
- if (ChatMessage != null) {
66
- // Etherpad >= v1.8.15.
67
- const msg = new ChatMessage('', authorId, when);
68
- msg.ep_chat_log_join_leave = 'leave';
69
- await padMessageHandler.sendChatMessageToPadClients(msg, padId);
70
- } else {
71
- // Etherpad <= v1.8.14. Warning was logged when the user joined, no need to repeat it.
72
- const txt = 'left the pad'; // User must upgrade Etherpad to >= v1.8.15 to localize this.
73
- await padMessageHandler.sendChatMessageToPadClients(when, authorId, txt, padId);
74
- }
98
+ const msg = new ChatMessage('', authorId, when);
99
+ msg.ep_chat_log_join_leave = 'leave';
100
+ await padMessageHandler.sendChatMessageToPadClients(msg, padId);
75
101
  }, timeout));
76
102
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ep_chat_log_join_leave",
3
- "version": "1.0.2",
3
+ "version": "1.0.6",
4
4
  "description": "Etherpad plugin to log user joins and leaves in the chat history",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -23,14 +23,14 @@
23
23
  },
24
24
  "homepage": "https://github.com/ether/ep_chat_log_join_leave#readme",
25
25
  "devDependencies": {
26
- "eslint": "^7.28.0",
27
- "eslint-config-etherpad": "^2.0.0",
28
- "eslint-plugin-cypress": "^2.11.3",
26
+ "eslint": "^7.32.0",
27
+ "eslint-config-etherpad": "^2.0.2",
28
+ "eslint-plugin-cypress": "^2.12.1",
29
29
  "eslint-plugin-eslint-comments": "^3.2.0",
30
30
  "eslint-plugin-mocha": "^9.0.0",
31
31
  "eslint-plugin-node": "^11.1.0",
32
32
  "eslint-plugin-prefer-arrow": "^1.2.3",
33
- "eslint-plugin-promise": "^5.1.0",
33
+ "eslint-plugin-promise": "^5.1.1",
34
34
  "eslint-plugin-you-dont-need-lodash-underscore": "^6.12.0"
35
35
  },
36
36
  "peerDependencies": {
@@ -8,8 +8,6 @@ const defaultMsg = {
8
8
  leave: 'left the pad',
9
9
  };
10
10
 
11
- exports.aceEditorCSS = (hookName, context) => ['ep_chat_log_join_leave/static/css/index.css'];
12
-
13
11
  exports.chatNewMessage = async (hookName, context) => {
14
12
  if (context.message == null) {
15
13
  // Etherpad <= v1.8.14 doesn't support custom message rendering. A warning was logged on the