serverless-ircd 0.6.0 → 0.7.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.
Files changed (247) hide show
  1. package/.github/workflows/ci.yml +6 -1
  2. package/.gitmodules +3 -0
  3. package/CHANGELOG.md +214 -0
  4. package/README.md +110 -23
  5. package/apps/aws-stack/package.json +1 -1
  6. package/apps/cf-tcp-container/package.json +1 -1
  7. package/apps/cf-worker/package.json +1 -1
  8. package/apps/cf-worker/src/origin-allowlist.ts +99 -0
  9. package/apps/cf-worker/src/worker.ts +89 -9
  10. package/apps/cf-worker/tests/fixtures/web-dist/app/index.html +18 -0
  11. package/apps/cf-worker/tests/fixtures/web-dist/index.html +18 -0
  12. package/apps/cf-worker/tests/origin-allowlist.test.ts +101 -0
  13. package/apps/cf-worker/tests/smoke.test.ts +28 -2
  14. package/apps/cf-worker/tests/ws-origin.test.ts +89 -0
  15. package/apps/cf-worker/wrangler.test.toml +23 -0
  16. package/apps/cf-worker/wrangler.toml +54 -0
  17. package/apps/local-cli/package.json +1 -1
  18. package/apps/web/landing/index.html +217 -0
  19. package/apps/web/package.json +28 -0
  20. package/apps/web/scripts/build.mjs +125 -0
  21. package/apps/web/src/build-env.ts +43 -0
  22. package/apps/web/src/config-schema.ts +138 -0
  23. package/apps/web/static/config.json +28 -0
  24. package/apps/web/static/config.prod.json +28 -0
  25. package/apps/web/static/config.staging.json +28 -0
  26. package/apps/web/tests/build-env.test.ts +63 -0
  27. package/apps/web/tests/build-smoke.test.ts +103 -0
  28. package/apps/web/tests/config-schema.test.ts +432 -0
  29. package/apps/web/tests/workspace.test.ts +12 -0
  30. package/apps/web/tsconfig.json +10 -0
  31. package/apps/web/upstream/.browserslistrc +3 -0
  32. package/apps/web/upstream/.editorconfig +9 -0
  33. package/apps/web/upstream/.eslintignore +3 -0
  34. package/apps/web/upstream/.eslintrc.js +90 -0
  35. package/apps/web/upstream/.github/FUNDING.yml +12 -0
  36. package/apps/web/upstream/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  37. package/apps/web/upstream/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  38. package/apps/web/upstream/.github/workflows/push.yml +26 -0
  39. package/apps/web/upstream/.github/workflows/release.yml +33 -0
  40. package/apps/web/upstream/.github/workflows/release_manual.yml +55 -0
  41. package/apps/web/upstream/.prettierrc.js +9 -0
  42. package/apps/web/upstream/.stylelintignore +5 -0
  43. package/apps/web/upstream/.stylelintrc.js +21 -0
  44. package/apps/web/upstream/LICENSE +201 -0
  45. package/apps/web/upstream/README.md +76 -0
  46. package/apps/web/upstream/babel.config.js +25 -0
  47. package/apps/web/upstream/crowdin.yml +3 -0
  48. package/apps/web/upstream/index.html +35 -0
  49. package/apps/web/upstream/jest.config.js +7 -0
  50. package/apps/web/upstream/jsdoc.json +22 -0
  51. package/apps/web/upstream/package.json +80 -0
  52. package/apps/web/upstream/scripts/pre-commit +43 -0
  53. package/apps/web/upstream/src/components/App.vue +516 -0
  54. package/apps/web/upstream/src/components/AppSettings.vue +587 -0
  55. package/apps/web/upstream/src/components/AutoComplete.vue +284 -0
  56. package/apps/web/upstream/src/components/Avatar.vue +105 -0
  57. package/apps/web/upstream/src/components/AwayStatusIndicator.vue +77 -0
  58. package/apps/web/upstream/src/components/BufferKey.vue +121 -0
  59. package/apps/web/upstream/src/components/BufferSettings.vue +97 -0
  60. package/apps/web/upstream/src/components/Captcha.vue +85 -0
  61. package/apps/web/upstream/src/components/ChannelBanlist.vue +96 -0
  62. package/apps/web/upstream/src/components/ChannelInfo.vue +159 -0
  63. package/apps/web/upstream/src/components/ChannelInvitelist.vue +276 -0
  64. package/apps/web/upstream/src/components/ChannelList.vue +345 -0
  65. package/apps/web/upstream/src/components/Container.vue +401 -0
  66. package/apps/web/upstream/src/components/ContainerHeader.vue +522 -0
  67. package/apps/web/upstream/src/components/ControlInput.vue +1016 -0
  68. package/apps/web/upstream/src/components/LoadingAnimation.vue +104 -0
  69. package/apps/web/upstream/src/components/MediaViewer.vue +199 -0
  70. package/apps/web/upstream/src/components/MessageInfo.vue +192 -0
  71. package/apps/web/upstream/src/components/MessageList.vue +1028 -0
  72. package/apps/web/upstream/src/components/MessageListAvatar.vue +20 -0
  73. package/apps/web/upstream/src/components/MessageListMessageCompact.vue +361 -0
  74. package/apps/web/upstream/src/components/MessageListMessageInline.vue +257 -0
  75. package/apps/web/upstream/src/components/MessageListMessageModern.vue +430 -0
  76. package/apps/web/upstream/src/components/NetworkSettings.vue +528 -0
  77. package/apps/web/upstream/src/components/Nicklist.vue +309 -0
  78. package/apps/web/upstream/src/components/NicklistUser.vue +181 -0
  79. package/apps/web/upstream/src/components/NotConnected.vue +271 -0
  80. package/apps/web/upstream/src/components/SelfUser.vue +283 -0
  81. package/apps/web/upstream/src/components/ServerSelector.vue +162 -0
  82. package/apps/web/upstream/src/components/ServerView.vue +126 -0
  83. package/apps/web/upstream/src/components/SettingsAdvanced.vue +232 -0
  84. package/apps/web/upstream/src/components/SettingsAliases.vue +121 -0
  85. package/apps/web/upstream/src/components/Sidebar.vue +429 -0
  86. package/apps/web/upstream/src/components/SidebarAboutBuffer.vue +288 -0
  87. package/apps/web/upstream/src/components/SidebarState.vue +145 -0
  88. package/apps/web/upstream/src/components/StartupError.vue +35 -0
  89. package/apps/web/upstream/src/components/StateBrowser.vue +420 -0
  90. package/apps/web/upstream/src/components/StateBrowserBuffer.vue +124 -0
  91. package/apps/web/upstream/src/components/StateBrowserNetwork.vue +823 -0
  92. package/apps/web/upstream/src/components/StateBrowserUsermenu.vue +162 -0
  93. package/apps/web/upstream/src/components/TypingStatusIndicator.vue +34 -0
  94. package/apps/web/upstream/src/components/TypingUsersList.vue +56 -0
  95. package/apps/web/upstream/src/components/UrlEmbed.vue +149 -0
  96. package/apps/web/upstream/src/components/UserBox.vue +728 -0
  97. package/apps/web/upstream/src/components/inputtools/Emoji.vue +67 -0
  98. package/apps/web/upstream/src/components/inputtools/TextStyle.vue +142 -0
  99. package/apps/web/upstream/src/components/startups/CommonLayout.vue +208 -0
  100. package/apps/web/upstream/src/components/startups/CustomServer.vue +495 -0
  101. package/apps/web/upstream/src/components/startups/KiwiBnc.vue +361 -0
  102. package/apps/web/upstream/src/components/startups/Personal.vue +317 -0
  103. package/apps/web/upstream/src/components/startups/Welcome.vue +544 -0
  104. package/apps/web/upstream/src/components/startups/ZncLogin.vue +229 -0
  105. package/apps/web/upstream/src/components/utils/InputConfirm.vue +68 -0
  106. package/apps/web/upstream/src/components/utils/InputPrompt.vue +118 -0
  107. package/apps/web/upstream/src/components/utils/InputText.vue +172 -0
  108. package/apps/web/upstream/src/components/utils/IrcInput.vue +579 -0
  109. package/apps/web/upstream/src/components/utils/PluginWrapper.vue +26 -0
  110. package/apps/web/upstream/src/components/utils/TabbedView.vue +149 -0
  111. package/apps/web/upstream/src/components/utils/TransitionExpand.vue +97 -0
  112. package/apps/web/upstream/src/helpers/Colours.js +128 -0
  113. package/apps/web/upstream/src/helpers/IrcdDiffs.js +26 -0
  114. package/apps/web/upstream/src/helpers/Md5.js +193 -0
  115. package/apps/web/upstream/src/helpers/Misc.js +401 -0
  116. package/apps/web/upstream/src/helpers/TextFormatting.js +237 -0
  117. package/apps/web/upstream/src/libs/AliasRewriter.js +157 -0
  118. package/apps/web/upstream/src/libs/AudioManager.js +60 -0
  119. package/apps/web/upstream/src/libs/BouncerMiddleware.js +247 -0
  120. package/apps/web/upstream/src/libs/BouncerProvider.js +551 -0
  121. package/apps/web/upstream/src/libs/ChathistoryMiddleware.js +153 -0
  122. package/apps/web/upstream/src/libs/ConfigLoader.js +94 -0
  123. package/apps/web/upstream/src/libs/EmojiProvider.js +46 -0
  124. package/apps/web/upstream/src/libs/GlobalApi.js +346 -0
  125. package/apps/web/upstream/src/libs/IPC.js +51 -0
  126. package/apps/web/upstream/src/libs/InputHandler.js +921 -0
  127. package/apps/web/upstream/src/libs/IrcClient.js +1506 -0
  128. package/apps/web/upstream/src/libs/Logger.js +71 -0
  129. package/apps/web/upstream/src/libs/Message.js +169 -0
  130. package/apps/web/upstream/src/libs/MessageFormatter.js +364 -0
  131. package/apps/web/upstream/src/libs/MessageParser.js +249 -0
  132. package/apps/web/upstream/src/libs/Notifications.js +78 -0
  133. package/apps/web/upstream/src/libs/ServerConnection.js +270 -0
  134. package/apps/web/upstream/src/libs/ServerSession.js +102 -0
  135. package/apps/web/upstream/src/libs/SoundBleep.js +20 -0
  136. package/apps/web/upstream/src/libs/StatePersistence.js +90 -0
  137. package/apps/web/upstream/src/libs/ThemeManager.js +128 -0
  138. package/apps/web/upstream/src/libs/TypingMiddleware.js +105 -0
  139. package/apps/web/upstream/src/libs/WindowTitle.js +63 -0
  140. package/apps/web/upstream/src/libs/batchedAdd.js +74 -0
  141. package/apps/web/upstream/src/libs/bufferTools.js +177 -0
  142. package/apps/web/upstream/src/libs/polyfill/Element.closest.js +18 -0
  143. package/apps/web/upstream/src/libs/renderers/Html.js +113 -0
  144. package/apps/web/upstream/src/libs/settingTools.js +31 -0
  145. package/apps/web/upstream/src/libs/state/BufferState.js +703 -0
  146. package/apps/web/upstream/src/libs/state/NetworkState.js +158 -0
  147. package/apps/web/upstream/src/libs/state/UserState.js +89 -0
  148. package/apps/web/upstream/src/libs/state/common.js +26 -0
  149. package/apps/web/upstream/src/libs/state.js +961 -0
  150. package/apps/web/upstream/src/libs/storage/Local.js +51 -0
  151. package/apps/web/upstream/src/main.js +566 -0
  152. package/apps/web/upstream/src/res/autocompleteCommands.js +31 -0
  153. package/apps/web/upstream/src/res/configTemplates.js +373 -0
  154. package/apps/web/upstream/src/res/globalStyle.css +277 -0
  155. package/apps/web/upstream/src/res/kiwiLoadingLogo.png +0 -0
  156. package/apps/web/upstream/src/res/locales/app.af-ZA.po +1145 -0
  157. package/apps/web/upstream/src/res/locales/app.ar-SA.po +1145 -0
  158. package/apps/web/upstream/src/res/locales/app.bg-BG.po +1145 -0
  159. package/apps/web/upstream/src/res/locales/app.bs-BA.po +1145 -0
  160. package/apps/web/upstream/src/res/locales/app.ca-ES.po +1145 -0
  161. package/apps/web/upstream/src/res/locales/app.cs-CZ.po +1145 -0
  162. package/apps/web/upstream/src/res/locales/app.da-DK.po +1145 -0
  163. package/apps/web/upstream/src/res/locales/app.de-DE.po +1145 -0
  164. package/apps/web/upstream/src/res/locales/app.dev.po +1246 -0
  165. package/apps/web/upstream/src/res/locales/app.el-GR.po +1145 -0
  166. package/apps/web/upstream/src/res/locales/app.en-US.po +1145 -0
  167. package/apps/web/upstream/src/res/locales/app.es-419.po +1145 -0
  168. package/apps/web/upstream/src/res/locales/app.es-AR.po +1145 -0
  169. package/apps/web/upstream/src/res/locales/app.es-EM.po +536 -0
  170. package/apps/web/upstream/src/res/locales/app.es-ES.po +1145 -0
  171. package/apps/web/upstream/src/res/locales/app.es-US.po +1145 -0
  172. package/apps/web/upstream/src/res/locales/app.eu-ES.po +1145 -0
  173. package/apps/web/upstream/src/res/locales/app.fi-FI.po +1145 -0
  174. package/apps/web/upstream/src/res/locales/app.fr-FR.po +1145 -0
  175. package/apps/web/upstream/src/res/locales/app.gl-ES.po +1145 -0
  176. package/apps/web/upstream/src/res/locales/app.he-IL.po +1145 -0
  177. package/apps/web/upstream/src/res/locales/app.hi-IN.po +1145 -0
  178. package/apps/web/upstream/src/res/locales/app.hu-HU.po +1145 -0
  179. package/apps/web/upstream/src/res/locales/app.id-ID.po +1145 -0
  180. package/apps/web/upstream/src/res/locales/app.it-IT.po +1145 -0
  181. package/apps/web/upstream/src/res/locales/app.ja-JP.po +1145 -0
  182. package/apps/web/upstream/src/res/locales/app.ko-KR.po +1145 -0
  183. package/apps/web/upstream/src/res/locales/app.nl-NL.po +1145 -0
  184. package/apps/web/upstream/src/res/locales/app.no-NO.po +1145 -0
  185. package/apps/web/upstream/src/res/locales/app.pl-PL.po +1145 -0
  186. package/apps/web/upstream/src/res/locales/app.pt-BR.po +1145 -0
  187. package/apps/web/upstream/src/res/locales/app.pt-PT.po +1145 -0
  188. package/apps/web/upstream/src/res/locales/app.ro-RO.po +1145 -0
  189. package/apps/web/upstream/src/res/locales/app.ru-RU.po +1145 -0
  190. package/apps/web/upstream/src/res/locales/app.sl-SI.po +1145 -0
  191. package/apps/web/upstream/src/res/locales/app.sq-AL.po +1145 -0
  192. package/apps/web/upstream/src/res/locales/app.sr-SP.po +1145 -0
  193. package/apps/web/upstream/src/res/locales/app.sv-SE.po +1145 -0
  194. package/apps/web/upstream/src/res/locales/app.tr-TR.po +1145 -0
  195. package/apps/web/upstream/src/res/locales/app.uk-UA.po +1145 -0
  196. package/apps/web/upstream/src/res/locales/app.vi-VN.po +1145 -0
  197. package/apps/web/upstream/src/res/locales/app.zh-CN.po +1145 -0
  198. package/apps/web/upstream/src/res/locales/app.zh-TW.po +1145 -0
  199. package/apps/web/upstream/src/res/localesList.json +27 -0
  200. package/apps/web/upstream/src/res/logo.png +0 -0
  201. package/apps/web/upstream/src/thirdparty/about.html +43 -0
  202. package/apps/web/upstream/src/thirdparty/index.js +5 -0
  203. package/apps/web/upstream/src/thirdparty/kiwiirccom.vue +185 -0
  204. package/apps/web/upstream/static/config.json +28 -0
  205. package/apps/web/upstream/static/emoticons/smile.png +0 -0
  206. package/apps/web/upstream/static/favicon.png +0 -0
  207. package/apps/web/upstream/static/highlight.mp3 +0 -0
  208. package/apps/web/upstream/static/highlight.ogg +0 -0
  209. package/apps/web/upstream/static/locales/.gitignore +2 -0
  210. package/apps/web/upstream/static/plugins/customise.html.example +10 -0
  211. package/apps/web/upstream/static/themes/coffee/theme.css +145 -0
  212. package/apps/web/upstream/static/themes/common/base.css +1064 -0
  213. package/apps/web/upstream/static/themes/dark/theme.css +196 -0
  214. package/apps/web/upstream/static/themes/default/theme.css +92 -0
  215. package/apps/web/upstream/static/themes/elite/theme.css +248 -0
  216. package/apps/web/upstream/static/themes/grayfox/theme.css +143 -0
  217. package/apps/web/upstream/static/themes/nightswatch/theme.css +367 -0
  218. package/apps/web/upstream/static/themes/osprey/theme.css +115 -0
  219. package/apps/web/upstream/static/themes/radioactive/theme.css +1211 -0
  220. package/apps/web/upstream/static/themes/sky/theme.css +107 -0
  221. package/apps/web/upstream/tests/unit/BatchAdd.spec.js +174 -0
  222. package/apps/web/upstream/tests/unit/MessageParser.spec.js +125 -0
  223. package/apps/web/upstream/tests/unit/Misc.spec.js +24 -0
  224. package/apps/web/upstream/tests/unit/NetworkState.spec.js +58 -0
  225. package/apps/web/upstream/tests/unit/StartupError.spec.js +20 -0
  226. package/apps/web/upstream/vue.config.js +150 -0
  227. package/apps/web/upstream/yarn.lock +9767 -0
  228. package/apps/web/vitest.config.ts +13 -0
  229. package/biome.json +1 -0
  230. package/docs/Home.md +1 -0
  231. package/docs/WebClientGuide.md +535 -0
  232. package/package.json +2 -2
  233. package/packages/aws-adapter/package.json +1 -1
  234. package/packages/cf-adapter/package.json +1 -1
  235. package/packages/cf-adapter/tests/cf-harness.ts +12 -1
  236. package/packages/in-memory-runtime/package.json +1 -1
  237. package/packages/irc-core/package.json +1 -1
  238. package/packages/irc-core/reports/mutation/mutation.html +342 -0
  239. package/packages/irc-core/tests/batch.test.ts +15 -0
  240. package/packages/irc-core/tests/numerics.test.ts +13 -0
  241. package/packages/irc-core/tests/parser.test.ts +109 -0
  242. package/packages/irc-server/package.json +1 -1
  243. package/packages/irc-test-support/package.json +1 -1
  244. package/packages/irc-test-support/src/scenarios.ts +24 -2
  245. package/tools/ci-hardening/package.json +1 -1
  246. package/tools/load-test/package.json +1 -1
  247. package/tools/tcp-ws-forwarder/package.json +1 -1
