diff --git a/.gitignore b/.gitignore
index b5aee5f..f713805 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
/node_modules/
-/dist/
-/lib/
+/app/
/client.config.toml
/webirc.data.json
diff --git a/README.md b/README.md
index 5950e37..f8c7acc 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ This application requires [node.js](https://nodejs.org/) to be installed.
1. Install the dependencies `npm install`
2. Copy the configuration `cp client.config.example.toml client.config.toml`
3. Build the project using `npm run build`
-4. Run the server `./teemant.js`
+4. Run the server `npm start`
The client will be accessible at http://localhost:9000/
diff --git a/index.js b/index.js
new file mode 100755
index 0000000..59db561
--- /dev/null
+++ b/index.js
@@ -0,0 +1,8 @@
+#!/usr/bin/env node
+const path = require('path')
+
+try {
+ require(path.join(__dirname, 'app'))
+} catch (e) {
+ console.error('Please build the application before running.')
+}
diff --git a/package-lock.json b/package-lock.json
index 8eb7c35..37177c3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1055,6 +1055,12 @@
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true
},
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
"ansi-align": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
@@ -1149,6 +1155,21 @@
"es-abstract": "^1.7.0"
}
},
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
@@ -1910,12 +1931,29 @@
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
"dev": true
},
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
"dev": true
},
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
"collection-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -1986,6 +2024,76 @@
"typedarray": "^0.0.6"
}
},
+ "concurrently": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-4.1.0.tgz",
+ "integrity": "sha512-pwzXCE7qtOB346LyO9eFWpkFJVO3JQZ/qU/feGeaAHiX1M3Rw3zgXKc5cZ8vSH5DGygkjzLFDzA/pwoQDkRNGg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "date-fns": "^1.23.0",
+ "lodash": "^4.17.10",
+ "read-pkg": "^4.0.1",
+ "rxjs": "^6.3.3",
+ "spawn-command": "^0.0.2-1",
+ "supports-color": "^4.5.0",
+ "tree-kill": "^1.1.0",
+ "yargs": "^12.0.1"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
+ "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
+ "dev": true,
+ "requires": {
+ "normalize-package-data": "^2.3.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "^2.0.0"
+ }
+ }
+ }
+ },
"configstore": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
@@ -2070,6 +2178,127 @@
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
"dev": true
},
+ "copy-webpack-plugin": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
+ "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.0",
+ "loader-utils": "^1.1.0",
+ "minimatch": "^3.0.4",
+ "p-limit": "^1.0.0",
+ "serialize-javascript": "^1.4.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -2215,6 +2444,12 @@
}
}
},
+ "css-parse": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
+ "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
+ "dev": true
+ },
"css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
@@ -2308,6 +2543,12 @@
"es5-ext": "^0.10.9"
}
},
+ "date-fns": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+ "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+ "dev": true
+ },
"date-now": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
@@ -2491,6 +2732,32 @@
"randombytes": "^2.0.0"
}
},
+ "dir-glob": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.0.tgz",
+ "integrity": "sha512-YqrO+bduKFqPgspvpjDAaKk0qhmvY+SY7NjIRljCDAy6CX7Ft65irIduHbrYXhy+BxJnYKjWuREw6X42w9/+DQ==",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
"doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -4098,6 +4365,12 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
@@ -4166,6 +4439,40 @@
"integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==",
"dev": true
},
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ }
+ }
+ },
"got": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
@@ -4609,6 +4916,12 @@
"loose-envify": "^1.0.0"
}
},
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
"ipaddr.js": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
@@ -4993,6 +5306,15 @@
"package-json": "^4.0.0"
}
},
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@@ -5161,6 +5483,15 @@
}
}
},
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -5204,6 +5535,17 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
+ "mem": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz",
+ "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^1.0.0",
+ "p-is-promise": "^1.1.0"
+ }
+ },
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -5659,6 +6001,12 @@
"boolbase": "~1.0.0"
}
},
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
"object-assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
@@ -5828,6 +6176,43 @@
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
"dev": true
},
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ },
+ "dependencies": {
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ }
+ }
+ },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
@@ -5845,12 +6230,24 @@
"mkdirp": "^0.5.1"
}
},
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
+ "p-is-promise": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=",
+ "dev": true
+ },
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
@@ -6667,6 +7064,18 @@
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
"dev": true
},
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
"require-uncached": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
@@ -6802,6 +7211,12 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
+ "dev": true
+ },
"schema-utils": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
@@ -6812,6 +7227,11 @@
"ajv-keywords": "^3.1.0"
}
},
+ "seedrandom": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz",
+ "integrity": "sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA=="
+ },
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
@@ -6864,6 +7284,12 @@
"send": "0.16.2"
}
},
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
"set-value": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
@@ -7184,6 +7610,12 @@
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
"dev": true
},
+ "spawn-command": {
+ "version": "0.0.2-1",
+ "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
+ "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=",
+ "dev": true
+ },
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -7402,6 +7834,45 @@
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
},
+ "stylus": {
+ "version": "0.54.5",
+ "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
+ "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
+ "dev": true,
+ "requires": {
+ "css-parse": "1.7.x",
+ "debug": "*",
+ "glob": "7.0.x",
+ "mkdirp": "0.5.x",
+ "sax": "0.5.x",
+ "source-map": "0.1.x"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "dev": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
"stylus-loader": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
@@ -7639,6 +8110,12 @@
"integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
"dev": true
},
+ "tree-kill": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz",
+ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==",
+ "dev": true
+ },
"trim-newlines": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
@@ -8171,6 +8648,12 @@
"isexe": "^2.0.0"
}
},
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
"widest-line": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
@@ -8195,6 +8678,47 @@
"errno": "~0.1.7"
}
},
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -8264,6 +8788,93 @@
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true
},
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ },
+ "dependencies": {
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz",
+ "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
"yargs-parser": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
diff --git a/package.json b/package.json
index f770d7f..2af7f85 100644
--- a/package.json
+++ b/package.json
@@ -2,9 +2,19 @@
"name": "teemantirc",
"version": "2.0.0",
"description": "Web-based IRC client",
- "main": "teemant.js",
+ "main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "css": "mkdir -p app/public/style && stylus -o app/public/style src/style/*.styl",
+ "css:watch": "mkdir -p app/public/style && stylus -w -o app/public/style src/style/*.styl",
+ "js": "webpack -p --config webpack.config.js",
+ "js:watch": "webpack -w --mode=development --config webpack.config.js",
+ "app": "babel src/server -d app",
+ "app:watch": "babel src/server -d app -w",
+ "build": "npm run app && npm run js && npm run css",
+ "watch": "concurrently --kill-others \"npm run app:watch\" \"npm run css:watch\" \"npm run js:watch\"",
+ "clean": "rm -rf app",
+ "start": "node index.js"
},
"keywords": [
"irc"
@@ -13,6 +23,7 @@
"license": "MIT",
"dependencies": {
"express": "^4.16.4",
+ "seedrandom": "^2.4.4",
"socket.io": "^2.2.0",
"toml": "^2.3.5"
},
@@ -25,11 +36,14 @@
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.2.3",
"babel-loader": "^8.0.5",
+ "concurrently": "^4.1.0",
+ "copy-webpack-plugin": "^4.6.0",
"css-loader": "^2.1.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"standard": "^12.0.1",
+ "stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"webpack": "^4.28.1",
"webpack-command": "^0.4.2"
diff --git a/src/document/index.html b/src/document/index.html
index 66a20f0..3a3a73d 100644
--- a/src/document/index.html
+++ b/src/document/index.html
@@ -6,11 +6,10 @@
TeemantIRC
-
-
+
-
+
diff --git a/src/js/colorparser.js b/src/js/colorparser.js
index f2c9706..bc28933 100644
--- a/src/js/colorparser.js
+++ b/src/js/colorparser.js
@@ -1,83 +1,90 @@
+/* eslint-disable no-useless-escape, no-control-regex */
+
// Shamelessly copied from https://github.com/megawac/irc-style-parser/
// Lol, I just gave credit, didn't I..
// Dammit, well, there's that.
-const styleCheck_Re = /[\x00-\x1F]/;
-const back_re = /^(\d{1,2})(,(\d{1,2}))?/;
-const colourKey = '\x03';
-const colour_re = /\x03/g;
-const styleBreak = '\x0F'; // breaks all open styles ^O (\x0F)
+import { el } from './utility'
+
+const styleCheckRe = /[\x00-\x1F]/
+const backRe = /^(\d{1,2})(,(\d{1,2}))?/
+const colourKey = '\x03'
+const colourRe = /\x03/g
+const styleBreak = '\x0F' // breaks all open styles ^O (\x0F)
let styles = [
- ['normal', '\x00', ''], ['underline', '\x1F'],
- ['bold', '\x02'], ['italic', '\x1D']
-].map(function(style) {
- var escaped = encodeURI(style[1]).replace('%', '\\x');
- return {
- name: style[0],
- style: style[2] != null ? style[2] : 'irc-' + style[0],
- key: style[1],
- keyregex: new RegExp(escaped + '(.*?)(' + escaped + '|$)')
- };
-});
+ ['normal', '\x00', ''], ['underline', '\x1F'],
+ ['bold', '\x02'], ['italic', '\x1D']
+].map(function (style) {
+ var escaped = encodeURI(style[1]).replace('%', '\\x')
+ return {
+ name: style[0],
+ style: style[2] != null ? style[2] : 'irc-' + style[0],
+ key: style[1],
+ keyregex: new RegExp(escaped + '(.*?)(' + escaped + '|$)')
+ }
+})
-//http://www.mirc.com/colors.html
+// http://www.mirc.com/colors.html
let colors = [
- 'white', 'black', 'navy', 'green', 'red', 'brown',
- 'purple', 'olive', 'yellow', 'lightgreen', 'teal',
- 'cyan', 'blue', 'pink', 'gray', 'lightgrey'
-].reduce(function(memo, name, index) {
- memo[index] = {
- name: name,
- fore: 'irc-fg' + index,
- back: 'irc-bg' + index,
- key: index
- };
- return memo;
-}, {});
+ 'white', 'black', 'navy', 'green', 'red', 'brown',
+ 'purple', 'olive', 'yellow', 'lightgreen', 'teal',
+ 'cyan', 'blue', 'pink', 'gray', 'lightgrey'
+].reduce(function (memo, name, index) {
+ memo[index] = {
+ name: name,
+ fore: 'irc-fg' + index,
+ back: 'irc-bg' + index,
+ key: index
+ }
+ return memo
+}, {})
-function stylize(line) {
- // Recheck
- if (!styleCheck_Re.test(line)) return line;
+function stylize (line) {
+ // Recheck
+ if (!styleCheckRe.test(line)) return line
- // split up by the irc style break character ^O
- if (line.indexOf(styleBreak) >= 0) {
- return line.split(styleBreak).map(stylize).join('');
- }
+ // split up by the irc style break character ^O
+ if (line.indexOf(styleBreak) >= 0) {
+ return line.split(styleBreak).map(stylize).join('')
+ }
- var result = line;
- var parseArr = result.split(colourKey);
- var text, match, colour, background = '';
- for (var i = 0; i < parseArr.length; i++) {
- text = parseArr[i];
- match = text.match(back_re);
- colour = match && colors[+match[1]];
- if (!match || !colour) {
- // ^C (no colour) ending. Escape current colour and carry on
- background = '';
- continue;
- }
- // set the background colour
- // we don't overide the background local var to support nesting
- if (colors[+match[3]]) {
- background = ' ' + colors[+match[3]].back;
- }
- // update the parsed text result
- result = result.replace(colourKey + text,
- '{1}'.format(colour.fore + background, text.slice(match[0].length)));
- }
+ let result = line
+ let parseArr = result.split(colourKey)
- // Matching styles (italics/bold/underline)
- // if only colors were this easy...
- styles.forEach(function(style) {
- if (result.indexOf(style.key) < 0) return;
- result = result.replace(style.keyregex, function(match, text) {
- return '{1}'.format(style.style, text);
- });
- });
+ let text
+ let match
+ let colour
+ let background = ''
+ for (let i = 0; i < parseArr.length; i++) {
+ text = parseArr[i]
+ match = text.match(backRe)
+ colour = match && colors[+match[1]]
+ if (!match || !colour) {
+ // ^C (no colour) ending. Escape current colour and carry on
+ background = ''
+ continue
+ }
+ // set the background colour
+ // we don't overide the background local var to support nesting
+ if (colors[+match[3]]) {
+ background = ' ' + colors[+match[3]].back
+ }
+ // update the parsed text result
+ result = result.replace(colourKey + text, el('span', text.slice(match[0].length), [colour.fore + background]))
+ }
- //replace the reminent colour terminations and be done with it
- return result.replace(colour_re, '');
+ // Matching styles (italics/bold/underline)
+ // if only colors were this easy...
+ styles.forEach(function (style) {
+ if (result.indexOf(style.key) < 0) return
+ result = result.replace(style.keyregex, function (match, text) {
+ return el('span', text, [style.style])
+ })
+ })
+
+ // replace the reminent colour terminations and be done with it
+ return result.replace(colourRe, '')
}
-module.exports = stylize;
+export default stylize
diff --git a/src/js/main.js b/src/js/main.js
index e52dee2..6ce33f7 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -1,2230 +1,2243 @@
-const themes = require('./theme.js');
+/* global irc, twemoji, io */
+/* eslint-disable no-useless-escape, no-control-regex */
+import { el, span, sf, formatDate, removeStr, match, serialize, objectGetKey, rand, addClass, removeClass, toggleClass } from './utility'
+import stylize from './colorparser'
+import seedrandom from 'seedrandom'
+
+const themes = require('./theme.js')
window.irc = {
- socketUp: false,
- primaryFrame: null,
- config: {
- colors: true,
- channelify: true,
- sharedInput: false,
- timestamps: true,
- timestampFormat: 'HH:mm:ss',
- colorNicknames: true,
- colorNicklist: false,
- scrollOnResize: true,
- scrollOnFocus: true,
- emoji: true,
- theme: 'default'
- },
- serverData: {},
- serverChatQueue: {},
- chatType: 'simple',
- documentTitle: 'TeemantIRC',
-};
+ socketUp: false,
+ primaryFrame: null,
+ config: {
+ colors: true,
+ channelify: true,
+ sharedInput: false,
+ timestamps: true,
+ timestampFormat: 'HH:mm:ss',
+ colorNicknames: true,
+ colorNicklist: false,
+ scrollOnResize: true,
+ scrollOnFocus: true,
+ emoji: true,
+ theme: 'default'
+ },
+ serverData: {},
+ serverChatQueue: {},
+ chatType: 'simple',
+ documentTitle: 'TeemantIRC'
+}
-const clientdom = {connector: {}, settings: {}};
+const clientdom = { connector: {}, settings: {} }
const colorizer = {
- get_random_color: function(nickname) {
- let themefunc = themes.available[irc.config.theme].nick_pallete;
+ get_random_color: function (nickname) {
+ let themefunc = themes.available[irc.config.theme].nick_pallete
- Math.seedrandom(nickname);
- let h = rand(themefunc.H[0], themefunc.H[1]);
- let s = rand(themefunc.S[0], themefunc.S[1]);
- let l = rand(themefunc.L[0], themefunc.L[1]);
- return 'hsl(' + h + ',' + s + '%,' + l + '%)';
- },
- strip: function(message) {
- return message.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, '');
- },
- stylize: require('./colorparser.js')
-};
+ let randgen = seedrandom(nickname)
+ let h = rand(randgen, themefunc.H[0], themefunc.H[1])
+ let s = rand(randgen, themefunc.S[0], themefunc.S[1])
+ let l = rand(randgen, themefunc.L[0], themefunc.L[1])
+ return 'hsl(' + h + ',' + s + '%,' + l + '%)'
+ },
+ strip: function (message) {
+ return message.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, '')
+ },
+ stylize: stylize
+}
-/*********************\
-|** **|
-|** UTILITIES **|
-|** **|
-\*********************/
+// Utilities
-const validators = {};
+const validators = {}
-validators.iporhost = function(str) {
- let valid = false;
+validators.iporhost = function (str) {
+ let valid = false
- if(str.match(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i)) {
- valid = true;
- } else if (str.match(/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i)) {
- valid = true;
- }
+ if (str.match(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i)) {
+ valid = true
+ } else if (str.match(/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i)) {
+ valid = true
+ }
- return valid;
-};
+ return valid
+}
-validators.nickname = function(str) {
- if(str.match(/[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]*/i)) {
- return true;
- }
- return false;
-};
+validators.nickname = function (str) {
+ if (str.match(/[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]*/i)) {
+ return true
+ }
+ return false
+}
-validators.escapeHTML = function(str) {
- return str.replace(/\/, '>');
-};
-
-Date.prototype.format = function (format, utc){
- var date = this;
- var MMMM = ['\x00', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
- var MMM = ['\x01', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
- var dddd = ['\x02', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
- var ddd = ['\x03', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
- function ii(i, len) { var s = i + ''; len = len || 2; while (s.length < len) s = '0' + s; return s; }
-
- var y = utc ? date.getUTCFullYear() : date.getFullYear();
- format = format.replace(/(^|[^\\])yyyy+/g, '$1' + y);
- format = format.replace(/(^|[^\\])yy/g, '$1' + y.toString().substr(2, 2));
- format = format.replace(/(^|[^\\])y/g, '$1' + y);
-
- var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
- format = format.replace(/(^|[^\\])MMMM+/g, '$1' + MMMM[0]);
- format = format.replace(/(^|[^\\])MMM/g, '$1' + MMM[0]);
- format = format.replace(/(^|[^\\])MM/g, '$1' + ii(M));
- format = format.replace(/(^|[^\\])M/g, '$1' + M);
-
- var d = utc ? date.getUTCDate() : date.getDate();
- format = format.replace(/(^|[^\\])dddd+/g, '$1' + dddd[0]);
- format = format.replace(/(^|[^\\])ddd/g, '$1' + ddd[0]);
- format = format.replace(/(^|[^\\])dd/g, '$1' + ii(d));
- format = format.replace(/(^|[^\\])d/g, '$1' + d);
-
- var H = utc ? date.getUTCHours() : date.getHours();
- format = format.replace(/(^|[^\\])HH+/g, '$1' + ii(H));
- format = format.replace(/(^|[^\\])H/g, '$1' + H);
-
- var h = H > 12 ? H - 12 : H == 0 ? 12 : H;
- format = format.replace(/(^|[^\\])hh+/g, '$1' + ii(h));
- format = format.replace(/(^|[^\\])h/g, '$1' + h);
-
- var m = utc ? date.getUTCMinutes() : date.getMinutes();
- format = format.replace(/(^|[^\\])mm+/g, '$1' + ii(m));
- format = format.replace(/(^|[^\\])m/g, '$1' + m);
-
- var s = utc ? date.getUTCSeconds() : date.getSeconds();
- format = format.replace(/(^|[^\\])ss+/g, '$1' + ii(s));
- format = format.replace(/(^|[^\\])s/g, '$1' + s);
-
- var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds();
- format = format.replace(/(^|[^\\])fff+/g, '$1' + ii(f, 3));
- f = Math.round(f / 10);
- format = format.replace(/(^|[^\\])ff/g, '$1' + ii(f));
- f = Math.round(f / 10);
- format = format.replace(/(^|[^\\])f/g, '$1' + f);
-
- var T = H < 12 ? 'AM' : 'PM';
- format = format.replace(/(^|[^\\])TT+/g, '$1' + T);
- format = format.replace(/(^|[^\\])T/g, '$1' + T.charAt(0));
-
- var t = T.toLowerCase();
- format = format.replace(/(^|[^\\])tt+/g, '$1' + t);
- format = format.replace(/(^|[^\\])t/g, '$1' + t.charAt(0));
-
- var tz = -date.getTimezoneOffset();
- var K = utc || !tz ? 'Z' : tz > 0 ? '+' : '-';
- if (!utc)
- {
- tz = Math.abs(tz);
- var tzHrs = Math.floor(tz / 60);
- var tzMin = tz % 60;
- K += ii(tzHrs) + ':' + ii(tzMin);
- }
- format = format.replace(/(^|[^\\])K/g, '$1' + K);
-
- var day = (utc ? date.getUTCDay() : date.getDay()) + 1;
- format = format.replace(new RegExp(dddd[0], 'g'), dddd[day]);
- format = format.replace(new RegExp(ddd[0], 'g'), ddd[day]);
-
- format = format.replace(new RegExp(MMMM[0], 'g'), MMMM[M]);
- format = format.replace(new RegExp(MMM[0], 'g'), MMM[M]);
-
- format = format.replace(/\\(.)/g, '$1');
-
- return format;
-};
+validators.escapeHTML = function (str) {
+ return str.replace(//, '>')
+}
const processors = {
- inline_color: function (text) {
- // TODO: Figure out how to make hex colors behave
- //const hexRegex = /(^|[^&])(\#[0-9a-f]{6};?)(?!\w)/gmi;
- const rgbRegex = /(.?)(rgba?\((?:\s*\d+\s*,){2}\s*\d+\s*(?:,\s*[\d.]+\s*)?\);?)/gmi;
- const substitute = '$1$2 ';
- //text = text.replace(hexRegex, substitute);
- text = text.replace(rgbRegex, substitute);
- return text;
- },
- linkify(text) {
- const re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:''.,<>?«»“”‘’]))/gi;
- return text.replace(re, function(url) {
- let href = url;
- if (url.indexOf('http') !== 0) {
- href = 'http://' + url;
- }
- return '' + url + '';
- });
- },
- channelify(text) {
- if(!irc.config.channelify) return text;
+ inline_color: function (text) {
+ // TODO: Figure out how to make hex colors behave
+ // const hexRegex = /(^|[^&])(\#[0-9a-f]{6};?)(?!\w)/gmi
+ const rgbRegex = /(.?)(rgba?\((?:\s*\d+\s*,){2}\s*\d+\s*(?:,\s*[\d.]+\s*)?\);?)/gmi
+ const substitute = '$1$2 '
+ // text = text.replace(hexRegex, substitute)
+ text = text.replace(rgbRegex, substitute)
+ return text
+ },
+ linkify (text) {
+ const re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:''.,<>?«»“”‘’]))/gi
+ return text.replace(re, function (url) {
+ let href = url
+ if (url.indexOf('http') !== 0) {
+ href = 'http://' + url
+ }
+ return '' + url + ''
+ })
+ },
+ channelify (text) {
+ if (!irc.config.channelify) return text
- const channelRegex = /(^|[\s,.:;?!"'()+@-\~%])(#+[^\x00\x07\r\n\s,:]*[a-z][^\x00\x07\r\n\s,:]*)/gmi;
- const substitute = '$1$2';
+ const channelRegex = /(^|[\s,.:;?!"'()+@-\~%])(#+[^\x00\x07\r\n\s,:]*[a-z][^\x00\x07\r\n\s,:]*)/gmi
+ const substitute = '$1$2'
- return text.replace(channelRegex, substitute);
- },
- emojify(text) {
- if (irc.config.emoji === true && window.emojione !== undefined) {
- // Emoji live in the D800-DFFF surrogate plane; only bother passing
- // this range to CPU-expensive unicodeToImage();
- const emojiRegex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
- if (emojiRegex.test(text)) {
- return emojione.unicodeToImage(text);
- } else {
- return text;
- }
- } else {
- return text;
+ return text.replace(channelRegex, substitute)
+ },
+ emojify (text) {
+ if (irc.config.emoji === true && window.twemoji !== undefined) {
+ // Emoji live in the D800-DFFF surrogate plane; only bother passing
+ // this range to CPU-expensive parse()
+ const emojiRegex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g
+ if (emojiRegex.test(text)) {
+ return twemoji.parse(text)
+ } else {
+ return text
+ }
+ } else {
+ return text
+ }
+ }
+}
+
+function whoisMessage (whoisData, buffer) {
+ let messages = []
+ for (let key in whoisData) {
+ switch (key) {
+ case 'hostmask':
+ messages.push(span(whoisData[key], ['hostmask']) + ': ' + validators.escapeHTML(whoisData['realname']))
+ break
+ case 'idleSeconds':
+ let msgs = 'is idle for ' + whoisData[key] + ' seconds'
+ if (whoisData['signonTime']) {
+ msgs += ', signed on at ' + (new Date(parseInt(whoisData['signonTime']) * 1000))
}
- }
-};
+ messages.push(msgs)
+ break
+ case 'loggedIn':
+ case 'registered':
+ case 'connectingFrom':
+ case 'usingModes':
+ case 'title':
+ messages.push(validators.escapeHTML(whoisData[key]))
+ break
+ case 'channels':
+ messages.push(whoisData[key].join(' '))
+ break
+ case 'server':
+ let adfd = sf('is on %s', span(whoisData[key], ['server', 'nick']))
+ if (whoisData['server_name']) {
+ adfd += ' '
+ adfd += span(validators.escapeHTML(whoisData['server_name']), ['hostmask'])
+ }
+ messages.push(adfd)
+ break
+ case 'secure':
+ messages.push('is using a secure connection.')
+ break
+ case 'bot':
+ messages.push('is a bot on ' + irc.serverData[buffer.server].network)
+ break
+ }
+ }
-function whoisMessage(whoisData, buffer) {
- let messages = [];
- for(let key in whoisData) {
- switch(key) {
- case 'hostmask':
- messages.push(''+whoisData[key]+': '+validators.escapeHTML(whoisData['realname']));
- break;
- case 'idleSeconds':
- let msgs = 'is idle for '+whoisData[key]+' seconds';
- if(whoisData['signonTime'])
- msgs += ', signed on at '+new Date(parseInt(whoisData['signonTime'])*1000);
- messages.push(msgs);
- break;
- case 'loggedIn':
- case 'registered':
- case 'connectingFrom':
- case 'usingModes':
- case 'title':
- messages.push(validators.escapeHTML(whoisData[key]));
- break;
- case 'channels':
- messages.push(whoisData[key].join(' '));
- break;
- case 'server':
- let adfd = 'is on '+whoisData[key]+'';
- if(whoisData['server_name'])
- adfd += ' '+validators.escapeHTML(whoisData['server_name'])+'';
- messages.push(adfd);
- break;
- case 'secure':
- messages.push('is using a secure connection.');
- break;
- case 'bot':
- messages.push('is a bot on '+irc.serverData[buffer.server].network);
- break;
- }
- }
-
- for(let i in messages) {
- let mesg = '['+whoisData.nickname+'] '+messages[i];
- buffer.addMessage(mesg, null, 'whois');
- }
+ for (let i in messages) {
+ let mesg = sf('[%s] %s', span(whoisData.nickname, ['nick']), messages[i])
+ buffer.addMessage(mesg, null, 'whois')
+ }
}
-function rand(min, max) {
- return parseInt(Math.random() * (max-min+1), 10) + min;
-}
-
-if (!String.prototype.format) {
- String.prototype.format = function() {
- var args = arguments;
- return this.replace(/{(\d+)}/g, function(match, number) {
- return typeof args[number] != undefined ? args[number] : match;
- });
- };
-}
-
-function remove_str(arr, str) {
- let index = arr.indexOf(str);
-
- if(index > -1) {
- arr.splice(index, 1);
- return arr;
- }
- return arr;
-};
-
-function grep(items, callback) {
- let filtered = [];
- for (let i in items) {
- let item = items[i];
- let cond = callback(item);
- if (cond) {
- filtered.push(item);
- }
- }
-
- return filtered;
-};
-
-function match(word, array) {
- return grep(
- array,
- function(w) {
- return w.toLowerCase().indexOf(word.toLowerCase()) == 0;
- }
- );
-}
-
-function serialize(obj) {
- let str = [];
- for(let p in obj)
- if (obj.hasOwnProperty(p)) {
- str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
- }
- return str.join('&');
-}
-
-function removeClass(element, cl) {
- let classList = element.className.split(' ');
-
- if(classList.indexOf(cl) != -1)
- classList.splice(classList.indexOf(cl), 1);
-
- element.className = classList.join(' ');
-}
-
-function addClass(element, cl) {
- let classList = element.className.split(' ');
-
- if(classList.indexOf(cl) != -1)
- return;
-
- classList.push(cl);
- element.className = classList.join(' ');
-}
-
-function toggleClass(element, cl) {
- let classList = element.className.split(' ');
- if(classList.indexOf(cl) != -1)
- removeClass(element, cl);
- else
- addClass(element, cl);
-}
-
-function objectGetKey(obj, value) {
- let key = null;
- for(let f in obj) {
- if(obj[f] == value)
- key = f;
- }
- return key;
-}
+const asterisk = span('ℹ', ['asterisk'])
+const arrowout = span('⬅', ['arrowout'])
+const arrowin = span('➡', ['arrowin'])
let composer = {
- message: {
- simple: function(time, sender, message, type, server) {
- let element = document.createElement('div');
- element.className = 'message type_simple m_'+type;
+ message: {
+ simple: function (time, sender, message, type, server) {
+ let element = document.createElement('div')
+ element.className = 'message type_simple m_' + type
- if(irc.config.timestamps)
- element.innerHTML += ''+time.format(irc.config.timestampFormat)+' ';
+ if (irc.config.timestamps) {
+ element.innerHTML += span(formatDate(time, irc.config.timestampFormat), ['timestamp'])
+ element.innerHTML += ' '
+ }
- if(irc.config.colors)
- message = colorizer.stylize(message);
- else
- message = colorizer.strip(message);
+ if (irc.config.colors) {
+ message = colorizer.stylize(message)
+ } else {
+ message = colorizer.strip(message)
+ }
- message = processors.inline_color(message);
- message = processors.channelify(message);
- message = processors.linkify(message);
- message = processors.emojify(message);
+ message = processors.inline_color(message)
+ message = processors.channelify(message)
+ message = processors.linkify(message)
+ message = processors.emojify(message)
- switch(type) {
- case 'mode':
- element.innerHTML += 'ℹ '+sender+' ';
- element.innerHTML += ''+message+'';
- break;
- case 'action':
- element.innerHTML += '⚡ '+sender+' ';
- element.innerHTML += ''+message+'';
- break;
- case 'part':
- case 'quit':
- case 'kick':
- element.innerHTML += '⬅ '+sender+'';
- element.innerHTML += ' '+message+'';
- break;
- case 'join':
- element.innerHTML += '➡ '+sender+'';
- element.innerHTML += ' '+message+'';
- break;
- case 'ctcp_response':
- element.innerHTML += 'ℹ CTCP response from '+sender+' ';
- element.innerHTML += ''+message+'';
- break;
- case 'ctcp_request':
- element.innerHTML += 'ℹ CTCP request to '+sender+' ';
- element.innerHTML += ''+message+'';
- break;
- default:
- if(sender) {
- element.innerHTML += ''+sender+' '+message+'';
- } else {
- element.innerHTML += ''+message+'';
- addClass(element, 'no_sender');
- }
- break;
- }
+ switch (type) {
+ case 'mode':
+ element.innerHTML += ' ' + span(sender, ['actionee', 'nick']) + ' '
+ element.innerHTML += span(message, ['content'])
+ break
+ case 'action':
+ element.innerHTML += asterisk + ' ' + span(sender, ['actionee', 'nick']) + ' '
+ element.innerHTML += span(message, ['content'])
+ break
+ case 'part':
+ case 'quit':
+ case 'kick':
+ element.innerHTML += arrowout + ' ' + span(span(sender, ['actionee', 'nick']) + ' ' + message, ['content'])
+ break
+ case 'join':
+ element.innerHTML += arrowin + ' ' + span(span(sender, ['actionee', 'nick']) + ' ' + message, ['content'])
+ break
+ case 'ctcp_response':
+ element.innerHTML += asterisk + ' CTCP response from ' + span(sender, ['actionee', 'nick']) + ' '
+ element.innerHTML += span(message, ['content'])
+ break
+ case 'ctcp_request':
+ element.innerHTML += asterisk + ' CTCP request to ' + span(sender, ['actionee', 'nick']) + ' '
+ element.innerHTML += span(message, ['content'])
+ break
+ default:
+ if (sender) {
+ element.innerHTML += span(sender, ['sender']) + ' ' + span(message, ['content'])
+ } else {
+ element.innerHTML += span(message, ['content', 'no_sender'])
+ }
+ break
+ }
- if(irc.config.colorNicknames == true) {
- if(sender) {
- let sndr1 = element.querySelector('.sender');
- if(sndr1)
- sndr1.style.color = colorizer.get_random_color(sndr1.innerHTML);
- }
+ if (irc.config.colorNicknames === true) {
+ if (sender) {
+ let sndr1 = element.querySelector('.sender')
+ if (sndr1) {
+ sndr1.style.color = colorizer.get_random_color(sndr1.innerHTML)
+ }
+ }
- let sndr2 = element.querySelectorAll('.nick');
- if(sndr2.length > 0)
- for(let a in sndr2)
- if(sndr2[a] && sndr2[a]['style'])
- sndr2[a].style.color = colorizer.get_random_color(sndr2[a].innerHTML);
- }
- return element;
- }
- },
- theme_selection: function(name, theme) {
- let btn = document.createElement('div');
- btn.className = 'theme_button theme_'+theme.type;
- let sampler = document.createElement('div');
- sampler.className = 'sampler';
- sampler.style['background-color'] = theme.colorSamples.background;
- let toolbar = document.createElement('span');
- toolbar.className = 's_toolbar';
- toolbar.style['background-color'] = theme.colorSamples.toolbar;
- let nameb = document.createElement('span');
- nameb.className = 'name';
- nameb.innerHTML = theme['name'];
- sampler.appendChild(toolbar);
- btn.appendChild(sampler);
- btn.appendChild(nameb);
- btn.setAttribute('id', 'theme-'+name);
+ let sndr2 = element.querySelectorAll('.nick')
+ if (sndr2.length > 0) {
+ for (let a in sndr2) {
+ if (sndr2[a] && sndr2[a]['style']) {
+ sndr2[a].style.color = colorizer.get_random_color(sndr2[a].innerHTML)
+ }
+ }
+ }
+ }
+ return element
+ }
+ },
+ themeSelection: function (name, theme) {
+ let btn = document.createElement('div')
+ btn.className = 'theme_button theme_' + theme.type
+ let sampler = document.createElement('div')
+ sampler.className = 'sampler'
+ sampler.style['background-color'] = theme.colorSamples.background
+ let toolbar = document.createElement('span')
+ toolbar.className = 's_toolbar'
+ toolbar.style['background-color'] = theme.colorSamples.toolbar
+ let nameb = document.createElement('span')
+ nameb.className = 'name'
+ nameb.innerHTML = theme['name']
+ sampler.appendChild(toolbar)
+ btn.appendChild(sampler)
+ btn.appendChild(nameb)
+ btn.setAttribute('id', 'theme-' + name)
- return btn;
- },
- embedURL: function(server, port, defaultNick, useSSL, hideServerData, channels) {
- let builder = window.location.origin + '/';
- let params = {};
- let final_channels = [];
+ return btn
+ },
+ embedURL: function (server, port, defaultNick, useSSL, hideServerData, channels) {
+ let builder = window.location.origin + '/'
+ let params = {}
+ let finalChannels = []
- if(server)
- builder += server + '/';
+ if (server) builder += server + '/'
+ if (channels) channels = channels.trim()
+ if (defaultNick) params.nickname = defaultNick
+ if (port && port !== 6667) params.port = port
+ if (useSSL) params.secure = 1
+ if (hideServerData) params.server_data = 0
+ if (Object.keys(params).length > 0) builder += '?' + serialize(params)
- if(channels)
- channels = channels.trim();
+ if (channels) {
+ if (channels.indexOf(',')) {
+ let tmp = channels.split(',')
+ for (let i in tmp) {
+ tmp[i] = tmp[i].trim()
- if(defaultNick)
- params.nickname = defaultNick;
+ if (tmp[i].indexOf('#') !== 0) {
+ tmp[i] = '#' + tmp[i]
+ }
- if(port && port != 6667)
- params.port = port;
+ finalChannels.push(tmp[i])
+ }
+ } else {
+ if (channels.indexOf('#') !== 0) {
+ channels = '#' + channels
+ }
+ finalChannels.push(channels)
+ }
- if(useSSL)
- params.secure = 1;
+ builder += finalChannels.join(',')
+ }
- if(hideServerData)
- params.server_data = 0;
-
- if(Object.keys(params).length > 0)
- builder += '?' + serialize(params);
-
- if(channels) {
- if(channels.indexOf(',')) {
- let tmp = channels.split(',');
- for(let i in tmp) {
- tmp[i] = tmp[i].trim();
-
- if(tmp[i].indexOf('#') != 0)
- tmp[i] = '#'+tmp[i];
-
- final_channels.push(tmp[i]);
- }
- } else {
- if(channels.indexOf('#') != 0)
- channels = '#'+channels;
- final_channels.push(channels);
- }
-
- builder += final_channels.join(',');
- }
-
- return builder;
- }
-};
+ return builder
+ }
+}
// onclick food
window.irc.joinChannel = (channel) => {
- let buf = irc.chat.getActiveChatBuffer();
- if(!buf || !buf.server) return;
+ let buf = irc.chat.getActiveChatBuffer()
+ if (!buf || !buf.server) return
- irc.socket.emit('userinput', {command: 'join', server: buf.server, message: '', arguments: [channel]});
- return false;
-};
+ irc.socket.emit('userinput', { command: 'join', server: buf.server, message: '', arguments: [channel] })
+ return false
+}
-/*****************************\
-|** **|
-|** CLIENT COMMANDS **|
-|** **|
-\*****************************/
+// Client commands
-// commandName: {execute: function(buffer, handler, command, message, listargs) {}, description: ''}
+// commandName: { execute: function (buffer, handler, command, message, listargs) {}, description: ''}
let commands = {
- embed: {execute: function(buffer, handler, command, message, listargs) {
- let data = irc.auther.getDataFromForm();
- let url = 'Couldn\'t compose URL!';
+ embed: {
+ execute: function (buffer, handler, command, message, listargs) {
+ let data = irc.auther.getDataFromForm()
+ let url = 'Couldn\'t compose URL!'
- if(data)
- url = composer.embedURL(data.server, data.port, data.nickname, data.secure, true, data.autojoin.join(','));
+ if (data) {
+ url = composer.embedURL(data.server, data.port, data.nickname, data.secure, true, data.autojoin.join(','))
+ }
- buffer.addMessage(url, null, 'help');
- }, description: '- Embed URL for the current connection'},
+ buffer.addMessage(url, null, 'help')
+ },
+ description: '- Embed URL for the current connection'
+ },
- join: {execute: function(buffer, handler, command, message, listargs) {
- if (!listargs[1]) {
- if(!buffer.alive) {
- irc.socket.emit('userinput', {command: 'join', server: buffer.server, message: '', arguments: [buffer.name]});
- } else {
- handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
- }
- } else {
- irc.socket.emit('userinput', {command: 'join', server: buffer.server, message: '', arguments: [listargs[1]]});
- }
- }, description: ' - Join a channel'},
+ join: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1]) {
+ if (!buffer.alive) {
+ irc.socket.emit('userinput', { command: 'join', server: buffer.server, message: '', arguments: [buffer.name] })
+ } else {
+ handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
+ } else {
+ irc.socket.emit('userinput', { command: 'join', server: buffer.server, message: '', arguments: [listargs[1]] })
+ }
+ },
+ description: ' - Join a channel'
+ },
- part: {execute: function(buffer, handler, command, message, listargs) {
- if (!listargs[1] && buffer.type == 'channel') {
- irc.socket.emit('userinput', {command: 'part', server: buffer.server, message: '', arguments: [buffer.name]});
- } else if(buffer.type != 'channel') {
- handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.');
- } else if(listargs[1]) {
- if(listargs[1].indexOf('#') != -1) {
- let msg = '';
- if(listargs[2])
- msg = listargs.slice(2).join(' ');
- irc.socket.emit('userinput', {command: 'part', server: buffer.server, message: msg, arguments: [listargs[1]]});
- } else {
- if(buffer.type == 'channel') {
- irc.socket.emit('userinput', {command: 'part', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [buffer.name]});
- } else {
- handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.');
- }
- }
- }
- }, description: '[<#channel>|] [message] - Leave the channel. If no channel specified, leave the current buffer.', aliases: ['leave']},
+ part: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1] && buffer.type === 'channel') {
+ irc.socket.emit('userinput', { command: 'part', server: buffer.server, message: '', arguments: [buffer.name] })
+ } else if (buffer.type !== 'channel') {
+ handler.commandError(buffer, listargs[0].toUpperCase() + ': Buffer is not a channel.')
+ } else if (listargs[1]) {
+ if (listargs[1].indexOf('#') !== -1) {
+ let msg = ''
+ if (listargs[2]) {
+ msg = listargs.slice(2).join(' ')
+ }
+ irc.socket.emit('userinput', { command: 'part', server: buffer.server, message: msg, arguments: [listargs[1]] })
+ } else {
+ if (buffer.type === 'channel') {
+ irc.socket.emit('userinput', { command: 'part', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [buffer.name] })
+ } else {
+ handler.commandError(buffer, listargs[0].toUpperCase() + ': Buffer is not a channel.')
+ }
+ }
+ }
+ },
+ description: '[<#channel>|] [message] - Leave the channel. If no channel specified, leave the current buffer.',
+ aliases: ['leave']
+ },
- topic: {execute: function(buffer, handler, command, message, listargs) {
- if (!listargs[1] && buffer.type == 'channel') {
- irc.socket.emit('userinput', {command: 'topic', server: buffer.server, message: '', arguments: [buffer.name]});
- } else if(buffer.type != 'channel') {
- handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.');
- } else if(listargs[1]) {
- if(listargs[1].indexOf('#') != -1) {
- let msg = '';
- if(listargs[2])
- msg = listargs.slice(2).join(' ');
- irc.socket.emit('userinput', {command: 'topic', server: buffer.server, message: msg, arguments: [listargs[1]]});
- } else {
- if(buffer.type == 'channel') {
- irc.socket.emit('userinput', {command: 'topic', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [buffer.name]});
- } else {
- handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.');
- }
- }
- }
- }, description: '[<#channel>|] [topic] - Sets/prints the current topic of the channel.', aliases: ['t']},
+ topic: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1] && buffer.type === 'channel') {
+ irc.socket.emit('userinput', { command: 'topic', server: buffer.server, message: '', arguments: [buffer.name] })
+ } else if (buffer.type !== 'channel') {
+ handler.commandError(buffer, listargs[0].toUpperCase() + ': Buffer is not a channel.')
+ } else if (listargs[1]) {
+ if (listargs[1].indexOf('#') !== -1) {
+ let msg = ''
+ if (listargs[2]) {
+ msg = listargs.slice(2).join(' ')
+ }
+ irc.socket.emit('userinput', { command: 'topic', server: buffer.server, message: msg, arguments: [listargs[1]] })
+ } else {
+ if (buffer.type === 'channel') {
+ irc.socket.emit('userinput', { command: 'topic', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [buffer.name] })
+ } else {
+ handler.commandError(buffer, listargs[0].toUpperCase() + ': Buffer is not a channel.')
+ }
+ }
+ }
+ },
+ description: '[<#channel>|] [topic] - Sets/prints the current topic of the channel.',
+ aliases: ['t']
+ },
- kick: {execute: function(buffer, handler, command, message, listargs) {
- if(buffer.type != 'channel')
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel!');
- if(!listargs[1])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameter !');
- irc.socket.emit('userinput', {command: 'kick', server: buffer.server, message: listargs.slice(2).join(' '), arguments: [buffer.name, listargs[1]]});
- }, description: ' - Kick the following user from the channel.'},
+ kick: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (buffer.type !== 'channel') {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Buffer is not a channel!')
+ }
- quit: {execute: function(buffer, handler, command, message, listargs) {
- irc.socket.emit('userinput', {command: 'quit', server: buffer.server, message: listargs.slice(1).join(' '), arguments: []});
- }, description: '[] - Quit the current server with message.', aliases: ['exit']},
+ if (!listargs[1]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameter !')
+ }
- mode: {execute: function(buffer, handler, command, message, listargs) {
- irc.socket.emit('userinput', {command: 'mode', server: buffer.server, message: listargs.slice(1).join(' '), arguments: []});
- }, description: '[target] [mode] - Set/remove mode of target.'},
+ irc.socket.emit('userinput', {
+ command: 'kick',
+ server: buffer.server,
+ message: listargs.slice(2).join(' '),
+ arguments: [buffer.name, listargs[1]]
+ })
+ },
+ description: ' - Kick the following user from the channel.'
+ },
- msg: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1] || !listargs[2])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
- if(listargs[1] == '*')
- listargs[1] = buffer.name;
- irc.socket.emit('userinput', {command: 'privmsg', server: buffer.server, message: listargs.slice(2).join(' '), arguments: [listargs[1]]});
- }, description: ' - Sends a message to target.', aliases: ['privmsg', 'q', 'query', 'say']},
+ quit: {
+ execute: function (buffer, handler, command, message, listargs) {
+ irc.socket.emit('userinput', { command: 'quit', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [] })
+ },
+ description: '[] - Quit the current server with message.',
+ aliases: ['exit']
+ },
- ctcp: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1] || !listargs[2])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
- if(listargs[1] == '*')
- listargs[1] = buffer.name;
-
- listargs[2] = listargs[2].toUpperCase();
+ mode: {
+ execute: function (buffer, handler, command, message, listargs) {
+ irc.socket.emit('userinput', { command: 'mode', server: buffer.server, message: listargs.slice(1).join(' '), arguments: [] })
+ },
+ description: '[target] [mode] - Set/remove mode of target.'
+ },
- irc.socket.emit('userinput', {command: 'ctcp', server: buffer.server, message: listargs.slice(2).join(' '), arguments: listargs.slice(1)});
- }, description: ' [arguments] - Sends a CTCP request to target.'},
+ msg: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1] || !listargs[2]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
- notice: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1] || !listargs[2])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
- if(listargs[1] == '*')
- listargs[1] = buffer.name;
- irc.socket.emit('userinput', {command: 'notice', server: buffer.server, message: listargs.slice(2).join(' '), arguments: [listargs[1]]});
- }, description: ' - Sends a NOTICE to target.'},
+ if (listargs[1] === '*') {
+ listargs[1] = buffer.name
+ }
- action: {execute: function(buffer, handler, command, message, listargs) {
- irc.socket.emit('userinput', {command: 'privmsg', server: buffer.server, message: '\x01ACTION '+message.substring(command.length+2)+'\x01', arguments: [buffer.name]});
- }, description: ' - act as yourself', aliases: ['me']},
+ irc.socket.emit('userinput', { command: 'privmsg', server: buffer.server, message: listargs.slice(2).join(' '), arguments: [listargs[1]] })
+ },
+ description: ' - Sends a message to target.',
+ aliases: ['privmsg', 'q', 'query', 'say']
+ },
- list: {execute: function(buffer, handler, command, message, listargs) {
- irc.socket.emit('userinput', {command: 'list', server: buffer.server, message: '', arguments: listargs.splice(1)});
- }, description: '- List all channels on the current server.'},
+ ctcp: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1] || !listargs[2]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
- nick: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1]) {
- if(buffer.server != '') {
- let mynick = irc.serverData[buffer.server].my_nick;
- buffer.addMessage('Your nickname is: '+mynick+'', null, 'help');
- }
- return;
- }
- irc.socket.emit('userinput', {command: 'nick', server: buffer.server, message: '', arguments: listargs.splice(1)});
- }, description: '- List all channels on the current server.', aliases: ['nickname']},
+ if (listargs[1] === '*') {
+ listargs[1] = buffer.name
+ }
- names: {execute: function(buffer, handler, command, message, listargs) {
- let channel = '';
- if(!listargs[1]) {
- if(buffer.type == 'channel')
- channel = buffer.name;
- else
- return handler.commandError(buffer, '/'+cmd.toUpperCase()+': Buffer is not a channel!');
- } else if(listargs[1].indexOf('#') == 0) {
- channel = listargs[1];
- } else {
- return handler.commandError(buffer, '/'+cmd.toUpperCase()+': Invalid channel name!');
- }
- irc.socket.emit('userinput', {command: 'names', server: buffer.server, message: '', arguments: [channel]});
- }, description: '- List all users on the current channel.', aliases: ['nicknames']},
+ listargs[2] = listargs[2].toUpperCase()
- quote: {execute: function(buffer, handler, command, message, listargs) {
- irc.socket.emit('userinput', {command: listargs[1], server: buffer.server, message: listargs.slice(2).join(' '), arguments: listargs.splice(2)});
- }, description: ' [args] - Send a raw command to the server.', aliases: ['raw']},
+ irc.socket.emit('userinput', { command: 'ctcp', server: buffer.server, message: listargs.slice(2).join(' '), arguments: listargs.slice(1) })
+ },
+ description: ' [arguments] - Sends a CTCP request to target.'
+ },
- whois: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
+ notice: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1] || !listargs[2]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
- irc.socket.emit('userinput', {command: 'whois', server: buffer.server, message: '', arguments: [listargs[1]]});
- }, description: ' - Display information about a user.'},
+ if (listargs[1] === '*') {
+ listargs[1] = buffer.name
+ }
- connect: {execute: function(buffer, handler, command, message, listargs) {
- clientdom.connector.frame.style.display = 'block';
- irc.auther.authMessage('Create a new connection', false);
- irc.auther.canClose = true;
- }, description: '- Create a new connection.'},
+ irc.socket.emit('userinput', {
+ command: 'notice',
+ server: buffer.server,
+ message: listargs.slice(2).join(' '),
+ arguments: [listargs[1]]
+ })
+ },
+ description: ' - Sends a NOTICE to target.'
+ },
- help: {execute: function(buffer, handler, command, message, listargs) {
- if(!listargs[1])
- return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!');
+ action: {
+ execute: function (buffer, handler, command, message, listargs) {
+ irc.socket.emit('userinput', {
+ command: 'privmsg',
+ server: buffer.server,
+ message: '\x01ACTION ' + message.substring(command.length + 2) + '\x01',
+ arguments: [buffer.name]
+ })
+ },
+ description: ' - act as yourself',
+ aliases: ['me']
+ },
- let cmd = listargs[1].toLowerCase();
- if(cmd.indexOf('/') === 0)
- cmd = cmd.substring(1);
+ list: {
+ execute: function (buffer, handler, command, message, listargs) {
+ irc.socket.emit('userinput', { command: 'list', server: buffer.server, message: '', arguments: listargs.splice(1) })
+ },
+ description: '- List all channels on the current server.'
+ },
- if(cmd in commands) {
- if('description' in commands[cmd])
- buffer.addMessage('/'+cmd.toUpperCase()+' '+
- validators.escapeHTML(commands[cmd].description), null, 'help');
- else
- buffer.addMessage('/'+cmd.toUpperCase()+' - No description provided', null, 'help');
- } else {
- let foundAliased = null;
- for(let cmd2 in commands) {
- if(!commands[cmd2]['aliases']) continue;
- if(commands[cmd2].aliases.indexOf(cmd) != -1) foundAliased = cmd2;
- }
- if(foundAliased) {
- if('description' in commands[foundAliased])
- buffer.addMessage('/'+cmd.toUpperCase()+' '+
- validators.escapeHTML(commands[foundAliased].description), null, 'help');
- else
- buffer.addMessage('/'+cmd.toUpperCase()+' - No description provided', null, 'help');
- } else {
- handler.commandError(buffer, '/'+cmd.toUpperCase()+': Unknown command!');
- }
- }
- }, description: ' - Display help for command'},
+ nick: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1]) {
+ if (buffer.server !== '' && irc.serverData[buffer.server] != null) {
+ let mynick = irc.serverData[buffer.server].my_nick
+ buffer.addMessage('Your nickname is: ' + mynick + '', null, 'help')
+ }
+ return
+ }
+ irc.socket.emit('userinput', { command: 'nick', server: buffer.server, message: '', arguments: listargs.splice(1) })
+ },
+ description: '- List all channels on the current server.',
+ aliases: ['nickname']
+ },
- clear: {execute: function(buffer, handler, command, message, listargs) {
- buffer.clearMessages();
- }, description: '- Clears the current buffer.'}
-};
+ names: {
+ execute: function (buffer, handler, command, message, listargs) {
+ let channel = ''
+ if (!listargs[1]) {
+ if (buffer.type === 'channel') {
+ channel = buffer.name
+ } else {
+ return handler.commandError(buffer, '/' + command.toUpperCase() + ': Buffer is not a channel!')
+ }
+ } else if (listargs[1].indexOf('#') === 0) {
+ channel = listargs[1]
+ } else {
+ return handler.commandError(buffer, '/' + command.toUpperCase() + ': Invalid channel name!')
+ }
+ irc.socket.emit('userinput', { command: 'names', server: buffer.server, message: '', arguments: [channel] })
+ },
+ description: '- List all users on the current channel.',
+ aliases: ['nicknames']
+ },
-/*********************\
-|** **|
-|** CLASSES **|
-|** **|
-\*********************/
+ quote: {
+ execute: function (buffer, handler, command, message, listargs) {
+ irc.socket.emit('userinput', {
+ command: listargs[1],
+ server: buffer.server,
+ message: listargs.slice(2).join(' '),
+ arguments: listargs.splice(2)
+ })
+ },
+ description: ' [args] - Send a raw command to the server.',
+ aliases: ['raw']
+ },
+
+ whois: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
+
+ irc.socket.emit('userinput', { command: 'whois', server: buffer.server, message: '', arguments: [listargs[1]] })
+ },
+ description: ' - Display information about a user.'
+ },
+
+ connect: {
+ execute: function (buffer, handler, command, message, listargs) {
+ clientdom.connector.frame.style.display = 'block'
+ irc.auther.authMessage('Create a new connection', false)
+ irc.auther.canClose = true
+ },
+ description: '- Create a new connection.'
+ },
+
+ help: {
+ execute: function (buffer, handler, command, message, listargs) {
+ if (!listargs[1]) {
+ return handler.commandError(buffer, listargs[0].toUpperCase() + ': Missing parameters!')
+ }
+
+ let cmd = listargs[1].toLowerCase()
+ if (cmd.indexOf('/') === 0) {
+ cmd = cmd.substring(1)
+ }
+
+ if (cmd in commands) {
+ if ('description' in commands[cmd]) {
+ buffer.addMessage(span('/' + cmd.toUpperCase(), ['command']) + ' ' +
+ validators.escapeHTML(commands[cmd].description), null, 'help')
+ } else {
+ buffer.addMessage(span('/' + cmd.toUpperCase(), ['command']) + ' - No description provided', null, 'help')
+ }
+ } else {
+ let foundAliased = null
+ for (let cmd2 in commands) {
+ if (!commands[cmd2]['aliases']) continue
+ if (commands[cmd2].aliases.indexOf(cmd) !== -1) foundAliased = cmd2
+ }
+ if (foundAliased) {
+ if ('description' in commands[foundAliased]) {
+ buffer.addMessage(span('/' + cmd.toUpperCase(), ['command']) + ' ' +
+ validators.escapeHTML(commands[foundAliased].description), null, 'help')
+ } else {
+ buffer.addMessage(span('/' + cmd.toUpperCase(), ['command']) + ' - No description provided', null, 'help')
+ }
+ } else {
+ handler.commandError(buffer, span('/' + cmd.toUpperCase(), ['command']) + ': Unknown command!')
+ }
+ }
+ },
+ description: ' - Display help for command'
+ },
+
+ clear: {
+ execute: function (buffer, handler, command, message, listargs) {
+ buffer.clearMessages()
+ },
+ description: '- Clears the current buffer.'
+ }
+}
+
+// Classes
class Nicklist {
- constructor(buffer) {
- this.buffer = buffer;
- this.nicks = [];
- this.simplifiedNicksList = [];
- }
+ constructor (buffer) {
+ this.buffer = buffer
+ this.nicks = []
+ this.simplifiedNicksList = []
+ }
- sort() {
- let spfx = irc.serverData[this.buffer.server].supportedPrefixes;
- this.nicks.sort(function (a,b) {
- let rex = new RegExp('^['+spfx+']');
- let nicks = [a.prefix.replace(rex,'').toLowerCase(), b.prefix.replace(rex,'').toLowerCase()];
- let prefix = [];
- if (rex.test(a.prefix)) prefix.push(spfx.indexOf(a.prefix[0]));
- else prefix.push(spfx.length+1);
- if (rex.test(b.prefix)) prefix.push(spfx.indexOf(b.prefix[0]));
- else prefix.push(spfx.length+1);
- if (prefix[0] < prefix[1]) return -1;
- if (prefix[0] > prefix[1]) return 1;
- if (nicks[0] > nicks[1]) return 1;
- if (nicks[0] < nicks[1]) return -1;
- return 0;
- });
- return this.nicks;
- }
+ sort () {
+ let spfx = irc.serverData[this.buffer.server].supportedPrefixes
+ this.nicks.sort(function (a, b) {
+ let rex = new RegExp('^[' + spfx + ']')
+ let nicks = [a.prefix.replace(rex, '').toLowerCase(), b.prefix.replace(rex, '').toLowerCase()]
+ let prefix = []
+ if (rex.test(a.prefix)) prefix.push(spfx.indexOf(a.prefix[0]))
+ else prefix.push(spfx.length + 1)
+ if (rex.test(b.prefix)) prefix.push(spfx.indexOf(b.prefix[0]))
+ else prefix.push(spfx.length + 1)
+ if (prefix[0] < prefix[1]) return -1
+ if (prefix[0] > prefix[1]) return 1
+ if (nicks[0] > nicks[1]) return 1
+ if (nicks[0] < nicks[1]) return -1
+ return 0
+ })
+ return this.nicks
+ }
- appendToList(nick) {
- if(!this.buffer.active) return;
+ appendToList (nick) {
+ if (!this.buffer.active) return
- let str = document.createElement('div');
- str.className = 'nick';
- str.setAttribute('id', 'nick-'+nick.nickname);
- let construct = '';
+ let str = document.createElement('div')
+ str.className = 'nick'
+ str.setAttribute('id', 'nick-' + nick.nickname)
+ let construct = ''
- if(nick.prefix != '')
- construct += ''+nick.prefix+'';
- else
- construct += ' ';
+ if (nick.prefix !== '') {
+ construct += span(nick.prefix, ['prefix'])
+ } else {
+ construct += span(' ', ['no-prefix'])
+ }
- if(irc.config.colorNicklist)
- construct += ''+nick.nickname+'';
- else
- construct += ''+nick.nickname+'';
+ if (irc.config.colorNicklist) {
+ construct += '' + nick.nickname + ''
+ } else {
+ construct += span(nick.nickname, ['nickname'])
+ }
- str.innerHTML = construct;
- clientdom.nicklist.appendChild(str);
- }
+ str.innerHTML = construct
+ clientdom.nicklist.appendChild(str)
+ }
- render() {
- if(!this.buffer.active) return;
- clientdom.nicklist.innerHTML = '';
- this.simplifiedNicksList = [];
- this.sort();
+ render () {
+ if (!this.buffer.active) return
+ if (!irc.serverData[this.buffer.server]) return
- for(let n in this.nicks) {
- let nick = this.nicks[n];
- this.simplifiedNicksList.push(nick.nickname);
- this.appendToList(nick);
- }
+ clientdom.nicklist.innerHTML = ''
+ this.simplifiedNicksList = []
+ this.sort()
- irc.chat.input_handler.searchNicknames = this.simplifiedNicksList;
- }
+ for (let n in this.nicks) {
+ let nick = this.nicks[n]
+ this.simplifiedNicksList.push(nick.nickname)
+ this.appendToList(nick)
+ }
- nickAdd(nickname) {
- let newbie = { nickname: nickname, prefix: '', modes: [] };
- if(this.getNickIndex(nickname) != null) return;
- this.nicks.push(newbie);
- this.render();
- }
+ irc.chat.input_handler.searchNicknames = this.simplifiedNicksList
+ }
- nickAddObject(obj) {
- if(this.getNickIndex(obj.nickname) != null) return;
- this.nicks.push(obj);
- }
+ nickAdd (nickname) {
+ let newbie = { nickname: nickname, prefix: '', modes: [] }
+ if (this.getNickIndex(nickname) != null) return
+ this.nicks.push(newbie)
+ this.render()
+ }
- nickRemove(nickname) {
- let nickIndex = this.getNickIndex(nickname);
+ nickAddObject (obj) {
+ if (this.getNickIndex(obj.nickname) != null) return
+ this.nicks.push(obj)
+ }
- if(nickIndex != null)
- this.nicks.splice(nickIndex, 1);
- else
- return;
+ nickRemove (nickname) {
+ let nickIndex = this.getNickIndex(nickname)
- if(!this.buffer.active) return;
- let tt = clientdom.nicklist.querySelector('#nick-'+nickname);
- if(tt) tt.remove();
- remove_str(this.simplifiedNicksList, nickname);
- }
+ if (nickIndex != null) {
+ this.nicks.splice(nickIndex, 1)
+ } else {
+ return
+ }
- nickChange(oldNickname, newNickname) {
- let nickIndex = this.getNickIndex(oldNickname);
+ if (!this.buffer.active) return
+ let tt = clientdom.nicklist.querySelector('#nick-' + nickname)
+ if (tt) tt.remove()
+ removeStr(this.simplifiedNicksList, nickname)
+ }
- if(nickIndex != null)
- this.nicks[nickIndex].nickname = newNickname;
- else
- return;
+ nickChange (oldNickname, newNickname) {
+ let nickIndex = this.getNickIndex(oldNickname)
- this.render();
- }
+ if (nickIndex != null) {
+ this.nicks[nickIndex].nickname = newNickname
+ } else {
+ return
+ }
- getNickIndex(nickname) {
- let result = null;
-
- for(let n in this.nicks)
- if(this.nicks[n].nickname == nickname) result = n;
+ this.render()
+ }
- return result;
- }
+ getNickIndex (nickname) {
+ let result = null
- modeAdded(nickname, newMode) {
- let nickIndex = this.getNickIndex(nickname);
- let nick = null;
+ for (let n in this.nicks) {
+ if (this.nicks[n].nickname === nickname) result = n
+ }
- if(nickIndex != null)
- nick = this.nicks[nickIndex];
- else
- return;
+ return result
+ }
- let modeTranslations = irc.serverData[this.buffer.server].modeTranslation;
- let prefixes = irc.serverData[this.buffer.server].supportedPrefixes;
+ modeAdded (nickname, newMode) {
+ let nickIndex = this.getNickIndex(nickname)
+ let nick = null
- nick.modes.push(newMode);
+ if (nickIndex != null) {
+ nick = this.nicks[nickIndex]
+ } else {
+ return
+ }
- for(let mode in modeTranslations) {
- let prefix = modeTranslations[mode];
- if(nick.modes.indexOf(mode) == -1) continue;
- let a = nick.modes.indexOf(mode) - 1;
- if(a >= 0) {
- if(prefixes.indexOf(modeTranslations[nick.modes[a]]) < prefixes.indexOf(prefix)) {
- nick.prefix = modeTranslations[nick.modes[a]];
- break;
- }
- } else {
- nick.prefix = prefix;
- break;
- }
- }
+ let modeTranslations = irc.serverData[this.buffer.server].modeTranslation
+ let prefixes = irc.serverData[this.buffer.server].supportedPrefixes
- this.render();
- }
+ nick.modes.push(newMode)
- modeRemoved(nickname, oldMode) {
- let nickIndex = this.getNickIndex(nickname);
- let nick = null;
+ for (let mode in modeTranslations) {
+ let prefix = modeTranslations[mode]
+ if (nick.modes.indexOf(mode) === -1) continue
+ let a = nick.modes.indexOf(mode) - 1
+ if (a >= 0) {
+ if (prefixes.indexOf(modeTranslations[nick.modes[a]]) < prefixes.indexOf(prefix)) {
+ nick.prefix = modeTranslations[nick.modes[a]]
+ break
+ }
+ } else {
+ nick.prefix = prefix
+ break
+ }
+ }
- if(nickIndex != null)
- nick = this.nicks[nickIndex];
- else
- return;
+ this.render()
+ }
- let modeTranslations = irc.serverData[this.buffer.server].modeTranslation;
- let prefixes = irc.serverData[this.buffer.server].supportedPrefixes;
+ modeRemoved (nickname, oldMode) {
+ let nickIndex = this.getNickIndex(nickname)
+ let nick = null
- remove_str(nick.modes, oldMode);
+ if (nickIndex != null) {
+ nick = this.nicks[nickIndex]
+ } else {
+ return
+ }
- let currentLowest = '';
+ let modeTranslations = irc.serverData[this.buffer.server].modeTranslation
+ let prefixes = irc.serverData[this.buffer.server].supportedPrefixes
- for(let n in nick.modes) {
- let mode = nick.modes[n];
- let nextMode = nick.modes[n+1];
- if(!nextMode && mode) {
- currentLowest = modeTranslations[mode];
- break;
- } else if(nextMode) {
- if(prefixes.indexOf(modeTranslations[nextMode]) > prefixes.indexOf(modeTranslations[mode]))
- currentLowest = modeTranslations[nextMode];
- } else {
- break;
- }
- }
+ removeStr(nick.modes, oldMode)
- nick.prefix = currentLowest;
+ let currentLowest = ''
- this.render();
- }
+ for (let n in nick.modes) {
+ let mode = nick.modes[n]
+ let nextMode = nick.modes[n + 1]
+ if (!nextMode && mode) {
+ currentLowest = modeTranslations[mode]
+ break
+ } else if (nextMode) {
+ if (prefixes.indexOf(modeTranslations[nextMode]) > prefixes.indexOf(modeTranslations[mode])) {
+ currentLowest = modeTranslations[nextMode]
+ }
+ } else {
+ break
+ }
+ }
+
+ nick.prefix = currentLowest
+
+ this.render()
+ }
}
class Tab {
- constructor(buffer) {
- this.buffer = buffer;
- this.element = null;
- this.closeRequested = false;
- }
+ constructor (buffer) {
+ this.buffer = buffer
+ this.element = null
+ this.closeRequested = false
+ }
- // Create a tab element
- renderTab() {
- let internals = ''+ this.buffer.title +'';
-
- let ttt = document.createElement('div');
- ttt.innerHTML = internals;
- ttt.className = 'tab';
- ttt.setAttribute('id', 'tab-'+this.buffer.name);
- clientdom.tabby.appendChild(ttt);
- this.element = ttt;
+ // Create a tab element
+ renderTab () {
+ let internals = span(this.buffer.title, null, 'title') + span('', ['none'], 'unread')
- ttt.innerHTML += 'x';
- ttt.querySelector('#close').addEventListener('click', () => {
- this.close();
- }, false);
+ let ttt = document.createElement('div')
+ ttt.innerHTML = internals
+ ttt.className = 'tab'
+ ttt.setAttribute('id', 'tab-' + this.buffer.name)
+ clientdom.tabby.appendChild(ttt)
+ this.element = ttt
- ttt.addEventListener('click', () => {
- if(this.closeRequested) return;
+ ttt.innerHTML += span('x', null, 'close')
+ ttt.querySelector('#close').addEventListener('click', () => {
+ this.close()
+ }, false)
- if(this.buffer.active)
- return;
+ ttt.addEventListener('click', () => {
+ if (this.closeRequested) return
+ if (this.buffer.active) return
- irc.chat.render(this.buffer);
- }, false);
- }
+ irc.chat.render(this.buffer)
+ }, false)
+ }
- setActive(active) {
- if(this.element) {
- this.element.className = 'tab';
- if(active) {
- addClass(this.element, 'active');
- }
- }
- }
+ setActive (active) {
+ if (this.element) {
+ this.element.className = 'tab'
+ if (active) {
+ addClass(this.element, 'active')
+ }
+ }
+ }
- setHot(hot) {
- if(this.element) {
- if(hot)
- addClass(this.element, 'hot');
- else
- removeClass(this.element, 'hot');
- }
- }
+ setHot (hot) {
+ if (this.element) {
+ if (hot) {
+ addClass(this.element, 'hot')
+ } else {
+ removeClass(this.element, 'hot')
+ }
+ }
+ }
- setUnreadCount(count) {
- if(this.element) {
- let counter = this.element.querySelector('#unread');
- if(count == 0) {
- counter.className = 'none';
- } else {
- counter.innerHTML = count;
- counter.className = '';
- }
- }
- }
+ setUnreadCount (count) {
+ if (this.element) {
+ let counter = this.element.querySelector('#unread')
+ if (count === 0) {
+ counter.className = 'none'
+ } else {
+ counter.innerHTML = count
+ counter.className = ''
+ }
+ }
+ }
- setTitle(title) {
- let titleEl = this.element.querySelector('#title');
- if(titleEl)
- titleEl.innerHTML = title;
- }
+ setTitle (title) {
+ let titleEl = this.element.querySelector('#title')
+ if (titleEl) {
+ titleEl.innerHTML = title
+ }
+ }
- close() {
- this.closeRequested = true;
- this.buffer.closeChatBuffer();
- }
+ close () {
+ this.closeRequested = true
+ this.buffer.closeChatBuffer()
+ }
}
class ChatBuffer {
- constructor(servername, buffername, tabname, type) {
- this.messages = [];
- this.nicklist = null;
- this.topic = null;
- this.input = '';
- this.lastscroll = 0;
- this.wasAtBottom = false;
- this.unreadCount = 0;
+ constructor (servername, buffername, tabname, type) {
+ this.messages = []
+ this.nicklist = null
+ this.topic = null
+ this.input = ''
+ this.lastscroll = 0
+ this.wasAtBottom = false
+ this.unreadCount = 0
- this.server = servername;
- this.name = buffername;
- this.title = tabname;
- this.type = type;
- this.active = false;
- this.alive = true;
- this.hot = false;
+ this.server = servername
+ this.name = buffername
+ this.title = tabname
+ this.type = type
+ this.active = false
+ this.alive = true
+ this.hot = false
- if(type != 'applet') {
- this.tab = new Tab(this);
- this.tab.renderTab();
- }
+ if (type !== 'applet') {
+ this.tab = new Tab(this)
+ this.tab.renderTab()
+ }
- if(type == 'channel')
- this.nicklist = new Nicklist(this, clientdom.nicklist);
- }
+ if (type === 'channel') {
+ this.nicklist = new Nicklist(this, clientdom.nicklist)
+ }
+ }
- render() {
- this.active = true;
- this.tab.setActive(true);
- this.unreadCount = 0;
- this.tab.setUnreadCount(0);
+ render () {
+ this.active = true
+ this.tab.setActive(true)
+ this.unreadCount = 0
+ this.tab.setUnreadCount(0)
- clientdom.chat.className = 'chatarea';
- clientdom.nicklist.innerHTML = '';
- clientdom.topicbar.innerHTML = '';
+ clientdom.chat.className = 'chatarea'
+ clientdom.nicklist.innerHTML = ''
+ clientdom.topicbar.innerHTML = ''
- if(!irc.config.sharedInput)
- clientdom.input.value = this.input;
+ if (!irc.config.sharedInput) {
+ clientdom.input.value = this.input
+ }
- if(this.nicklist) {
- addClass(clientdom.chat, 'vnicks');
- this.nicklist.render();
- }
+ if (this.nicklist) {
+ addClass(clientdom.chat, 'vnicks')
+ this.nicklist.render()
+ }
- if(this.hot)
- this.setHotStatus(false);
+ if (this.hot) {
+ this.setHotStatus(false)
+ }
- if(this.topic != null && this.topic != '') {
- addClass(clientdom.chat, 'vtopic');
- if(irc.config.colors)
- clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.stylize(this.topic)));
- else
- clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.strip(this.topic)));
- }
+ if (this.topic != null && this.topic !== '') {
+ addClass(clientdom.chat, 'vtopic')
+ if (irc.config.colors) {
+ clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.stylize(this.topic)))
+ } else {
+ clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.strip(this.topic)))
+ }
+ }
- this.renderMessages();
- if(this.wasAtBottom)
- clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight;
- else
- clientdom.letterbox.scrollTop = this.lastscroll;
+ this.renderMessages()
+ if (this.wasAtBottom) {
+ clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight
+ } else {
+ clientdom.letterbox.scrollTop = this.lastscroll
+ }
- clientdom.currentNickname.innerHTML = irc.serverData[this.server].my_nick;
+ clientdom.currentNickname.innerHTML = irc.serverData[this.server] ? irc.serverData[this.server].my_nick
+ : el('i', 'Disconnected')
- irc.chat.changeTitle('TeemantIRC - '+this.title);
- }
+ irc.chat.changeTitle('TeemantIRC - ' + this.title)
+ }
- renderMessages() {
- if(!this.active) return;
+ renderMessages () {
+ if (!this.active) return
- clientdom.letterbox.innerHTML = '';
+ clientdom.letterbox.innerHTML = ''
- for(let t in this.messages) {
- let mesg = this.messages[t];
- this.appendMessage({message: mesg.message, sender: mesg.sender, type: mesg.type, time: mesg.time});
- }
- }
+ for (let t in this.messages) {
+ let mesg = this.messages[t]
+ this.appendMessage({ message: mesg.message, sender: mesg.sender, type: mesg.type, time: mesg.time })
+ }
+ }
- clearMessages() {
- this.messages = [];
+ clearMessages () {
+ this.messages = []
- if(this.active)
- clientdom.letterbox.innerHTML = '';
- }
+ if (this.active) {
+ clientdom.letterbox.innerHTML = ''
+ }
+ }
- setHotStatus(hot) {
- this.hot = hot;
- if(this.tab)
- this.tab.setHot(hot);
- }
+ setHotStatus (hot) {
+ this.hot = hot
+ if (this.tab) {
+ this.tab.setHot(hot)
+ }
+ }
- appendMessage(meta) {
- let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type, this.server);
+ appendMessage (meta) {
+ let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type, this.server)
- if(irc.serverData[this.server]) {
- let mynick = irc.serverData[this.server].my_nick;
- if((meta.type == 'privmsg' || meta.type == 'notice' || meta.type == 'action') &&
- meta.message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && meta.sender != mynick)
- addClass(mesgConstr, 'mentioned');
- }
+ if (irc.serverData[this.server]) {
+ let mynick = irc.serverData[this.server].my_nick
+ if ((meta.type === 'privmsg' || meta.type === 'notice' || meta.type === 'action') &&
+ meta.message.toLowerCase().indexOf(mynick.toLowerCase()) !== -1 && meta.sender !== mynick) {
+ addClass(mesgConstr, 'mentioned')
+ }
+ }
- clientdom.letterbox.appendChild(mesgConstr);
+ clientdom.letterbox.appendChild(mesgConstr)
- let lFactor = clientdom.letterbox.offsetHeight + clientdom.letterbox.scrollTop;
- if(lFactor > clientdom.letterbox.scrollHeight - 100)
- clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight;
- }
+ let lFactor = clientdom.letterbox.offsetHeight + clientdom.letterbox.scrollTop
+ if (lFactor > clientdom.letterbox.scrollHeight - 100) {
+ clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight
+ }
+ }
- topicChange(topic) {
- if(this.active) {
- if(irc.config.colors)
- clientdom.topicbar.innerHTML = processors.linkify(colorizer.stylize(topic));
- else
- clientdom.topicbar.innerHTML = processors.linkify(colorizer.strip(topic));
+ topicChange (topic) {
+ if (this.active) {
+ if (irc.config.colors) {
+ clientdom.topicbar.innerHTML = processors.linkify(colorizer.stylize(topic))
+ } else {
+ clientdom.topicbar.innerHTML = processors.linkify(colorizer.strip(topic))
+ }
- if(this.topic == null)
- addClass(clientdom.chat, 'vtopic');
- }
- this.topic = topic;
- }
+ if (this.topic == null) {
+ addClass(clientdom.chat, 'vtopic')
+ }
+ }
+ this.topic = topic
+ }
- addMessage(message, sender, type, time) {
- let mesg = {message: message, sender: sender, type: type, time: time || new Date()};
- this.messages.push(mesg);
+ addMessage (message, sender, type, time) {
+ let mesg = { message: message, sender: sender, type: type, time: time || new Date() }
+ this.messages.push(mesg)
- if(this.active) {
- this.appendMessage(mesg);
- } else {
- this.unreadCount += 1;
- if(irc.serverData[this.server]) {
- let mynick = irc.serverData[this.server].my_nick;
- if((type == 'privmsg' || type == 'notice' || type == 'action') &&
- message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && sender != mynick) {
- // TODO: notify user of mentioned
-
- if(!this.active)
- this.setHotStatus(true);
- }
- }
- }
+ if (this.active) {
+ this.appendMessage(mesg)
+ } else {
+ this.unreadCount += 1
+ if (irc.serverData[this.server]) {
+ let mynick = irc.serverData[this.server].my_nick
+ if ((type === 'privmsg' || type === 'notice' || type === 'action') &&
+ message.toLowerCase().indexOf(mynick.toLowerCase()) !== -1 && sender !== mynick) {
+ // TODO: notify user of mentioned
- this.tab.setUnreadCount(this.unreadCount);
- }
+ if (!this.active) {
+ this.setHotStatus(true)
+ }
+ }
+ }
+ }
- switchOff() {
- irc.chat.input_handler.searchNicknames = [];
+ this.tab.setUnreadCount(this.unreadCount)
+ }
- let lFactor = clientdom.letterbox.offsetHeight + clientdom.letterbox.scrollTop;
- if(lFactor > clientdom.letterbox.scrollHeight - 100)
- this.wasAtBottom = true;
- else
- this.wasAtBottom = false;
+ switchOff () {
+ irc.chat.input_handler.searchNicknames = []
- if(!irc.config.sharedInput)
- this.input = clientdom.input.value;
+ let lFactor = clientdom.letterbox.offsetHeight + clientdom.letterbox.scrollTop
+ if (lFactor > clientdom.letterbox.scrollHeight - 100) {
+ this.wasAtBottom = true
+ } else {
+ this.wasAtBottom = false
+ }
- this.tab.setActive(false);
- this.lastscroll = clientdom.letterbox.scrollTop;
- this.active = false;
- }
+ if (!irc.config.sharedInput) {
+ this.input = clientdom.input.value
+ }
- setAliveStatus(status) {
- this.alive = status;
- if(this.alive)
- this.tab.setTitle(this.title);
- else
- this.tab.setTitle('('+this.title+')');
- }
+ this.tab.setActive(false)
+ this.lastscroll = clientdom.letterbox.scrollTop
+ this.active = false
+ }
- closeChatBuffer() {
- irc.chat.closeChatBuffer(this);
- }
+ setAliveStatus (status) {
+ this.alive = status
+ if (this.alive) {
+ this.tab.setTitle(this.title)
+ } else {
+ this.tab.setTitle(el('i', sf('(%s)', this.title)))
+ }
+ }
+
+ closeChatBuffer () {
+ irc.chat.closeChatBuffer(this)
+ }
}
class ThemeSelector {
- constructor(settings, variable) {
- this.settings = settings;
- this.variable = variable;
- }
+ constructor (settings, variable) {
+ this.settings = settings
+ this.variable = variable
+ }
- set_active_selection(name) {
- let all = clientdom.settings.available_themes.querySelectorAll('.theme_button');
- if(all.length > 0) {
- for(let a in all) {
- if(all[a] && all[a]['className']) {
- let elem = all[a];
- if(elem.getAttribute('id') == 'theme-'+name) {
- addClass(elem, 'selected');
- } else {
- removeClass(elem, 'selected');
- }
- }
- }
- }
- }
+ setActiveSelection (name) {
+ let all = clientdom.settings.available_themes.querySelectorAll('.theme_button')
+ if (all.length > 0) {
+ for (let a in all) {
+ if (all[a] && all[a]['className']) {
+ let elem = all[a]
+ if (elem.getAttribute('id') === 'theme-' + name) {
+ addClass(elem, 'selected')
+ } else {
+ removeClass(elem, 'selected')
+ }
+ }
+ }
+ }
+ }
- bindButton(button, theme) {
- button.onclick = (e) => {
- this.settings.themeSelection = theme;
- this.set_active_selection(theme);
- };
- }
+ bindButton (button, theme) {
+ button.onclick = (e) => {
+ this.settings.themeSelection = theme
+ this.setActiveSelection(theme)
+ }
+ }
- render() {
- clientdom.settings.available_themes.innerHTML = '';
+ render () {
+ clientdom.settings.available_themes.innerHTML = ''
- for(let n in themes.available) {
- let theme = themes.available[n];
- let button = composer.theme_selection(n, theme);
+ for (let n in themes.available) {
+ let theme = themes.available[n]
+ let button = composer.themeSelection(n, theme)
- clientdom.settings.available_themes.appendChild(button);
+ clientdom.settings.available_themes.appendChild(button)
- this.bindButton(button, n);
- }
- }
+ this.bindButton(button, n)
+ }
+ }
}
class AppletChatBuffer extends ChatBuffer {
- constructor(appletName, title, frame) {
- super('', appletName, title, 'applet');
- this.tab = null;
- this.isOpen = false;
- this.timeout = null;
- this.frame = frame;
- }
+ constructor (appletName, title, frame) {
+ super('', appletName, title, 'applet')
+ this.tab = null
+ this.isOpen = false
+ this.timeout = null
+ this.frame = frame
+ }
- closeChatBuffer() {
- irc.chat.closeChatBuffer(this);
- this.tab = null;
- this.isOpen = false;
- }
+ closeChatBuffer () {
+ irc.chat.closeChatBuffer(this)
+ this.tab = null
+ this.isOpen = false
+ }
- open() {
- if(this.isOpen) {
- irc.chat.render(this);
- return;
- }
+ open () {
+ if (this.isOpen) {
+ irc.chat.render(this)
+ return
+ }
- this.tab = new Tab(this);
- this.tab.renderTab();
- irc.chat.buffers.push(this);
- irc.chat.render(this);
- this.isOpen = true;
- }
+ this.tab = new Tab(this)
+ this.tab.renderTab()
+ irc.chat.buffers.push(this)
+ irc.chat.render(this)
+ this.isOpen = true
+ }
- addMessage(message, sender, type, time) {
- // Don't send messages to any applet buffer
- return;
- }
+ addMessage (message, sender, type, time) {
+ // Don't send messages to any applet buffer
+ }
- switchOff() {
- this.active = false;
- this.tab.setActive(false);
- this.frame.style.display = 'none';
- }
+ switchOff () {
+ this.active = false
+ this.tab.setActive(false)
+ this.frame.style.display = 'none'
+ }
- render() {
- this.active = true;
- this.tab.setActive(true);
- this.frame.style.display = 'block';
- }
+ render () {
+ this.active = true
+ this.tab.setActive(true)
+ this.frame.style.display = 'block'
+ }
}
class Settings extends AppletChatBuffer {
- constructor() {
- super('settings', 'Settings', clientdom.settings.frame);
+ constructor () {
+ super('settings', 'Settings', clientdom.settings.frame)
- this.themeSelection = '';
+ this.themeSelection = ''
- this.themeSelector = new ThemeSelector(this);
- this.themeSelector.render();
+ this.themeSelector = new ThemeSelector(this)
+ this.themeSelector.render()
- clientdom.settings.save.onclick = (e) => {
- this.saveSpecified();
- };
+ clientdom.settings.save.onclick = (e) => {
+ this.saveSpecified()
+ }
- clientdom.settings.open.onclick = (e) => {
- this.open();
- };
- }
+ clientdom.settings.open.onclick = (e) => {
+ this.open()
+ }
+ }
- switch_theme() {
- if(this.themeSelection != '') {
- themes.change_theme(this.themeSelection);
- irc.config.theme = this.themeSelection;
- this.themeSelector.set_active_selection(this.themeSelection);
- }
- }
+ switchTheme () {
+ if (this.themeSelection !== '') {
+ themes.change_theme(this.themeSelection)
+ irc.config.theme = this.themeSelection
+ this.themeSelector.setActiveSelection(this.themeSelection)
+ }
+ }
- saveSpecified() {
- if(this.timeout)
- clearTimeout(this.timeout);
+ saveSpecified () {
+ if (this.timeout) {
+ clearTimeout(this.timeout)
+ }
- this.switch_theme();
+ this.switchTheme()
- for(let key in irc.config) {
- let value = irc.config[key];
- let type = typeof(value);
+ for (let key in irc.config) {
+ let value = irc.config[key]
+ let type = typeof value
- if(clientdom.settings[key]) {
- if(type == 'boolean')
- irc.config[key] = clientdom.settings[key].checked;
- else
- irc.config[key] = clientdom.settings[key].value;
- }
- }
- clientdom.settings.saveStatus.innerHTML = 'Settings saved!';
+ if (clientdom.settings[key]) {
+ if (type === 'boolean') {
+ irc.config[key] = clientdom.settings[key].checked
+ } else {
+ irc.config[key] = clientdom.settings[key].value
+ }
+ }
+ }
+ clientdom.settings.saveStatus.innerHTML = span('Settings saved!', ['success'])
- if('localStorage' in window) {
- window.localStorage['teemant_settings'] = JSON.stringify(irc.config);
- }
+ if ('localStorage' in window) {
+ window.localStorage['teemant_settings'] = JSON.stringify(irc.config)
+ }
- this.timeout = setTimeout(function() {
- clientdom.settings.saveStatus.innerHTML = '';
- }, 3000);
- }
+ this.timeout = setTimeout(function () {
+ clientdom.settings.saveStatus.innerHTML = ''
+ }, 3000)
+ }
- setInitialValues() {
- if('localStorage' in window) {
- if(window.localStorage['teemant_settings']) {
- try {
- let settings = JSON.parse(window.localStorage.teemant_settings);
- for(let key in irc.config) {
- let value = irc.config[key];
- let type = typeof(value);
+ setInitialValues () {
+ if ('localStorage' in window) {
+ if (window.localStorage['teemant_settings']) {
+ try {
+ let settings = JSON.parse(window.localStorage.teemant_settings)
+ for (let key in irc.config) {
+ let value = irc.config[key]
+ let type = typeof value
- if(settings[key]) {
- if(key == 'theme') {
- this.themeSelection = settings[key];
- continue;
- }
+ if (settings[key]) {
+ if (key === 'theme') {
+ this.themeSelection = settings[key]
+ continue
+ }
- if(type == 'boolean')
- clientdom.settings[key].checked = settings[key];
- else
- clientdom.settings[key].value = settings[key];
- }
- }
- this.saveSpecified();
- return;
- } catch(e) {}
- }
- }
+ if (type === 'boolean') {
+ clientdom.settings[key].checked = settings[key]
+ } else {
+ clientdom.settings[key].value = settings[key]
+ }
+ }
+ }
+ this.saveSpecified()
+ return
+ } catch (e) {}
+ }
+ }
- for(let key in irc.config) {
- let value = irc.config[key];
- let type = typeof(value);
+ for (let key in irc.config) {
+ let value = irc.config[key]
+ let type = typeof value
- if(clientdom.settings[key]) {
- if(type == 'boolean')
- clientdom.settings[key].checked = value;
- else
- clientdom.settings[key].value = value;
- }
- }
- }
+ if (clientdom.settings[key]) {
+ if (type === 'boolean') {
+ clientdom.settings[key].checked = value
+ } else {
+ clientdom.settings[key].value = value
+ }
+ }
+ }
+ }
- render() {
- super.render();
- clientdom.chat.className = 'chatarea';
- clientdom.nicklist.innerHTML = '';
- clientdom.topicbar.innerHTML = '';
- clientdom.letterbox.innerHTML = '';
- irc.chat.changeTitle('TeemantIRC - Settings');
- }
+ render () {
+ super.render()
+ clientdom.chat.className = 'chatarea'
+ clientdom.nicklist.innerHTML = ''
+ clientdom.topicbar.innerHTML = ''
+ clientdom.letterbox.innerHTML = ''
+ irc.chat.changeTitle('TeemantIRC - Settings')
+ }
}
class IRCConnector {
- constructor() {
- this.formLocked = false;
- this.canClose = false;
- this.defaults = {};
+ constructor () {
+ this.formLocked = false
+ this.canClose = false
+ this.defaults = {}
- clientdom.connector.form.onsubmit = (e) => {
- if(this.formLocked) {
- e.preventDefault();
- return false;
- }
+ clientdom.connector.form.onsubmit = (e) => {
+ if (this.formLocked) {
+ e.preventDefault()
+ return false
+ }
- this.formLocked = true;
+ this.formLocked = true
- this.validateForm(e);
- };
+ this.validateForm(e)
+ }
- clientdom.connector.onkeyup = (e) => {
- let key = evt.keyCode || evt.which || evt.charCode || 0;
- if(key === 27 && this.canClose)
- this.authComplete();
- };
+ clientdom.connector.onkeyup = (e) => {
+ let key = e.keyCode || e.which || e.charCode || 0
+ if (key === 27 && this.canClose) {
+ this.authComplete()
+ }
+ }
- clientdom.connector.pwtrigger.onclick = (e) => {
- this.togglePassword();
- };
- }
+ clientdom.connector.pwtrigger.onclick = (e) => {
+ this.togglePassword()
+ }
+ }
- fillFormFromURI(urlParams) {
- if(this.defaults.server)
- clientdom.connector.server.value = this.defaults.server;
- if(this.defaults.port)
- clientdom.connector.port.value = this.defaults.port;
- if(this.defaults.ssl)
- clientdom.connector.secure.checked = this.defaults.ssl;
+ fillFormFromURI (urlParams) {
+ if (this.defaults.server) {
+ clientdom.connector.server.value = this.defaults.server
+ }
- for(let param in urlParams) {
- let value = urlParams[param];
+ if (this.defaults.port) {
+ clientdom.connector.port.value = this.defaults.port
+ }
- switch(param) {
- case 'nick':
- case 'nickname':
- if (validators.nickname(value))
- clientdom.connector.nickname.value = value.replace(/\?/g, rand(10000, 99999));
- break;
- case 'secure':
- case 'ssl':
- if(value == 'true' || value == '1')
- clientdom.connector.secure.checked = true;
- break;
- case 'password':
- if(value == 'true' || value == '1') {
- clientdom.connector.pwtrigger.checked = true;
- this.togglePassword();
- }
- break;
- case 'server':
- case 'host':
- if(validators.iporhost(value))
- clientdom.connector.server.value = value;
- break;
- case 'server_data':
- case 'extra':
- case 'extras':
- case 'connection':
- if(value == 'false' || value == '0')
- clientdom.connector.server_data.style.display = 'none';
- break;
- case 'port':
- try {
- let ppp = parseInt(value);
- clientdom.connector.port.value = ppp;
- } catch(e) {}
- break;
- }
- }
+ if (this.defaults.ssl) {
+ clientdom.connector.secure.checked = this.defaults.ssl
+ }
- if(window.location.hash)
- clientdom.connector.channel.value = window.location.hash;
-
- if(window.location.pathname.length > 4) {
- let t1 = window.location.pathname.substring(1, window.location.pathname.length-1);
- let proposed = '';
+ for (let param in urlParams) {
+ let value = urlParams[param]
- if(t1.indexOf('/') != -1) {
- proposed = t1.split('/');
- proposed = proposed[proposed.length-1];
- } else {
- proposed = t1;
- }
+ switch (param) {
+ case 'nick':
+ case 'nickname':
+ if (validators.nickname(value)) {
+ clientdom.connector.nickname.value = value.replace(/\?/g, rand(10000, 99999))
+ }
+ break
+ case 'secure':
+ case 'ssl':
+ if (value === 'true' || value === '1') {
+ clientdom.connector.secure.checked = true
+ }
+ break
+ case 'password':
+ if (value === 'true' || value === '1') {
+ clientdom.connector.pwtrigger.checked = true
+ this.togglePassword()
+ }
+ break
+ case 'server':
+ case 'host':
+ if (validators.iporhost(value)) {
+ clientdom.connector.server.value = value
+ }
+ break
+ case 'server_data':
+ case 'extra':
+ case 'extras':
+ case 'connection':
+ if (value === 'false' || value === '0') {
+ clientdom.connector.server_data.style.display = 'none'
+ }
+ break
+ case 'port':
+ try {
+ let ppp = parseInt(value)
+ clientdom.connector.port.value = ppp
+ } catch (e) {}
+ break
+ }
+ }
- if(validators.iporhost(proposed))
- clientdom.connector.server.value = proposed;
- }
- }
+ if (window.location.hash) {
+ clientdom.connector.channel.value = window.location.hash
+ }
- defaultTo(data) {
- this.defaults = data;
- }
+ if (window.location.pathname.length > 4) {
+ let t1 = window.location.pathname.substring(1, window.location.pathname.length - 1)
+ let proposed = ''
- getDataFromForm() {
- let nickname = clientdom.connector.nickname.value;
- let password = clientdom.connector.password.value;
- let channel = clientdom.connector.channel.value;
- let server = clientdom.connector.server.value;
- let port = clientdom.connector.port.value;
+ if (t1.indexOf('/') !== -1) {
+ proposed = t1.split('/')
+ proposed = proposed[proposed.length - 1]
+ } else {
+ proposed = t1
+ }
- if (!validators.nickname(nickname)) {
- this.authMessage('Erroneous nickname!', true);
- return false;
- }
+ if (validators.iporhost(proposed)) {
+ clientdom.connector.server.value = proposed
+ }
+ }
+ }
- if (channel.indexOf(',') !== -1) {
- channel = channel.trim().split(',');
+ defaultTo (data) {
+ this.defaults = data
+ }
- for (let t in channel) {
- let chan = channel[t];
-
- channel[t] = chan.trim();
+ getDataFromForm () {
+ let nickname = clientdom.connector.nickname.value
+ let password = clientdom.connector.password.value
+ let channel = clientdom.connector.channel.value
+ let server = clientdom.connector.server.value
+ let port = clientdom.connector.port.value
- if (chan.indexOf('#') != 0) {
- channel[t] = '#'+chan;
- }
- }
- } else if(channel != '') {
- channel = channel.trim();
- if (channel.indexOf('#') != 0) {
- channel = '#'+channel;
- }
- channel = [channel];
- } else {
- channel = [];
- }
+ if (!validators.nickname(nickname)) {
+ this.authMessage('Erroneous nickname!', true)
+ return false
+ }
- if(!validators.iporhost(server)) {
- this.authMessage('Erroneous server address!', true);
- return false;
- }
+ if (channel.indexOf(',') !== -1) {
+ channel = channel.trim().split(',')
- try {
- port = parseInt(port);
- } catch(e) {
- this.authMessage('Erroneous port!', true);
- return false;
- }
+ for (let t in channel) {
+ let chan = channel[t]
- if(port < 10 || port > 65535) {
- this.authMessage('Erroneous port!', true);
- return false;
- }
+ channel[t] = chan.trim()
- if(!clientdom.connector.pwtrigger.checked)
- password = '';
+ if (chan.indexOf('#') !== 0) {
+ channel[t] = '#' + chan
+ }
+ }
+ } else if (channel !== '') {
+ channel = channel.trim()
+ if (channel.indexOf('#') !== 0) {
+ channel = '#' + channel
+ }
+ channel = [channel]
+ } else {
+ channel = []
+ }
- return {nickname: nickname,
- autojoin: channel,
- server: server,
- port: port,
- password: password,
- secure: clientdom.connector.secure.checked };
- }
+ if (!validators.iporhost(server)) {
+ this.authMessage('Erroneous server address!', true)
+ return false
+ }
- validateForm(event) {
- event.preventDefault();
+ try {
+ port = parseInt(port)
+ } catch (e) {
+ this.authMessage('Erroneous port!', true)
+ return false
+ }
- let data = this.getDataFromForm();
- if(!data) return;
+ if (port < 10 || port > 65535) {
+ this.authMessage('Erroneous port!', true)
+ return false
+ }
- irc.socket.emit('irc_create', data);
- return true;
- }
+ if (!clientdom.connector.pwtrigger.checked) {
+ password = ''
+ }
- authMessage(message, error) {
- clientdom.connector.messenger.innerHTML = ''+message+'';
- if(error)
- this.formLocked = false;
- }
+ return {
+ nickname: nickname,
+ autojoin: channel,
+ server: server,
+ port: port,
+ password: password,
+ secure: clientdom.connector.secure.checked
+ }
+ }
- togglePassword() {
- if(clientdom.connector.pwtrigger.checked)
- clientdom.connector.pwbox.style.display = 'block';
- else
- clientdom.connector.pwbox.style.display = 'none';
- }
+ validateForm (event) {
+ event.preventDefault()
- authComplete() {
- clientdom.connector.frame.style.display = 'none';
- this.formLocked = false;
- }
+ let data = this.getDataFromForm()
+ if (!data) return
+
+ irc.socket.emit('irc_create', data)
+ return true
+ }
+
+ authMessage (message, error) {
+ clientdom.connector.messenger.innerHTML = span(message, ['msg', (error ? 'error' : '')])
+ if (error) {
+ this.formLocked = false
+ }
+ }
+
+ togglePassword () {
+ if (clientdom.connector.pwtrigger.checked) {
+ clientdom.connector.pwbox.style.display = 'block'
+ } else {
+ clientdom.connector.pwbox.style.display = 'none'
+ }
+ }
+
+ authComplete () {
+ clientdom.connector.frame.style.display = 'none'
+ this.formLocked = false
+ }
}
class InputHandler {
- constructor() {
- this.history = [];
- this.historyCaret = 0;
- this.searchNicknames = [];
+ constructor () {
+ this.history = []
+ this.historyCaret = 0
+ this.searchNicknames = []
- this.index = -1;
- this.words = [];
- this.last = '';
+ this.index = -1
+ this.words = []
+ this.last = ''
- clientdom.input.onkeyup = (evt) => {
- let key = evt.keyCode || evt.which || evt.charCode || 0;
- if (key == 13) {
- this.handleInput();
- return;
- }
+ clientdom.input.onkeyup = (e) => {
+ let key = e.keyCode || e.which || e.charCode || 0
+ if (key === 13) {
+ this.handleInput()
+ return
+ }
- this.keyUpHandle(evt, key);
- };
+ this.keyUpHandle(e, key)
+ }
- clientdom.input.onkeydown = (e) => {
- let key = e.keyCode || e.which || e.charCode || 0;
- if (e.ctrlKey || e.shiftKey || e.altKey) {
- return;
- }
+ clientdom.input.onkeydown = (e) => {
+ let key = e.keyCode || e.which || e.charCode || 0
+ if (e.ctrlKey || e.shiftKey || e.altKey) {
+ return
+ }
- this.keyDownHandle(e, key);
- };
+ this.keyDownHandle(e, key)
+ }
- clientdom.input.onfocus = (e) => {
- if(irc.config.scrollOnFocus)
- clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight;
- };
+ clientdom.input.onfocus = (e) => {
+ if (irc.config.scrollOnFocus) {
+ clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight
+ }
+ }
- clientdom.send.onclick = (e) => {
- this.handleInput();
- };
- }
+ clientdom.send.onclick = (e) => {
+ this.handleInput()
+ }
+ }
- keyUpHandle(e, key) {
- if(key == 38 || key == 40) {
- clientdom.input.selectionStart = clientdom.input.value.length;
- clientdom.input.selectionEnd = clientdom.input.value.length;
- } else if(key == 9) return;
- let input = clientdom.input.value;
- let word = input.split(/ |\n/).pop();
+ keyUpHandle (e, key) {
+ if (key === 38 || key === 40) {
+ clientdom.input.selectionStart = clientdom.input.value.length
+ clientdom.input.selectionEnd = clientdom.input.value.length
+ } else if (key === 9) return
+ let input = clientdom.input.value
+ let word = input.split(/ |\n/).pop()
- // Reset iteration.
- this.tabCompleteReset();
+ // Reset iteration.
+ this.tabCompleteReset()
- // Check for matches if the current word is the last word.
- if (clientdom.input.selectionStart == input.length && word.length) {
- // Call the match() function to filter the words.
- this.tabWords = match(word, this.searchNicknames);
- if(input.indexOf(word) == 0)
- for(let n in this.tabWords)
- this.tabWords[n] += ': ';
- }
+ // Check for matches if the current word is the last word.
+ if (clientdom.input.selectionStart === input.length && word.length) {
+ // Call the match() function to filter the words.
+ this.tabWords = match(word, this.searchNicknames)
+ if (input.indexOf(word) === 0) {
+ for (let n in this.tabWords) {
+ this.tabWords[n] += ': '
+ }
+ }
+ }
+ }
- }
+ keyDownHandle (e, key) {
+ if (key === 38) {
+ if (this.historyCaret <= 0) {
+ this.historyCaret = 0
+ } else {
+ this.historyCaret -= 1
+ }
- keyDownHandle(e, key) {
- if(key == 38) {
- if(this.historyCaret <= 0) {
- this.historyCaret = 0;
- } else {
- this.historyCaret -= 1;
- }
+ let selection = this.history[this.historyCaret]
- let selection = this.history[this.historyCaret];
+ if (selection) {
+ clientdom.input.value = selection
+ this.tabCompleteReset()
+ }
- if(selection) {
- clientdom.input.value = selection;
- this.tabCompleteReset();
- }
+ return
+ } else if (key === 40) {
+ if (this.historyCaret >= this.history.length) {
+ this.historyCaret = this.history.length
+ } else {
+ this.historyCaret += 1
+ }
- return;
- } else if(key == 40) {
- if(this.historyCaret >= this.history.length) {
- this.historyCaret = this.history.length;
- } else {
- this.historyCaret += 1;
- }
+ let selection = this.history[this.historyCaret]
- let selection = this.history[this.historyCaret];
+ if (!this.history[this.historyCaret]) selection = ''
- if(!this.history[this.historyCaret])
- selection = '';
+ clientdom.input.value = selection
+ this.tabCompleteReset()
- clientdom.input.value = selection;
- this.tabCompleteReset();
+ return
+ }
- return;
- }
+ if (key === 9) {
+ e.preventDefault()
- if(key == 9) {
- e.preventDefault();
+ this.index++
- this.index++;
+ // Get next match.
+ let word = this.tabWords[this.index % this.tabWords.length]
+ if (!word) {
+ return
+ }
- // Get next match.
- let word = this.tabWords[this.index % this.tabWords.length];
- if (!word) {
- return;
- }
+ let value = clientdom.input.value
+ this.lastWord = this.lastWord || value.split(/ |\n/).pop()
- let value = clientdom.input.value;
- this.lastWord = this.lastWord || value.split(/ |\n/).pop();
+ // Return if the 'minLength' requirement isn't met.
+ if (this.lastWord.length < 1) return
- // Return if the 'minLength' requirement isn't met.
- if (this.lastWord.length < 1)
- return;
+ let text = value.substr(0, clientdom.input.selectionStart - this.lastWord.length) + word
+ clientdom.input.value = text
- let text = value.substr(0, clientdom.input.selectionStart - this.lastWord.length) + word;
- clientdom.input.value = text;
+ // Remember the word until next time.
+ this.lastWord = word
+ }
+ }
- // Remember the word until next time.
- this.lastWord = word;
+ tabCompleteReset () {
+ this.index = -1
+ this.lastWord = ''
+ this.tabWords = []
+ }
- return;
- }
- }
+ handleInput () {
+ let message = clientdom.input.value
+ let buffer = irc.chat.getActiveChatBuffer()
- tabCompleteReset() {
- this.index = -1;
- this.lastWord = '';
- this.tabWords = [];
- }
+ if (!buffer) return
+ if (message.trim() === '') return
- handleInput() {
- let message = clientdom.input.value;
- let buffer = irc.chat.getActiveChatBuffer();
+ let listargs = message.split(' ')
- if(!buffer) return;
- if(message.trim() == '') return;
+ if (listargs[0].indexOf('/') === 0) {
+ let command = listargs[0].substring(1).toLowerCase()
+ if (command.toLowerCase() in commands) {
+ let cmd = commands[command]
+ if ('execute' in cmd) {
+ cmd.execute(buffer, this, command, message, listargs)
+ }
+ } else {
+ let foundAliased = null
+ for (let cmd in commands) {
+ if (!commands[cmd]['aliases']) continue
+ if (commands[cmd].aliases.indexOf(command) !== -1) foundAliased = commands[cmd]
+ }
+ if (foundAliased) {
+ foundAliased.execute(buffer, this, command, message, listargs)
+ } else {
+ this.commandError(buffer, listargs[0].toUpperCase() + ': Unknown command!')
+ }
+ }
+ } else {
+ irc.socket.emit('userinput', { command: 'privmsg', server: buffer.server, message: message, arguments: [buffer.name] })
+ }
- let listargs = message.split(' ');
+ this.history.push(message)
+ this.historyCaret = this.history.length
+ clientdom.input.value = ''
+ }
- if(listargs[0].indexOf('/') == 0) {
- let command = listargs[0].substring(1).toLowerCase();
- if(command.toLowerCase() in commands) {
- let cmd = commands[command];
- if('execute' in cmd)
- cmd.execute(buffer, this, command, message, listargs);
- } else {
- let foundAliased = null;
- for(let cmd in commands) {
- if(!commands[cmd]['aliases']) continue;
- if(commands[cmd].aliases.indexOf(command) != -1) foundAliased = commands[cmd];
- }
- if(foundAliased)
- foundAliased.execute(buffer, this, command, message, listargs);
- else
- this.commandError(buffer, listargs[0].toUpperCase()+': Unknown command!');
- }
-
- } else {
- irc.socket.emit('userinput', {command: 'privmsg', server: buffer.server, message: message, arguments: [buffer.name]});
- }
-
- this.history.push(message);
- this.historyCaret = this.history.length;
- clientdom.input.value = '';
- }
-
- commandError(buffer, message) {
- buffer.addMessage(message, null, 'error');
- return true;
- }
+ commandError (buffer, message) {
+ buffer.addMessage(message, null, 'error')
+ return true
+ }
}
class IRCChatWindow {
- constructor() {
- this.buffers = [];
- this.firstServer = true;
- this.currentChatBuffer = null;
- this.input_handler = new InputHandler();
-
- clientdom.frame.style.display = 'none';
-
- clientdom.smsctrig.onclick = (e) => {
- toggleClass(clientdom.chat, 'vopentrig');
- };
- }
-
- destroyAllChatBuffers() {
- // Wipe all server data
- irc.serverData = {};
- irc.serverChatQueue = {};
- this.buffers = [];
-
- // Clear tabs
- clientdom.tabby.innerHTML = '';
-
- // Reset to the defaults
- irc.auther.authMessage('Disconnected', true);
- clientdom.frame.style.display = 'none';
- this.firstServer = true;
- window.onbeforeunload = null;
- }
-
- getChatBufferByName(buffername) {
- let result = null;
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.name.toLowerCase() == buffername.toLowerCase())
- result = buf;
- }
- return result;
- }
-
- getActiveChatBuffer() {
- let result = null;
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.active == true)
- result = buf;
- }
- return result;
- }
-
- getServerChatBuffer(server) {
- let result = null;
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.server == server)
- result = buf;
- }
- return result;
- }
-
- getChatBuffersByServer(server) {
- let result = [];
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.server == server)
- result.push(buf);
- }
- return result;
- }
-
- getChatBufferByServerName(server, channel) {
- let result = null;
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.server == server && buf.name.toLowerCase() == channel.toLowerCase())
- result = buf;
- }
- return result;
- }
-
- getChatBuffersByType(type) {
- let result = [];
- for (let t in this.buffers) {
- let buf = this.buffers[t];
- if(buf.type == type)
- result.push(buf);
- }
- return result;
- }
-
- newServerChatBuffer(serverinfo) {
- if(this.firstServer) {
- clientdom.frame.style.display = 'block';
- window.onbeforeunload = function(e) {
- return 'IRC will disconnect.';
- };
- }
-
- let prefixes = '';
-
- for(let v in serverinfo.supportedModes) {
- prefixes += serverinfo.supportedModes[v];
- }
-
- irc.serverData[serverinfo.address] = {
- modeTranslation: serverinfo.supportedModes,
- supportedPrefixes: prefixes,
- network: serverinfo.network,
- my_nick: serverinfo.nickname,
- max_channel_length: serverinfo.max_channel_length
- };
-
- let newServer = new ChatBuffer(serverinfo.address, serverinfo.address, serverinfo.network, 'server');
- this.buffers.push(newServer);
- this.render(newServer);
- this.firstServer = false;
-
- if(irc.serverChatQueue[serverinfo.address]) {
- for(let a in irc.serverChatQueue[serverinfo.address]) {
- let mesg = irc.serverChatQueue[serverinfo.address][a];
- newServer.addMessage(mesg.message, mesg.from, mesg.type, mesg.time);
- }
- delete irc.serverChatQueue[serverinfo.address];
- }
-
- }
-
- createChatBuffer(server, name, type, autoswitch) {
- let buf = this.getChatBufferByServerName(server, name);
- if(buf) {
- if(autoswitch)
- this.render(buf);
- return buf;
- }
-
- buf = new ChatBuffer(server, name, name, type);
- this.buffers.push(buf);
-
- if(autoswitch)
- this.render(buf);
-
- return buf;
- }
-
- closeChatBuffer(buffer) {
- if(buffer.type == 'server')
- irc.socket.emit('userinput', {command: 'quit', server: buffer.server, message: 'Server tab closed', arguments: []});
- else if(buffer.type == 'channel' && buffer.alive)
- irc.socket.emit('userinput', {command: 'part', server: buffer.server, message: 'Tab closed', arguments: [buffer.name]});
-
- let bufIndex = this.buffers.indexOf(buffer);
-
- if(buffer.active) {
- if (bufIndex == 0) {
- if(this.buffers[bufIndex+1]) {
- this.render(this.buffers[bufIndex+1]);
- }
- } else {
- this.render(this.buffers[bufIndex-1]);
- }
- }
-
- buffer.tab.element.remove();
- this.buffers.splice(bufIndex, 1);
-
- if(this.buffers.length == 0 || (this.buffers.length == 1 && this.buffers[0].type == 'applet')) {
- irc.chat.destroyAllChatBuffers();
- irc.auther.authMessage('Create a new connection', false);
- irc.auther.canClose = false;
- clientdom.connector.frame.style.display = 'block';
- }
- }
-
- messageChatBuffer(name, server, message) {
- let buf = this.getChatBufferByServerName(server, name);
-
- if(buf == null)
- buf = this.createChatBuffer(server, name, 'message', false);
-
- if(message.type == 'privmsg' && message.message.indexOf('\x01ACTION') == 0) {
- message.message = message.message.substring(8);
- message.type = 'action';
- }
-
- buf.addMessage(message.message, message.from, message.type);
- }
-
- buildNicklist(channel, server, nicks) {
- let buf = this.getChatBufferByServerName(server, channel);
-
- if(buf == null)
- return;
-
- let channelSendNicks = [];
-
- for(let n in nicks) {
- let nick = {nickname: '', prefix: '', modes: []};
-
- if(irc.serverData[buf.server].supportedPrefixes.split('').indexOf(nicks[n].substring(0, 1)) != -1) {
- nick.prefix = nicks[n].substring(0, 1);
- nick.nickname = nicks[n].substring(1);
- nick.modes = [objectGetKey(irc.serverData[buf.server].modeTranslation, nick.prefix)];
- channelSendNicks.push('{0}{1}'.format(nick.prefix, nick.nickname));
- } else {
- nick.nickname = nicks[n];
- channelSendNicks.push('{1}'.format(nick.prefix, nick.nickname));
- }
-
- buf.nicklist.nickAddObject(nick);
- }
-
- buf.addMessage('Nicks {0}: {1}'.format(channel, channelSendNicks.join(', ')), null, 'names');
-
- if(buf.active)
- buf.nicklist.render();
- }
-
- nickChange(server, oldNick, newNick) {
- let buffers = this.getChatBuffersByServer(server);
-
- if(irc.serverData[server].my_nick == oldNick) {
- irc.serverData[server].my_nick = newNick;
-
- let activeBuf = this.getActiveChatBuffer();
-
- if(activeBuf.server == server) {
- clientdom.currentNickname.innerHTML = newNick;
- }
- }
-
- for(let i in buffers) {
- let buffer = buffers[i];
-
- if(buffer.type != 'channel') continue;
- if(buffer.nicklist.getNickIndex(oldNick) == null) continue;
-
- buffer.nicklist.nickChange(oldNick, newNick);
- buffer.addMessage('{0} is now known as {1}'.format(oldNick, newNick), null, 'nick');
- }
- }
-
- topicChange(channel, server, topic, changer) {
- let buf = this.getChatBufferByServerName(server, channel);
-
- if (!buf) return;
-
- buf.topicChange(topic);
- if(changer)
- buf.addMessage('{0} has changed the topic of {1} to \'{2}\''.format(changer, channel, topic),
- null, 'topic');
- else
- buf.addMessage('Topic of {0} is \'{1}\''.format(channel, topic), null, 'topic');
- }
-
- handleQuit(server, user, reason) {
- let buffers = this.getChatBuffersByServer(server);
-
- for(let i in buffers) {
- let buffer = buffers[i];
-
- if(buffer.type != 'channel') continue;
- if(buffer.nicklist.getNickIndex(user.nickname) == null) continue;
-
- buffer.nicklist.nickRemove(user.nickname);
- buffer.addMessage('{0}@{1} has quit {2}'.format(user.username,
- user.hostname, reason), user.nickname, 'quit');
- }
- }
-
- handleJoin(server, user, channel) {
- let buffer = this.getChatBufferByServerName(server, channel);
-
- if(!buffer) return;
-
- if(user.nickname == irc.serverData[server].my_nick)
- buffer.setAliveStatus(true);
- else
- buffer.nicklist.nickAdd(user.nickname);
-
- buffer.addMessage('{0}@{1} has joined {2}'.format(user.username,
- user.hostname, channel), user.nickname, 'join');
- }
-
- handleLeave(server, user, channel, reason, kicker) {
- let buffer = this.getChatBufferByServerName(server, channel);
-
- if(!buffer) return;
-
- if(user['nickname']) {
- if(user.nickname == irc.serverData[server].my_nick)
- buffer.setAliveStatus(false);
- } else {
- if(user == irc.serverData[server].my_nick)
- buffer.setAliveStatus(false);
- }
-
- if(kicker)
- buffer.addMessage('has kicked {0} {1}'.format(user, reason), kicker.nickname, 'part');
- else
- buffer.addMessage('{0}@{1} has left {2}{3}'.format(user.username,
- user.hostname, (reason != null ? ' '+reason+'' : '')), user.nickname, 'part');
- if(kicker)
- buffer.nicklist.nickRemove(user);
- else
- buffer.nicklist.nickRemove(user.nickname);
- }
-
- handleMode(data) {
- let buf = null;
- if(data.target == irc.serverData[data.server].my_nick)
- buf = this.getServerChatBuffer(data.server);
- else
- buf = this.getChatBufferByServerName(data.server, data.target);
-
- if(!buf) return;
-
- if(data.type == 'mode_add') {
- buf.nicklist.modeAdded(data.modeTarget, data.mode);
- buf.addMessage('set mode {0} +{1} {2}'.format(data.target,
- data.mode, data.modeTarget), data.user.nickname, 'mode');
- } else if(data.type == 'mode_del') {
- buf.nicklist.modeRemoved(data.modeTarget, data.mode);
- buf.addMessage('set mode {0} -{1} {2}'.format(data.target,
- data.mode, data.modeTarget), data.user.nickname, 'mode');
- } else {
- buf.addMessage('set mode {0} {1}'.format(data.target,
- data.message), data.user.nickname, 'mode');
- }
- }
-
- joinChannels(server, channel) {
- if (channel.indexOf(',') !== -1) {
- channel = channel.trim().split(',');
-
- for (let t in channel) {
- let chan = channel[t];
-
- channel[t] = chan.trim();
-
- if (chan.indexOf('#') != 0) {
- channel[t] = '#'+chan;
- }
- }
- } else if(channel != '') {
- channel = channel.trim();
- if (channel.indexOf('#') != 0) {
- channel = '#'+channel;
- }
- channel = [channel];
- } else {
- channel = [];
- }
-
- irc.socket.emit('userinput', {command: 'join', server: server, message: '', arguments: channel});
- }
-
- changeTitle(title) {
- // TODO: notify of hot buffers
- document.title = title;
- irc.documentTitle = title;
- }
-
- render(buffer) {
- let activeNow = this.getActiveChatBuffer();
- this.input_handler.tabCompleteReset();
-
- if(activeNow)
- activeNow.switchOff();
-
- buffer.render();
- }
+ constructor () {
+ this.buffers = []
+ this.firstServer = true
+ this.currentChatBuffer = null
+ this.input_handler = new InputHandler()
+
+ clientdom.frame.style.display = 'none'
+
+ clientdom.smsctrig.onclick = (e) => {
+ toggleClass(clientdom.chat, 'vopentrig')
+ }
+ }
+
+ destroyAllChatBuffers () {
+ // Wipe all server data
+ irc.serverData = {}
+ irc.serverChatQueue = {}
+ this.buffers = []
+
+ // Clear tabs
+ clientdom.tabby.innerHTML = ''
+
+ // Reset to the defaults
+ irc.auther.authMessage('Disconnected', true)
+ clientdom.frame.style.display = 'none'
+ this.firstServer = true
+ window.onbeforeunload = null
+ }
+
+ getChatBufferByName (buffername) {
+ let result = null
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.name.toLowerCase() === buffername.toLowerCase()) {
+ result = buf
+ break
+ }
+ }
+ return result
+ }
+
+ getActiveChatBuffer () {
+ let result = null
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.active === true) {
+ result = buf
+ break
+ }
+ }
+ return result
+ }
+
+ getServerChatBuffer (server) {
+ let result = null
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.server === server) {
+ result = buf
+ break
+ }
+ }
+ return result
+ }
+
+ getChatBuffersByServer (server) {
+ let result = []
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.server === server) {
+ result.push(buf)
+ }
+ }
+ return result
+ }
+
+ getChatBufferByServerName (server, channel) {
+ let result = null
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.server === server && buf.name.toLowerCase() === channel.toLowerCase()) {
+ result = buf
+ break
+ }
+ }
+ return result
+ }
+
+ getChatBuffersByType (type) {
+ let result = []
+ for (let t in this.buffers) {
+ let buf = this.buffers[t]
+ if (buf.type === type) {
+ result.push(buf)
+ }
+ }
+ return result
+ }
+
+ newServerChatBuffer (serverinfo) {
+ if (this.firstServer) {
+ clientdom.frame.style.display = 'block'
+ window.onbeforeunload = function (e) {
+ return 'IRC will disconnect.'
+ }
+ }
+
+ let prefixes = ''
+
+ for (let v in serverinfo.supportedModes) {
+ prefixes += serverinfo.supportedModes[v]
+ }
+
+ irc.serverData[serverinfo.address] = {
+ modeTranslation: serverinfo.supportedModes,
+ supportedPrefixes: prefixes,
+ network: serverinfo.network,
+ my_nick: serverinfo.nickname,
+ max_channel_length: serverinfo.max_channel_length
+ }
+
+ let newServer = new ChatBuffer(serverinfo.address, serverinfo.address, serverinfo.network, 'server')
+ this.buffers.push(newServer)
+ this.render(newServer)
+ this.firstServer = false
+
+ if (irc.serverChatQueue[serverinfo.address]) {
+ for (let a in irc.serverChatQueue[serverinfo.address]) {
+ let mesg = irc.serverChatQueue[serverinfo.address][a]
+ newServer.addMessage(mesg.message, mesg.from, mesg.type, mesg.time)
+ }
+ delete irc.serverChatQueue[serverinfo.address]
+ }
+ }
+
+ createChatBuffer (server, name, type, autoswitch) {
+ let buf = this.getChatBufferByServerName(server, name)
+ if (buf) {
+ if (autoswitch) {
+ this.render(buf)
+ }
+ return buf
+ }
+
+ buf = new ChatBuffer(server, name, name, type)
+ this.buffers.push(buf)
+
+ if (autoswitch) {
+ this.render(buf)
+ }
+
+ return buf
+ }
+
+ closeChatBuffer (buffer) {
+ if (buffer.type === 'server') {
+ irc.socket.emit('userinput', { command: 'quit', server: buffer.server, message: 'Server tab closed', arguments: [] })
+ } else if (buffer.type === 'channel' && buffer.alive) {
+ irc.socket.emit('userinput', { command: 'part', server: buffer.server, message: 'Tab closed', arguments: [buffer.name] })
+ }
+
+ let bufIndex = this.buffers.indexOf(buffer)
+
+ if (buffer.active) {
+ if (bufIndex === 0) {
+ if (this.buffers[bufIndex + 1]) {
+ this.render(this.buffers[bufIndex + 1])
+ }
+ } else {
+ this.render(this.buffers[bufIndex - 1])
+ }
+ }
+
+ buffer.tab.element.remove()
+ this.buffers.splice(bufIndex, 1)
+
+ if (this.buffers.length === 0 || (this.buffers.length === 1 && this.buffers[0].type === 'applet')) {
+ irc.chat.destroyAllChatBuffers()
+ irc.auther.authMessage('Create a new connection', false)
+ irc.auther.canClose = false
+ clientdom.connector.frame.style.display = 'block'
+ }
+ }
+
+ messageChatBuffer (name, server, message) {
+ let buf = this.getChatBufferByServerName(server, name)
+
+ if (buf == null) {
+ buf = this.createChatBuffer(server, name, 'message', false)
+ }
+
+ if (message.type === 'privmsg' && message.message.indexOf('\x01ACTION') === 0) {
+ message.message = message.message.substring(8)
+ message.type = 'action'
+ }
+
+ buf.addMessage(message.message, message.from, message.type)
+ }
+
+ buildNicklist (channel, server, nicks) {
+ let buf = this.getChatBufferByServerName(server, channel)
+
+ if (buf == null) return
+
+ let channelSendNicks = []
+
+ for (let n in nicks) {
+ let nick = { nickname: '', prefix: '', modes: [] }
+
+ if (irc.serverData[buf.server].supportedPrefixes.split('').indexOf(nicks[n].substring(0, 1)) !== -1) {
+ nick.prefix = nicks[n].substring(0, 1)
+ nick.nickname = nicks[n].substring(1)
+ nick.modes = [objectGetKey(irc.serverData[buf.server].modeTranslation, nick.prefix)]
+ channelSendNicks.push(span(nick.prefix, ['prefix']) + span(nick.nickname, ['nick']))
+ } else {
+ nick.nickname = nicks[n]
+ channelSendNicks.push(span(nick.nickname, ['nick']))
+ }
+
+ buf.nicklist.nickAddObject(nick)
+ }
+
+ buf.addMessage(sf('Nicks %s: %s', span(channel, ['channel']), channelSendNicks.join(', ')), null, 'names')
+
+ if (buf.active) {
+ buf.nicklist.render()
+ }
+ }
+
+ nickChange (server, oldNick, newNick) {
+ let buffers = this.getChatBuffersByServer(server)
+
+ if (irc.serverData[server].my_nick === oldNick) {
+ irc.serverData[server].my_nick = newNick
+
+ let activeBuf = this.getActiveChatBuffer()
+
+ if (activeBuf.server === server) {
+ clientdom.currentNickname.innerHTML = newNick
+ }
+ }
+
+ for (let i in buffers) {
+ let buffer = buffers[i]
+
+ if (buffer.type !== 'channel') continue
+ if (buffer.nicklist.getNickIndex(oldNick) == null) continue
+
+ buffer.nicklist.nickChange(oldNick, newNick)
+ buffer.addMessage(sf('%s is now known as %s', oldNick, newNick), null, 'nick')
+ }
+ }
+
+ topicChange (channel, server, topic, changer) {
+ let buf = this.getChatBufferByServerName(server, channel)
+
+ if (!buf) return
+
+ buf.topicChange(topic)
+ if (changer) {
+ buf.addMessage(sf('%s has changed the topic of %s to %s', span(changer, ['nick']), channel, topic),
+ null, 'topic')
+ } else {
+ buf.addMessage(sf('Topic of %s is \'%s\'', span(channel, ['channel']), topic), null, 'topic')
+ }
+ }
+
+ handleQuit (server, user, reason) {
+ let buffers = this.getChatBuffersByServer(server)
+
+ for (let i in buffers) {
+ let buffer = buffers[i]
+
+ if (buffer.type !== 'channel') continue
+ if (buffer.nicklist.getNickIndex(user.nickname) == null) continue
+
+ buffer.nicklist.nickRemove(user.nickname)
+ buffer.addMessage(sf('%s has quit %s', span(sf('%s@%s', user.username, user.hostname), ['hostmask']), reason), user.nickname, 'quit')
+ }
+ }
+
+ handleJoin (server, user, channel) {
+ let buffer = this.getChatBufferByServerName(server, channel)
+
+ if (!buffer) return
+
+ if (user.nickname === irc.serverData[server].my_nick) {
+ buffer.setAliveStatus(true)
+ } else {
+ buffer.nicklist.nickAdd(user.nickname)
+ }
+
+ buffer.addMessage(sf('%s has joined %s', span(sf('%s@%s', user.username, user.hostname), ['hostmask']), channel), user.nickname, 'join')
+ }
+
+ handleLeave (server, user, channel, reason, kicker) {
+ let buffer = this.getChatBufferByServerName(server, channel)
+
+ if (!buffer) return
+
+ if (user['nickname']) {
+ if (irc.serverData[server] && user.nickname === irc.serverData[server].my_nick) {
+ buffer.setAliveStatus(false)
+ }
+ } else {
+ if (irc.serverData[server] && user === irc.serverData[server].my_nick) {
+ buffer.setAliveStatus(false)
+ }
+ }
+
+ if (kicker) {
+ buffer.addMessage(sf('has kicked %s %s', span(user, ['nick']), reason), kicker.nickname, 'part')
+ } else {
+ buffer.addMessage(sf('%s has left %s %s', span(sf('%s@%s', user.username, user.hostname), ['hostmask']), channel,
+ (reason != null ? span(reason, ['reason']) : '')), user.nickname, 'part')
+ }
+ if (kicker) {
+ buffer.nicklist.nickRemove(user)
+ } else {
+ buffer.nicklist.nickRemove(user.nickname)
+ }
+ }
+
+ handleMode (data) {
+ let buf = null
+ if (data.target === irc.serverData[data.server].my_nick) {
+ buf = this.getServerChatBuffer(data.server)
+ } else {
+ buf = this.getChatBufferByServerName(data.server, data.target)
+ }
+
+ if (!buf) return
+
+ if (data.type === 'mode_add') {
+ buf.nicklist.modeAdded(data.modeTarget, data.mode)
+ buf.addMessage('set mode ' + span(data.target, ['channel']) + ' ' + span(sf('+%s %s', data.mode, data.modeTarget), ['mode']),
+ data.user.nickname, 'mode')
+ } else if (data.type === 'mode_del') {
+ buf.nicklist.modeRemoved(data.modeTarget, data.mode)
+ buf.addMessage('set mode ' + span(data.target, ['channel']) + ' ' + span(sf('-%s %s', data.mode, data.modeTarget), ['mode']),
+ data.user.nickname, 'mode')
+ } else {
+ buf.addMessage('set mode ' + span(data.target, ['channel']) + ' ' + span(data.message, ['mode']),
+ data.user.nickname, 'mode')
+ }
+ }
+
+ joinChannels (server, channel) {
+ if (channel.indexOf(',') !== -1) {
+ channel = channel.trim().split(',')
+
+ for (let t in channel) {
+ let chan = channel[t]
+
+ channel[t] = chan.trim()
+
+ if (chan.indexOf('#') !== 0) {
+ channel[t] = '#' + chan
+ }
+ }
+ } else if (channel !== '') {
+ channel = channel.trim()
+ if (channel.indexOf('#') !== 0) {
+ channel = '#' + channel
+ }
+ channel = [channel]
+ } else {
+ channel = []
+ }
+
+ irc.socket.emit('userinput', { command: 'join', server: server, message: '', arguments: channel })
+ }
+
+ changeTitle (title) {
+ // TODO: notify of hot buffers
+ document.title = title
+ irc.documentTitle = title
+ }
+
+ render (buffer) {
+ let activeNow = this.getActiveChatBuffer()
+ this.input_handler.tabCompleteReset()
+
+ if (activeNow) {
+ activeNow.switchOff()
+ }
+
+ buffer.render()
+ }
}
-/**************************\
-|** **|
-|** INITIALIZATION **|
-|** **|
-\**************************/
+// Initialization
-function parseURL() {
- let match,
- pl = /\+/g, // Regex for replacing addition symbol with a space
- search = /([^&=]+)=?([^&]*)/g,
- decode = function (s) { return decodeURIComponent(s.replace(pl, ' ')); },
- query = window.location.search.substring(1);
+function parseURL () {
+ let match
+ let pl = /\+/g // Regex for replacing addition symbol with a space
+ let search = /([^&=]+)=?([^&]*)/g
+ let decode = (s) => { return decodeURIComponent(s.replace(pl, ' ')) }
+ let query = window.location.search.substring(1)
- let urlParams = {};
- while (match = search.exec(query))
- urlParams[decode(match[1])] = decode(match[2]);
+ let urlParams = {}
+ while ((match = search.exec(query)) != null) {
+ urlParams[decode(match[1])] = decode(match[2])
+ }
- irc.auther.fillFormFromURI(urlParams);
+ irc.auther.fillFormFromURI(urlParams)
}
-function stopWarnings() {
- if(Object.keys(irc.serverData).length == 0)
- window.onbeforeunload = null;
+function stopWarnings () {
+ if (Object.keys(irc.serverData).length === 0) {
+ window.onbeforeunload = null
+ }
}
-window.onresize = function() {
- if(irc.config.scrollOnResize)
- clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight;
-};
+window.onresize = function () {
+ if (irc.config.scrollOnResize) {
+ clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight
+ }
+}
-window.onload = function() {
- irc.primaryFrame = document.querySelector('.ircclient');
+window.onload = function () {
+ irc.primaryFrame = document.querySelector('.ircclient')
- clientdom.settings['frame'] = irc.primaryFrame.querySelector('.settings');
+ clientdom.settings['frame'] = irc.primaryFrame.querySelector('.settings')
- for(let key in irc.config) {
- clientdom.settings[key] = clientdom.settings.frame.querySelector('#s_'+key);
- }
+ for (let key in irc.config) {
+ clientdom.settings[key] = clientdom.settings.frame.querySelector('#s_' + key)
+ }
- clientdom.settings['available_themes'] = clientdom.settings.frame.querySelector('.available_themes');
- clientdom.settings['save'] = clientdom.settings.frame.querySelector('#save_settings');
- clientdom.settings['saveStatus'] = clientdom.settings.frame.querySelector('#settings_status');
- clientdom.connector['frame'] = irc.primaryFrame.querySelector('#authdialog');
- clientdom.connector['server_data'] = clientdom.connector.frame.querySelector('.server_data');
- clientdom.connector['messenger'] = clientdom.connector.frame.querySelector('#connmsg');
- clientdom.connector['form'] = clientdom.connector.frame.querySelector('#IRCConnector');
- clientdom.connector['nickname'] = clientdom.connector.form.querySelector('#nickname');
- clientdom.connector['password'] = clientdom.connector.form.querySelector('#password');
- clientdom.connector['pwtrigger'] = clientdom.connector.form.querySelector('#password_trig');
- clientdom.connector['pwbox'] = clientdom.connector.form.querySelector('.password_box');
- clientdom.connector['channel'] = clientdom.connector.form.querySelector('#channel');
- clientdom.connector['server'] = clientdom.connector.form.querySelector('#server');
- clientdom.connector['port'] = clientdom.connector.form.querySelector('#port');
- clientdom.connector['secure'] = clientdom.connector.form.querySelector('#secure');
- clientdom['tabby'] = irc.primaryFrame.querySelector('.tabby');
- clientdom['frame'] = irc.primaryFrame.querySelector('#chat');
- clientdom['letterbox'] = clientdom.frame.querySelector('.letterbox');
- clientdom['nicklist'] = clientdom.frame.querySelector('.nicklist');
- clientdom['currentNickname'] = clientdom.frame.querySelector('.my_nickname');
- clientdom['input'] = clientdom.frame.querySelector('.userinput');
- clientdom['send'] = clientdom.frame.querySelector('.sendbutton');
- clientdom['chat'] = clientdom.frame.querySelector('.chatarea');
- clientdom['topicbar'] = clientdom.chat.querySelector('.topicbar');
- clientdom['smsctrig'] = clientdom.chat.querySelector('.smsc-nicklistbtn');
- clientdom.settings['open'] = irc.primaryFrame.querySelector('.open_settings');
+ clientdom.settings['available_themes'] = clientdom.settings.frame.querySelector('.available_themes')
+ clientdom.settings['save'] = clientdom.settings.frame.querySelector('#save_settings')
+ clientdom.settings['saveStatus'] = clientdom.settings.frame.querySelector('#settings_status')
+ clientdom.connector['frame'] = irc.primaryFrame.querySelector('#authdialog')
+ clientdom.connector['server_data'] = clientdom.connector.frame.querySelector('.server_data')
+ clientdom.connector['messenger'] = clientdom.connector.frame.querySelector('#connmsg')
+ clientdom.connector['form'] = clientdom.connector.frame.querySelector('#IRCConnector')
+ clientdom.connector['nickname'] = clientdom.connector.form.querySelector('#nickname')
+ clientdom.connector['password'] = clientdom.connector.form.querySelector('#password')
+ clientdom.connector['pwtrigger'] = clientdom.connector.form.querySelector('#password_trig')
+ clientdom.connector['pwbox'] = clientdom.connector.form.querySelector('.password_box')
+ clientdom.connector['channel'] = clientdom.connector.form.querySelector('#channel')
+ clientdom.connector['server'] = clientdom.connector.form.querySelector('#server')
+ clientdom.connector['port'] = clientdom.connector.form.querySelector('#port')
+ clientdom.connector['secure'] = clientdom.connector.form.querySelector('#secure')
+ clientdom['tabby'] = irc.primaryFrame.querySelector('.tabby')
+ clientdom['frame'] = irc.primaryFrame.querySelector('#chat')
+ clientdom['letterbox'] = clientdom.frame.querySelector('.letterbox')
+ clientdom['nicklist'] = clientdom.frame.querySelector('.nicklist')
+ clientdom['currentNickname'] = clientdom.frame.querySelector('.my_nickname')
+ clientdom['input'] = clientdom.frame.querySelector('.userinput')
+ clientdom['send'] = clientdom.frame.querySelector('.sendbutton')
+ clientdom['chat'] = clientdom.frame.querySelector('.chatarea')
+ clientdom['topicbar'] = clientdom.chat.querySelector('.topicbar')
+ clientdom['smsctrig'] = clientdom.chat.querySelector('.smsc-nicklistbtn')
+ clientdom.settings['open'] = irc.primaryFrame.querySelector('.open_settings')
- irc.socket = io.connect();
+ irc.socket = io.connect()
- irc.settings = new Settings();
- irc.auther = new IRCConnector();
- irc.chat = new IRCChatWindow();
+ irc.settings = new Settings()
+ irc.auther = new IRCConnector()
+ irc.chat = new IRCChatWindow()
- irc.settings.setInitialValues();
+ irc.settings.setInitialValues()
- irc.socket.on('defaults', function (data) {
- irc.auther.defaultTo(data);
- parseURL();
- window.onpopstate = parseURL;
- });
+ irc.socket.on('defaults', function (data) {
+ irc.auther.defaultTo(data)
+ parseURL()
+ window.onpopstate = parseURL
+ })
- irc.socket.on('connect', function (data) {
- irc.socketUp = true;
- });
+ irc.socket.on('connect', function (data) {
+ irc.socketUp = true
+ })
- irc.socket.on('disconnect', function (data) {
- irc.socketUp = false;
- irc.chat.destroyAllChatBuffers();
- clientdom.connector.frame.style.display = 'block';
- });
+ irc.socket.on('disconnect', function (data) {
+ irc.socketUp = false
+ irc.chat.destroyAllChatBuffers()
+ clientdom.connector.frame.style.display = 'block'
+ })
- // Does everything
- irc.socket.on('act_client', function (data) {
- if(data['message'])
- data.message = validators.escapeHTML(data.message);
- if(data['reason'])
- data.reason = validators.escapeHTML(data.reason);
-
- switch(data.type) {
- case 'event_connect':
- irc.auther.authComplete();
- irc.chat.newServerChatBuffer(data);
- break;
- case 'event_join_channel':
- if(data.user.nickname == irc.serverData[data.server].my_nick)
- irc.chat.createChatBuffer(data.server, data.channel, 'channel', true);
- irc.chat.handleJoin(data.server, data.user, data.channel);
- break;
- case 'event_kick_channel':
- irc.chat.handleLeave(data.server, data.kickee, data.channel, data.reason, data.user);
- break;
- case 'event_part_channel':
- irc.chat.handleLeave(data.server, data.user, data.channel, data.reason);
- break;
- case 'event_quit':
- irc.chat.handleQuit(data.server, data.user, data.reason);
- break;
- case 'event_server_quit':
- let serverz = irc.chat.getChatBuffersByServer(data.server);
- for(let a in serverz) {
- let serv = serverz[a];
- serv.addMessage('You are no longer talking on this server.', null, 'error');
- serv.setAliveStatus(false);
- }
-
- if(irc.serverData[data.server])
- delete irc.serverData[data.server];
- stopWarnings();
- break;
- case 'message':
- if(data.to == irc.serverData[data.server].my_nick) {
- irc.chat.messageChatBuffer(data.user.nickname, data.server, {message: data.message, type: data.messageType, from: data.user.nickname});
- } else if(data.to == null) {
- let atest = irc.chat.getActiveChatBuffer();
+ // Does everything
+ irc.socket.on('act_client', function (data) {
+ if (data['message']) {
+ data.message = validators.escapeHTML(data.message)
+ }
- if(atest.server != data.server)
- atest = irc.chat.getServerChatBuffer(data.server);
+ if (data['reason']) {
+ data.reason = validators.escapeHTML(data.reason)
+ }
- atest.addMessage(data.message, data.user.nickname, data.messageType);
- } else {
- irc.chat.messageChatBuffer(data.to, data.server, {message: data.message, type: data.messageType, from: data.user.nickname});
- }
- break;
- case 'channel_nicks':
- irc.chat.buildNicklist(data.channel, data.server, data.nicks);
- break;
- case 'channel_topic':
- if(data['topic'] && data['set_by'])
- irc.chat.topicChange(data.channel, data.server, data.topic, data['set_by']);
- else if(data['topic'])
- irc.chat.topicChange(data.channel, data.server, data.topic, null);
- else if(data['set_by'])
- irc.chat.messageChatBuffer(data.channel, data.server, {message: 'Topic set by '+data.set_by+' on '+new Date(data.time*1000), type: 'topic', from: null});
- break;
- case 'nick_change':
- irc.chat.nickChange(data.server, data.nick, data.newNick);
- break;
- case 'mode_add':
- case 'mode_del':
- case 'mode':
- irc.chat.handleMode(data);
- break;
- case 'server_message':
- if(data['error']) data.messageType = 'error';
- if(irc.chat.getServerChatBuffer(data.server) == null) {
- if(!irc.serverChatQueue[data.server]) {
- irc.serverChatQueue[data.server] = [];
- } else {
- irc.serverChatQueue[data.server].push({type: data.messageType, message: data.message, from: data.from || null, time: new Date()});
- }
- } else {
- irc.chat.messageChatBuffer(data.server, data.server, {message: data.message, type: data.messageType, from: data.from || null});
- }
- break;
- case 'connect_message':
- irc.auther.authMessage(data.message, data.error);
- break;
- case 'whoisResponse':
- whoisMessage(data.whois, irc.chat.getActiveChatBuffer());
- break;
- case 'listedchan':
- irc.chat.messageChatBuffer(data.server, data.server, {message: ''+data.channel+''+
- ' '+data.users+' '+data.topic+'',
- type: 'listentry', from: data.from});
- break;
- }
- });
-};
+ switch (data.type) {
+ case 'event_connect':
+ irc.auther.authComplete()
+ irc.chat.newServerChatBuffer(data)
+ break
+ case 'event_join_channel':
+ if (data.user.nickname === irc.serverData[data.server].my_nick) {
+ irc.chat.createChatBuffer(data.server, data.channel, 'channel', true)
+ }
+ irc.chat.handleJoin(data.server, data.user, data.channel)
+ break
+ case 'event_kick_channel':
+ irc.chat.handleLeave(data.server, data.kickee, data.channel, data.reason, data.user)
+ break
+ case 'event_part_channel':
+ irc.chat.handleLeave(data.server, data.user, data.channel, data.reason)
+ break
+ case 'event_quit':
+ irc.chat.handleQuit(data.server, data.user, data.reason)
+ break
+ case 'event_server_quit':
+ let serverz = irc.chat.getChatBuffersByServer(data.server)
+ for (let a in serverz) {
+ let serv = serverz[a]
+ serv.addMessage('You are no longer talking on this server.', null, 'error')
+ serv.setAliveStatus(false)
+ }
+
+ if (irc.serverData[data.server]) {
+ delete irc.serverData[data.server]
+ }
+ stopWarnings()
+ break
+ case 'message':
+ if (data.to === irc.serverData[data.server].my_nick) {
+ irc.chat.messageChatBuffer(data.user.nickname, data.server, { message: data.message, type: data.messageType, from: data.user.nickname })
+ } else if (data.to == null) {
+ let atest = irc.chat.getActiveChatBuffer()
+
+ if (atest.server !== data.server) {
+ atest = irc.chat.getServerChatBuffer(data.server)
+ }
+
+ atest.addMessage(data.message, data.user.nickname, data.messageType)
+ } else {
+ irc.chat.messageChatBuffer(data.to, data.server, { message: data.message, type: data.messageType, from: data.user.nickname })
+ }
+ break
+ case 'channel_nicks':
+ irc.chat.buildNicklist(data.channel, data.server, data.nicks)
+ break
+ case 'channel_topic':
+ if (data['topic'] && data['set_by']) {
+ irc.chat.topicChange(data.channel, data.server, data.topic, data['set_by'])
+ } else if (data['topic']) {
+ irc.chat.topicChange(data.channel, data.server, data.topic, null)
+ } else if (data['set_by']) {
+ irc.chat.messageChatBuffer(data.channel, data.server, {
+ message: 'Topic set by ' + data.set_by + ' on ' + (new Date(data.time * 1000)),
+ type: 'topic',
+ from: null
+ })
+ }
+ break
+ case 'nick_change':
+ irc.chat.nickChange(data.server, data.nick, data.newNick)
+ break
+ case 'mode_add':
+ case 'mode_del':
+ case 'mode':
+ irc.chat.handleMode(data)
+ break
+ case 'server_message':
+ if (data['error']) data.messageType = 'error'
+ if (irc.chat.getServerChatBuffer(data.server) == null) {
+ if (!irc.serverChatQueue[data.server]) {
+ irc.serverChatQueue[data.server] = []
+ } else {
+ irc.serverChatQueue[data.server].push({ type: data.messageType, message: data.message, from: data.from || null, time: new Date() })
+ }
+ } else {
+ irc.chat.messageChatBuffer(data.server, data.server, { message: data.message, type: data.messageType, from: data.from || null })
+ }
+ break
+ case 'connect_message':
+ irc.auther.authMessage(data.message, data.error)
+ break
+ case 'whoisResponse':
+ whoisMessage(data.whois, irc.chat.getActiveChatBuffer())
+ break
+ case 'listedchan':
+ irc.chat.messageChatBuffer(data.server, data.server,
+ {
+ message: span(data.channel, ['channel']) + ' ' +
+ span(data.users, ['usercount']) + ' ' +
+ span(data.topic, ['topic']),
+ type: 'listentry',
+ from: data.from
+ })
+ break
+ }
+ })
+}
diff --git a/src/js/theme.js b/src/js/theme.js
index f2414c2..0c576bc 100644
--- a/src/js/theme.js
+++ b/src/js/theme.js
@@ -1,46 +1,46 @@
-function swapSheet(name) {
- document.querySelector('#theme_stylesheet').setAttribute('href', 'style/'+name+'.css');
+function swapSheet (name) {
+ document.querySelector('#theme_stylesheet').setAttribute('href', 'style/' + name + '.css')
}
-const themes = module.exports = {
- available: {
- default: {
- name: 'Default',
- type: 'bright',
- nick_pallete: {
- H: [1, 360],
- S: [30, 100],
- L: [30, 70]
- },
- stylesheet: 'theme_default',
- default: true,
- colorSamples: {
- toolbar: '#00c7e0',
- background: '#f5f5f5'
- }
- },
+window.themes = module.exports = {
+ available: {
+ default: {
+ name: 'Default',
+ type: 'bright',
+ nick_pallete: {
+ H: [1, 360],
+ S: [30, 100],
+ L: [30, 70]
+ },
+ stylesheet: 'theme_default',
+ default: true,
+ colorSamples: {
+ toolbar: '#00c7e0',
+ background: '#f5f5f5'
+ }
+ },
- night: {
- name: 'Night',
- type: 'dark',
- nick_pallete: {
- H: [1, 360],
- S: [30, 100],
- L: [50, 100]
- },
- stylesheet: 'theme_night',
- default: false,
- colorSamples: {
- toolbar: '#008e8e',
- background: '#1d1d1d'
- }
- }
- },
+ night: {
+ name: 'Night',
+ type: 'dark',
+ nick_pallete: {
+ H: [1, 360],
+ S: [30, 100],
+ L: [50, 100]
+ },
+ stylesheet: 'theme_night',
+ default: false,
+ colorSamples: {
+ toolbar: '#008e8e',
+ background: '#1d1d1d'
+ }
+ }
+ },
- change_theme: function(name) {
- if(name in themes.available) {
- swapSheet(themes.available[name].stylesheet);
- window.irc.config.theme = name;
- }
- }
-};
+ change_theme: function (name) {
+ if (name in window.themes.available) {
+ swapSheet(window.themes.available[name].stylesheet)
+ window.irc.config.theme = name
+ }
+ }
+}
diff --git a/src/js/utility.js b/src/js/utility.js
new file mode 100644
index 0000000..09878fc
--- /dev/null
+++ b/src/js/utility.js
@@ -0,0 +1,185 @@
+import util from 'util'
+
+// Create element
+export function el (element, content, classes, id) {
+ let _el = document.createElement(element)
+ _el.innerHTML = content
+ _el.classList = classes || []
+ if (id) _el.id = id
+ return _el.outerHTML
+}
+
+export function span (content, classes, id) {
+ return el('span', content, classes, id)
+}
+
+// String format
+export function sf () {
+ return util.format.apply(null, arguments)
+}
+
+export function formatDate (date, format, utc) {
+ var MMMM = ['\x00', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
+ var MMM = ['\x01', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ var dddd = ['\x02', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
+ var ddd = ['\x03', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
+ function ii (i, len) { var s = i + ''; len = len || 2; while (s.length < len) s = '0' + s; return s }
+
+ var y = utc ? date.getUTCFullYear() : date.getFullYear()
+ format = format.replace(/(^|[^\\])yyyy+/g, '$1' + y)
+ format = format.replace(/(^|[^\\])yy/g, '$1' + y.toString().substr(2, 2))
+ format = format.replace(/(^|[^\\])y/g, '$1' + y)
+
+ var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1
+ format = format.replace(/(^|[^\\])MMMM+/g, '$1' + MMMM[0])
+ format = format.replace(/(^|[^\\])MMM/g, '$1' + MMM[0])
+ format = format.replace(/(^|[^\\])MM/g, '$1' + ii(M))
+ format = format.replace(/(^|[^\\])M/g, '$1' + M)
+
+ var d = utc ? date.getUTCDate() : date.getDate()
+ format = format.replace(/(^|[^\\])dddd+/g, '$1' + dddd[0])
+ format = format.replace(/(^|[^\\])ddd/g, '$1' + ddd[0])
+ format = format.replace(/(^|[^\\])dd/g, '$1' + ii(d))
+ format = format.replace(/(^|[^\\])d/g, '$1' + d)
+
+ var H = utc ? date.getUTCHours() : date.getHours()
+ format = format.replace(/(^|[^\\])HH+/g, '$1' + ii(H))
+ format = format.replace(/(^|[^\\])H/g, '$1' + H)
+
+ var h = H > 12 ? H - 12 : H === 0 ? 12 : H
+ format = format.replace(/(^|[^\\])hh+/g, '$1' + ii(h))
+ format = format.replace(/(^|[^\\])h/g, '$1' + h)
+
+ var m = utc ? date.getUTCMinutes() : date.getMinutes()
+ format = format.replace(/(^|[^\\])mm+/g, '$1' + ii(m))
+ format = format.replace(/(^|[^\\])m/g, '$1' + m)
+
+ var s = utc ? date.getUTCSeconds() : date.getSeconds()
+ format = format.replace(/(^|[^\\])ss+/g, '$1' + ii(s))
+ format = format.replace(/(^|[^\\])s/g, '$1' + s)
+
+ var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds()
+ format = format.replace(/(^|[^\\])fff+/g, '$1' + ii(f, 3))
+ f = Math.round(f / 10)
+ format = format.replace(/(^|[^\\])ff/g, '$1' + ii(f))
+ f = Math.round(f / 10)
+ format = format.replace(/(^|[^\\])f/g, '$1' + f)
+
+ var T = H < 12 ? 'AM' : 'PM'
+ format = format.replace(/(^|[^\\])TT+/g, '$1' + T)
+ format = format.replace(/(^|[^\\])T/g, '$1' + T.charAt(0))
+
+ var t = T.toLowerCase()
+ format = format.replace(/(^|[^\\])tt+/g, '$1' + t)
+ format = format.replace(/(^|[^\\])t/g, '$1' + t.charAt(0))
+
+ var tz = -date.getTimezoneOffset()
+ var K = utc || !tz ? 'Z' : tz > 0 ? '+' : '-'
+ if (!utc) {
+ tz = Math.abs(tz)
+ var tzHrs = Math.floor(tz / 60)
+ var tzMin = tz % 60
+ K += ii(tzHrs) + ':' + ii(tzMin)
+ }
+ format = format.replace(/(^|[^\\])K/g, '$1' + K)
+
+ var day = (utc ? date.getUTCDay() : date.getDay()) + 1
+ format = format.replace(new RegExp(dddd[0], 'g'), dddd[day])
+ format = format.replace(new RegExp(ddd[0], 'g'), ddd[day])
+
+ format = format.replace(new RegExp(MMMM[0], 'g'), MMMM[M])
+ format = format.replace(new RegExp(MMM[0], 'g'), MMM[M])
+
+ format = format.replace(/\\(.)/g, '$1')
+
+ return format
+}
+
+export function rand (randgen, min, max) {
+ return parseInt(randgen() * (max - min + 1), 10) + min
+}
+
+export function removeStr (arr, str) {
+ let index = arr.indexOf(str)
+
+ if (index > -1) {
+ arr.splice(index, 1)
+ return arr
+ }
+
+ return arr
+}
+
+export function grep (items, callback) {
+ let filtered = []
+ for (let i in items) {
+ let item = items[i]
+ let cond = callback(item)
+ if (cond) {
+ filtered.push(item)
+ }
+ }
+
+ return filtered
+}
+
+export function match (word, array) {
+ return grep(
+ array,
+ function (w) {
+ return w.toLowerCase().indexOf(word.toLowerCase()) === 0
+ }
+ )
+}
+
+export function serialize (obj) {
+ let str = []
+
+ for (let p in obj) {
+ if (obj.hasOwnProperty(p)) {
+ str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]))
+ }
+ }
+
+ return str.join('&')
+}
+
+export function removeClass (element, cl) {
+ let classList = element.className.split(' ')
+
+ if (classList.indexOf(cl) !== -1) {
+ classList.splice(classList.indexOf(cl), 1)
+ }
+
+ element.className = classList.join(' ')
+}
+
+export function addClass (element, cl) {
+ let classList = element.className.split(' ')
+
+ if (classList.indexOf(cl) !== -1) {
+ return
+ }
+
+ classList.push(cl)
+ element.className = classList.join(' ')
+}
+
+export function toggleClass (element, cl) {
+ let classList = element.className.split(' ')
+ if (classList.indexOf(cl) !== -1) {
+ removeClass(element, cl)
+ } else {
+ addClass(element, cl)
+ }
+}
+
+export function objectGetKey (obj, value) {
+ let key = null
+ for (let f in obj) {
+ if (obj[f] === value) {
+ key = f
+ }
+ }
+ return key
+}
diff --git a/server/config.js b/src/server/config.js
similarity index 100%
rename from server/config.js
rename to src/server/config.js
diff --git a/teemant.js b/src/server/index.js
old mode 100755
new mode 100644
similarity index 90%
rename from teemant.js
rename to src/server/index.js
index 93c21ef..757ecda
--- a/teemant.js
+++ b/src/server/index.js
@@ -1,20 +1,19 @@
-#!/usr/bin/env node
'use strict'
import express from 'express'
import path from 'path'
import sockio from 'socket.io'
import dns from 'dns'
-import pkginfo from './package.json'
-import irclib from './server/irc'
-import webirc from './server/webirc'
+import pkginfo from '../package.json'
+import irclib from './irc'
+import webirc from './webirc'
-import config from './server/config'
-import logger from './server/logger'
+import config from './config'
+import logger from './logger'
const app = express()
const router = express.Router()
-const pubdir = path.join(__dirname, 'build')
+const pubdir = path.join(__dirname, 'public')
const port = config.server.port || 8080
const cacheAge = 365 * 24 * 60 * 60 * 1000
@@ -36,16 +35,16 @@ let customCTCPs = {
process.stdin.resume()
router.get('/', function (req, res) {
- res.sendFile(path.join(pubdir, '/document/index.html'))
+ res.sendFile(path.join(pubdir, '/index.html'))
})
router.get('/:server?*', function (req, res) {
- res.sendFile(path.join(pubdir, '/document/index.html'))
+ res.sendFile(path.join(pubdir, '/index.html'))
})
app.use('/', express.static(pubdir, { maxAge: cacheAge }))
app.use('/', express.static(path.join(pubdir, 'icons'), { maxAge: cacheAge }))
-app.use('/', express.static(path.join(__dirname, 'static'), { maxAge: cacheAge }))
+app.use('/', express.static(path.join(pubdir, 'static'), { maxAge: cacheAge }))
app.use('/:server', express.static(pubdir, { maxAge: cacheAge }))
app.use('/:server', express.static(path.join(pubdir, 'icons'), { maxAge: cacheAge }))
@@ -116,7 +115,7 @@ io.sockets.on('connection', function (socket) {
delete connections[socket.id]
- logger.debugLog('clientID: {0} disconnect'.format(socket.id))
+ logger.debugLog(`clientID: ${socket.id} disconnect`)
})
socket.on('error', (e) => {
@@ -130,7 +129,12 @@ io.sockets.on('connection', function (socket) {
logger.debugLog(`[${socket.id}] ->`, data)
- serv.handler.handleUserLine(data)
+ try {
+ serv.handler.handleUserLine(data)
+ } catch (e) {
+ console.error('An error occured while handling message from client', data)
+ console.error(e.stack)
+ }
})
socket.on('irc_create', function (connectiondata) {
diff --git a/server/irc/index.js b/src/server/irc/index.js
similarity index 100%
rename from server/irc/index.js
rename to src/server/irc/index.js
diff --git a/server/irc/irc.js b/src/server/irc/irc.js
similarity index 96%
rename from server/irc/irc.js
rename to src/server/irc/irc.js
index 9d99f0e..50f3bde 100644
--- a/server/irc/irc.js
+++ b/src/server/irc/irc.js
@@ -471,7 +471,7 @@ class IRCConnectionHandler {
// start whois queue
list = {
nickname: line.arguments[1],
- hostmask: '%s!%s@%s'.format(line.arguments[1], line.arguments[2], line.arguments[3]),
+ hostmask: util.format('%s!%s@%s', line.arguments[1], line.arguments[2], line.arguments[3]),
realname: line.trailing || ''
}
this.whoisManage(line.arguments[1], list)
@@ -652,7 +652,7 @@ class IRCConnection extends EventEmitter {
buffer = data.pop()
data.forEach((line) => {
if (line.indexOf('PING') === 0) {
- this.socket.write('PONG %s\r\n', line.substring(4))
+ this.write('PONG %s\r\n', line.substring(4))
return
}
@@ -660,7 +660,13 @@ class IRCConnection extends EventEmitter {
let parsed = parse(line)
this.emit('line', parsed)
- this.handler.handleServerLine(parsed)
+
+ try {
+ this.handler.handleServerLine(parsed)
+ } catch (e) {
+ console.error('An error occured while handling parsed server line', parsed)
+ console.error(e.stack)
+ }
})
})
@@ -676,7 +682,7 @@ class IRCConnection extends EventEmitter {
authenticate () {
if (this.config.password) {
- this.socket.write('PASS %s\r\n', this.config.password)
+ this.write('PASS %s\r\n', this.config.password)
}
if (this.extras.authenticationSteps) {
@@ -686,8 +692,8 @@ class IRCConnection extends EventEmitter {
}
}
- this.socket.write('USER %s 8 * :%s\r\n', this.config.username, this.config.realname)
- this.socket.write('NICK %s\r\n', this.config.nickname)
+ this.write('USER %s 8 * :%s\r\n', this.config.username, this.config.realname)
+ this.write('NICK %s\r\n', this.config.nickname)
}
disconnect (message) {
@@ -697,7 +703,7 @@ class IRCConnection extends EventEmitter {
}
this.queue['close'] = true
- this.socket.write('QUIT :%s\r\n', (message != null ? message : this.globalConfig.default_quit_msg))
+ this.write('QUIT :%s\r\n', (message != null ? message : this.globalConfig.default_quit_msg))
}
write () {
diff --git a/server/irc/parser.js b/src/server/irc/parser.js
similarity index 100%
rename from server/irc/parser.js
rename to src/server/irc/parser.js
diff --git a/server/logger.js b/src/server/logger.js
similarity index 100%
rename from server/logger.js
rename to src/server/logger.js
diff --git a/server/webirc.js b/src/server/webirc.js
similarity index 97%
rename from server/webirc.js
rename to src/server/webirc.js
index cd7fcd4..dd9498e 100644
--- a/server/webirc.js
+++ b/src/server/webirc.js
@@ -2,8 +2,8 @@ import dns from 'dns'
import fs from 'fs'
import path from 'path'
-import config from './server/config'
-import logger from './server/logger'
+import config from './config'
+import logger from './logger'
const webircDataPath = path.join(__dirname, '..', 'webirc.data.json')
diff --git a/src/style/layout.styl b/src/style/layout.styl
index daaee99..882f8f6 100644
--- a/src/style/layout.styl
+++ b/src/style/layout.styl
@@ -181,7 +181,7 @@ body
margin-left: 4px;
border-radius: 5px;
vertical-align: bottom;
- .emojione
+ .emoji
width: 20px;
height: 20px;
vertical-align: sub;
diff --git a/webpack.config.js b/webpack.config.js
index 59ca256..f70e360 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -2,13 +2,14 @@
const webpack = require('webpack')
const path = require('path')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
entry: {
main: './src/js/main'
},
output: {
- path: path.join(__dirname, 'dist', 'js'),
+ path: path.join(__dirname, 'app', 'public'),
filename: '[name].js'
},
module: {
@@ -22,10 +23,6 @@ module.exports = {
presets: [ '@babel/preset-env' ]
}
}
- },
- {
- test: /src\/style\/.+\.styl$/,
- loader: 'file-loader?name=./dist/style/[name].css!css-loader!stylus-loader'
}
]
},
@@ -33,7 +30,15 @@ module.exports = {
new webpack.ProvidePlugin({
// Detect and inject
_: 'underscore'
- })
+ }),
+ new CopyWebpackPlugin([{
+ from: 'src/document/index.html',
+ to: '.'
+ },
+ {
+ from: 'static',
+ to: 'static'
+ }])
],
devtool: 'inline-source-map'
}