@@ -0,0 +1,157 @@
1
+ 'kiwi public';
2
+
3
+ /** @module */
4
+
5
+ /**
6
+ * Command input Alias + re-writing
7
+ *
8
+ * Variables used in aliases:
9
+ * - $0 = the command being run
10
+ * - $1 = first param of input
11
+ * - $N = Nth param of input
12
+ * - $1+2 = first param of input and the next 2 words
13
+ * - $2+4 = second param of input and the next 4 words
14
+ * - $2+ = second param of input and all words after
15
+ * - $variable = variable as set in the vars object
16
+ */
17
+ export default class AliasRewriter {
18
+ constructor() {
19
+ // Max alias recursion depth
20
+ this.recursiveDepth = 3;
21
+ // Current alias recursion depth
22
+ this.depth = 0;
23
+
24
+ this.aliases = {};
25
+ }
26
+
27
+ /** Reset the current aliases object from a newline delimited string of aliases */
28
+ importFromString(str) {
29
+ // Clear out the current aliases before adding new ones in
30
+ this.aliases = {};
31
+
32
+ str.split('\n').forEach((line) => {
33
+ if (line[0] !== '/') {
34
+ return;
35
+ }
36
+
37
+ let spaceSep = line.indexOf(' ');
38
+ if (spaceSep === -1) {
39
+ return;
40
+ }
41
+
42
+ let command = line.substring(0, spaceSep);
43
+ let actions = line.substring(spaceSep + 1).trim();
44
+ if (!actions) {
45
+ return;
46
+ }
47
+
48
+ this.aliases[command.toLowerCase()] = actions;
49
+ });
50
+ }
51
+
52
+ // Takes an array of words to process!
53
+ processInput(input, vars) {
54
+ let words = input || [];
55
+ let alias = this.aliases[words[0].toLowerCase()];
56
+ let aliasLen;
57
+ let currentAliasWord = '';
58
+ let currentAliasWordLen = 0;
59
+ let processedConditionals = false;
60
+ let compiled = [];
61
+
62
+ // If an alias wasn't found, return the original input
63
+ if (!alias) return input;
64
+
65
+ // Split the alias up into useable words
66
+ alias = alias.split(' ');
67
+ aliasLen = alias.length;
68
+
69
+ // Iterate over each word and pop them into the final compiled array.
70
+ // Any $ words are processed with the result ending into the compiled array.
71
+ for (let i = 0; i < aliasLen; i++) {
72
+ currentAliasWord = alias[i];
73
+ currentAliasWordLen = currentAliasWord.length;
74
+
75
+ // $var? word makes this command only run if the var exists
76
+ if (
77
+ !processedConditionals &&
78
+ currentAliasWord[0] === '$' && currentAliasWord[currentAliasWordLen - 1] === '?'
79
+ ) {
80
+ let checkVar = currentAliasWord.substr(1, currentAliasWordLen - 2);
81
+ if (!vars[checkVar]) {
82
+ compiled = [];
83
+ break;
84
+ } else {
85
+ continue;
86
+ }
87
+ } else {
88
+ processedConditionals = true;
89
+ }
90
+
91
+ // Non $ word
92
+ if (currentAliasWord[0] !== '$') {
93
+ compiled.push(currentAliasWord);
94
+ continue;
95
+ }
96
+
97
+ // Refering to an input word ($N)
98
+ if ((currentAliasWord[1] || '').match(/\d/)) {
99
+ let num = currentAliasWord.match(/\$(\d+)(\+)?(\d+)?/);
100
+
101
+ // Did we find anything or does the word it refers to non-existant?
102
+ if (!num || !words[num[1]]) continue;
103
+
104
+ if (num[2] === '+' && num[3]) {
105
+ // Add X number of words
106
+ compiled = compiled.concat(words.slice(
107
+ parseInt(num[1], 10),
108
+ parseInt(num[1], 10) + parseInt(num[3], 10)
109
+ ));
110
+ } else if (num[2] === '+') {
111
+ // Add the remaining of the words
112
+ compiled = compiled.concat(words.slice(parseInt(num[1], 10)));
113
+ } else {
114
+ // Add a single word
115
+ compiled.push(words[parseInt(num[1], 10)]);
116
+ }
117
+
118
+ continue;
119
+ }
120
+
121
+ // Refering to a variable
122
+ if (typeof vars[currentAliasWord.substr(1)] !== 'undefined') {
123
+ // Get the variable
124
+ compiled.push(vars[currentAliasWord.substr(1)]);
125
+
126
+ continue;
127
+ }
128
+ }
129
+
130
+ return compiled;
131
+ }
132
+
133
+ /** Take a string input, process any aliases and output the finalised string */
134
+ process(input, vars) {
135
+ let line = input || '';
136
+ let words = line.split(' ');
137
+ let firstWord = (words[0] || '').toLowerCase();
138
+
139
+ this.depth++;
140
+ if (this.depth >= this.recursiveDepth) {
141
+ this.depth--;
142
+ return line;
143
+ }
144
+
145
+ if (this.aliases[firstWord]) {
146
+ words = this.processInput(words, vars);
147
+ firstWord = (words[0] || '').toLowerCase();
148
+
149
+ if (this.aliases[firstWord]) {
150
+ words = this.process(words.join(' '), vars).split(' ');
151
+ }
152
+ }
153
+
154
+ this.depth--;
155
+ return words.join(' ');
156
+ }
157
+ }
@@ -0,0 +1,60 @@
1
+ 'kiwi public';
2
+
3
+ /** @module */
4
+
5
+ /**
6
+ * Plays alert sounds
7
+ */
8
+ export class AudioManager {
9
+ constructor(audio) {
10
+ this.lastPlayed = 0;
11
+ this.audio = audio;
12
+ }
13
+
14
+ /** Play the alert sound */
15
+ play() {
16
+ // Only play the bleep once every 2 seconds
17
+ if (!this.lastPlayed || Date.now() - this.lastPlayed > 2000) {
18
+ this.audio.play();
19
+ this.lastPlayed = Date.now();
20
+ }
21
+ }
22
+
23
+ listen(state) {
24
+ state.$on('audio.bleep', () => {
25
+ this.play();
26
+ });
27
+ }
28
+
29
+ /** Watch the Kiwi state for any message highlights and play an alert */
30
+ watchForMessages(state) {
31
+ state.$on('message.new', (event) => {
32
+ let { message, buffer } = event;
33
+ if (buffer.setting('mute_sound')) {
34
+ return;
35
+ }
36
+
37
+ let ignoreTypes = [
38
+ 'connection',
39
+ 'traffic',
40
+ 'mode',
41
+ 'nick',
42
+ ];
43
+ if (ignoreTypes.indexOf(message.type) > -1) {
44
+ return;
45
+ }
46
+
47
+ if (message.ignore || buffer.isSpecial()) {
48
+ return;
49
+ }
50
+
51
+ let shouldBleep = buffer.getNetwork().nick !== message.nick && ((message.isHighlight && buffer.setting('alert_on') === 'highlight') || buffer.setting('alert_on') === 'message');
52
+ let isActiveBuffer = state.getActiveBuffer() === buffer;
53
+ let inFocus = isActiveBuffer && state.ui.app_has_focus;
54
+
55
+ if (shouldBleep || (buffer.isQuery() && !inFocus)) {
56
+ this.play();
57
+ }
58
+ });
59
+ }
60
+ }
@@ -0,0 +1,247 @@
1
+ 'kiwi public';
2
+
3
+ /** @module */
4
+
5
+ import { MessageTags } from 'irc-framework';
6
+ import * as Misc from '@/helpers/Misc';
7
+
8
+ /**
9
+ * Adds the BOUNCER IRCv3 spec to irc-framework
10
+ */
11
+ export default function bouncerMiddleware() {
12
+ let networks = [];
13
+ let buffers = {};
14
+
15
+ return function middleware(client, rawEvents, parsedEvents) {
16
+ client.requestCap('bouncer');
17
+ addFunctionsToClient(client);
18
+ rawEvents.use(theMiddleware);
19
+ };
20
+
21
+ function theMiddleware(command, message, rawLine, client, next) {
22
+ if (command !== 'BOUNCER') {
23
+ next();
24
+ return;
25
+ }
26
+
27
+ let params = message.params;
28
+
29
+ if (params[0] === 'listnetworks' && ['end', 'RPL_OK'].indexOf(params[1]) > -1) {
30
+ client.command_handler.emit('bouncer networks', networks);
31
+ networks = [];
32
+ } else if (params[0] === 'listnetworks') {
33
+ let tags = MessageTags.decode(params[2]);
34
+ networks.push({
35
+ networkId: params[1],
36
+ name: tags.network,
37
+ host: tags.host,
38
+ port: parseInt(tags.port, 10),
39
+ tls: tags.tls === '1',
40
+ connected: tags.state === 'connected',
41
+ nick: tags.nick,
42
+ currentNick: tags.currentNick,
43
+ password: tags.password || '',
44
+ account: tags.account || '',
45
+ account_password: tags.account_password || '',
46
+ });
47
+ } else if (params[0] === 'listbuffers' && ['end', 'RPL_OK'].indexOf(params[2]) > -1) {
48
+ let netId = (params[1] || '');
49
+ let detectedBuffers = buffers[netId] || [];
50
+ delete buffers[netId];
51
+
52
+ client.command_handler.emit('bouncer buffers', detectedBuffers);
53
+ client.command_handler.emit('bouncer buffers ' + netId, detectedBuffers);
54
+ } else if (params[0] === 'listbuffers') {
55
+ let netId = (params[1] || '');
56
+ let tags = MessageTags.decode(params[2]);
57
+ buffers[netId] = buffers[netId] || [];
58
+ buffers[netId].push({
59
+ networkId: netId,
60
+ network: tags.network,
61
+ name: tags.buffer,
62
+ topic: tags.topic,
63
+ joined: tags.joined === '1',
64
+ seen: tags.seen,
65
+ notify: tags.notify || 'highlight',
66
+ });
67
+ } else if (params[0] === 'state') {
68
+ client.command_handler.emit('bouncer state', {
69
+ networkId: params[1],
70
+ network: params[2],
71
+ state: params[3],
72
+ });
73
+ }
74
+
75
+ // BOUNCER addnetwork NetID Network1 ERR_NAMEINUSE
76
+ if (params[0] === 'addnetwork' && params[3].substr(0, 4) === 'ERR_') {
77
+ let netName = (params[2] || '').toLowerCase();
78
+ let eventObj = {
79
+ error: params[3],
80
+ reason: params[4] || '',
81
+ };
82
+ client.command_handler.emit('bouncer addnetwork error', eventObj);
83
+ client.command_handler.emit('bouncer addnetwork error ' + netName, eventObj);
84
+ } else if (params[0] === 'addnetwork' && ['end', 'RPL_OK'].indexOf(params[3]) > -1) {
85
+ // BOUNCER addnetwork 5 Network1 RPL_OK
86
+ let netId = (params[1] || '');
87
+ let netName = (params[2] || '').toLowerCase();
88
+ let eventObj = {
89
+ networkId: netId,
90
+ network: netName,
91
+ };
92
+ client.command_handler.emit('bouncer addnetwork ok', eventObj);
93
+ client.command_handler.emit('bouncer addnetwork ok ' + netName, eventObj);
94
+ }
95
+ }
96
+ }
97
+
98
+ function addFunctionsToClient(client) {
99
+ let bnc = client.bnc = {};
100
+
101
+ bnc.tags = function tags() {
102
+ let token = client.network.supports('bouncer');
103
+ return !token || typeof token !== 'string' ?
104
+ {} :
105
+ MessageTags.decode(token) || {};
106
+ };
107
+
108
+ bnc.hasNetwork = function hasNetwork() {
109
+ let token = client.network.supports('bouncer');
110
+ if (!token || token === true) {
111
+ return false;
112
+ }
113
+
114
+ let tags = MessageTags.decode(token);
115
+ return tags && !!tags.network;
116
+ };
117
+
118
+ bnc.getNetworks = function getNetworks() {
119
+ return new Promise((resolve, reject) => {
120
+ client.raw('BOUNCER listnetworks');
121
+ client.once('bouncer networks', (networks) => {
122
+ resolve(networks);
123
+ });
124
+ });
125
+ };
126
+
127
+ bnc.getBuffers = function getBuffers(netId) {
128
+ return new Promise((resolve, reject) => {
129
+ client.raw('BOUNCER listbuffers ' + netId);
130
+ client.once('bouncer buffers ' + netId, (buffers) => {
131
+ resolve(buffers);
132
+ });
133
+ });
134
+ };
135
+
136
+ bnc.closeBuffer = function closeBuffer(netId, bufferName) {
137
+ return new Promise((resolve, reject) => {
138
+ client.raw(`BOUNCER delbuffer ${netId} ${bufferName}`);
139
+ });
140
+ };
141
+
142
+ bnc.bufferSeen = function bufferSeen(netId, bufferName, seenTime) {
143
+ return new Promise((resolve, reject) => {
144
+ // 1 tells the bouncer to use the current time
145
+ let timeStr = seenTime ? Misc.dateIso(seenTime) : '1';
146
+ client.raw(`BOUNCER changebuffer ${netId} ${bufferName} seen=${timeStr}`);
147
+ });
148
+ };
149
+
150
+ bnc.addNetwork = function addNetwork(netName, host, port, tls, nick, user, password) {
151
+ let tags = {};
152
+ tags.network = netName;
153
+ tags.host = host;
154
+ tags.port = port;
155
+ tags.tls = tls ? 1 : 0;
156
+ tags.nick = nick;
157
+ tags.password = password;
158
+
159
+ if (user) {
160
+ tags.user = user;
161
+ }
162
+
163
+ let tagString = createTagString(tags);
164
+ return new Promise((resolve, reject) => {
165
+ client.raw('BOUNCER addnetwork ' + tagString);
166
+ client.once('bouncer addnetwork ok ' + netName.toLowerCase(), onOk);
167
+ client.once('bouncer addnetwork error', onError);
168
+
169
+ function onOk(event) {
170
+ client.off('bouncer addnetwork error', onError);
171
+ resolve(event);
172
+ }
173
+ function onError(event) {
174
+ client.off('bouncer addnetwork ok ' + netName.toLowerCase(), onOk);
175
+ reject({
176
+ error: event.error,
177
+ reason: event.reason,
178
+ });
179
+ }
180
+ });
181
+ };
182
+
183
+ bnc.removeNetwork = function removeNetwork(netId, bufferName) {
184
+ return new Promise((resolve, reject) => {
185
+ client.raw(`BOUNCER delnetwork ${netId}`);
186
+ });
187
+ };
188
+
189
+ bnc.saveNetwork = function saveNetwork(netId, opts) {
190
+ let tags = {};
191
+
192
+ if (typeof opts.network !== 'undefined') {
193
+ tags.network = opts.network;
194
+ }
195
+ if (typeof opts.host !== 'undefined') {
196
+ tags.host = opts.host;
197
+ }
198
+ if (typeof opts.port !== 'undefined') {
199
+ tags.port = opts.port;
200
+ }
201
+ if (typeof opts.tls !== 'undefined') {
202
+ tags.tls = opts.tls ? 1 : 0;
203
+ }
204
+ if (typeof opts.nick !== 'undefined') {
205
+ tags.nick = opts.nick;
206
+ }
207
+ if (typeof opts.user !== 'undefined') {
208
+ tags.user = opts.user;
209
+ }
210
+ if (typeof opts.password !== 'undefined') {
211
+ tags.password = opts.password;
212
+ }
213
+ if (typeof opts.account_password !== 'undefined') {
214
+ tags.account_password = opts.account_password;
215
+ }
216
+ if (typeof opts.account !== 'undefined') {
217
+ tags.account = opts.account;
218
+ }
219
+
220
+ let tagString = createTagString(tags);
221
+ return new Promise((resolve, reject) => {
222
+ if (tagString.length === 0) {
223
+ resolve();
224
+ } else {
225
+ client.raw(`BOUNCER changenetwork ${netId} ${tagString}`);
226
+ }
227
+ });
228
+ };
229
+ }
230
+
231
+ function createTagString(tags) {
232
+ let tagParts = [];
233
+
234
+ Object.keys(tags).forEach((tag) => {
235
+ let val = tags[tag];
236
+ if (typeof val !== 'undefined') {
237
+ val = val.toString()
238
+ .replace(' ', '\\s')
239
+ .replace(';', '\\:');
240
+ tagParts.push(tag + '=' + val);
241
+ } else {
242
+ tagParts.push(tag);
243
+ }
244
+ });
245
+
246
+ return tagParts.join(';');
247
+ }