Created
January 24, 2019 23:55
-
-
Save daGrevis/897fed9d78f8f22ae76cf74a82496953 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/backend/package.json b/backend/package.json | |
| index 21a1462..166172c 100644 | |
| --- a/backend/package.json | |
| +++ b/backend/package.json | |
| @@ -9,6 +9,7 @@ | |
| "prettier": "^1.14.3" | |
| }, | |
| "dependencies": { | |
| + "@koa/cors": "^2.2.3", | |
| "bcrypt": "^3.0.0", | |
| "bluebird": "^3.5.1", | |
| "chalk": "^2.4.1", | |
| diff --git a/backend/src/irc/commands/index.js b/backend/src/irc/commands/index.js | |
| index bbb3e2e..722e99d 100644 | |
| --- a/backend/src/irc/commands/index.js | |
| +++ b/backend/src/irc/commands/index.js | |
| @@ -34,10 +34,13 @@ const getCommand = (connection, payload) => { | |
| return {} | |
| } | |
| - const isPrivateMessage = payload.target === connection.nick | |
| + const isSentToMe = payload.target === connection.nick | |
| - // Require to prefix command unless it's a private message or command is addressed to me. | |
| - if (!hasCommandPrefix && !isPrivateMessage && !isAddressedToMe) { | |
| + if (hasCommandPrefix && isAddressedToMe) { | |
| + return {} | |
| + } | |
| + | |
| + if (!hasCommandPrefix && !isAddressedToMe && !isSentToMe) { | |
| return {} | |
| } | |
| diff --git a/backend/src/irc/commands/index.test.js b/backend/src/irc/commands/index.test.js | |
| index 5033fc9..3e324ac 100644 | |
| --- a/backend/src/irc/commands/index.test.js | |
| +++ b/backend/src/irc/commands/index.test.js | |
| @@ -30,16 +30,15 @@ describe('command parsing', () => { | |
| itWillPong({ message: ',ping' }) | |
| itWillPong({ message: 'msks, ping' }) | |
| itWillPong({ message: 'msks: ping' }) | |
| - itWillPong({ message: 'msks, !ping' }) | |
| - itWillPong({ message: 'msks, ,ping' }) | |
| itWillPong({ message: 'msks, ping' }) | |
| - itWillPong({ message: 'msks, !ping' }) | |
| itWillPong({ message: 'ping', target: 'msks' }) | |
| itWontPong({ message: 'hello' }) | |
| itWontPong({ message: 'pls ping' }) | |
| itWontPong({ message: 'sudo !ping' }) | |
| itWontPong({ message: 'pingerino' }) | |
| + itWontPong({ message: 'msks, !ping' }) | |
| + itWontPong({ message: 'msks, ,ping' }) | |
| itWontPong({ message: 'msks,!ping' }) | |
| itWontPong({ message: 'msks,ping' }) | |
| itWontPong({ message: 'msks,,ping' }) | |
| diff --git a/backend/src/irc/events/bot.js b/backend/src/irc/events/bot.js | |
| index 8e9e7b3..a9af88d 100644 | |
| --- a/backend/src/irc/events/bot.js | |
| +++ b/backend/src/irc/events/bot.js | |
| @@ -90,6 +90,15 @@ const onMessage = async ({ payload, ircClient, connection, NOW }) => { | |
| }) | |
| } | |
| +const onKick = async ({ payload, ircClient, connection }) => { | |
| + if (!connection.isBot) { | |
| + return | |
| + } | |
| + | |
| + ircClient.join(payload.channel) | |
| +} | |
| + | |
| module.exports = { | |
| onMessage, | |
| + onKick, | |
| } | |
| diff --git a/backend/src/irc/events/connection.js b/backend/src/irc/events/connection.js | |
| index f576acf..82850ae 100644 | |
| --- a/backend/src/irc/events/connection.js | |
| +++ b/backend/src/irc/events/connection.js | |
| @@ -17,7 +17,6 @@ const { | |
| setJoinedIrcChannel, | |
| unsetJoinedIrcChannel, | |
| } = require('../../store/actions') | |
| -const { updateConnection } = require('../../postgres/queries/connections') | |
| const { | |
| createChannel, | |
| updateChannel, | |
| @@ -70,20 +69,6 @@ const onConnected = async ({ connection, ircClient, NOW }) => { | |
| }), | |
| ) | |
| - if (!connection.autoConnect) { | |
| - // Enable autoConnect when connected. | |
| - connection = await updateConnection( | |
| - { id: connection.id }, | |
| - { autoConnect: true }, | |
| - ) | |
| - store.dispatch( | |
| - syncPostgres({ | |
| - table: 'connections', | |
| - change: { next: connection }, | |
| - }), | |
| - ) | |
| - } | |
| - | |
| broadcastConnection({ | |
| next: connection, | |
| }) | |
| @@ -319,25 +304,6 @@ const onKick = async ({ payload, connection }) => { | |
| }) | |
| } | |
| -const onQuit = async ({ payload, connection }) => { | |
| - if (payload.nick !== connection.nick) { | |
| - return | |
| - } | |
| - | |
| - connection = await updateConnection( | |
| - { id: connection.id }, | |
| - { autoConnect: false }, | |
| - ) | |
| - store.dispatch( | |
| - syncPostgres({ | |
| - table: 'connections', | |
| - change: { next: connection }, | |
| - }), | |
| - ) | |
| - | |
| - // No point in broadcasting autoConnect because onSocketClose will get called soon after. | |
| -} | |
| - | |
| const onNick = async ({ payload, connection }) => { | |
| if (payload.nick !== connection.nick) { | |
| return | |
| @@ -363,7 +329,6 @@ module.exports = { | |
| onJoin, | |
| onPart, | |
| onKick, | |
| - onQuit, | |
| // onNick, | |
| // onNickInUse, | |
| // onNickInvalid, | |
| diff --git a/backend/src/server/index.js b/backend/src/server/index.js | |
| index e1c25e2..d926a02 100644 | |
| --- a/backend/src/server/index.js | |
| +++ b/backend/src/server/index.js | |
| @@ -1,12 +1,14 @@ | |
| const http = require('http') | |
| const Koa = require('koa') | |
| +const koaCors = require('@koa/cors') | |
| const koaBody = require('koa-body') | |
| const KoaRouter = require('koa-router') | |
| const koaMount = require('koa-mount') | |
| const koaSend = require('koa-send') | |
| const koaStatic = require('koa-static') | |
| +const config = require('../env/config') | |
| const withLogger = require('./middlewares/withLogger') | |
| const withSession = require('./middlewares/withSession') | |
| const messagesRouter = require('./routes/messages') | |
| @@ -20,6 +22,10 @@ const socket = require('./socket') | |
| const koa = new Koa() | |
| +if (config.http.cors) { | |
| + koa.use(koaCors(config.http.cors)) | |
| +} | |
| + | |
| koa.use(koaBody()) | |
| koa.use(withLogger()) | |
| diff --git a/backend/src/server/routes/commands.js b/backend/src/server/routes/commands.js | |
| index 50b433b..fc7ce5f 100644 | |
| --- a/backend/src/server/routes/commands.js | |
| +++ b/backend/src/server/routes/commands.js | |
| @@ -2,6 +2,8 @@ const fp = require('lodash/fp') | |
| const KoaRouter = require('koa-router') | |
| const HttpStatus = require('http-status-codes') | |
| +const store = require('../../store') | |
| +const { syncPostgres } = require('../../store/actions') | |
| const withParamRequired = require('../middlewares/withParamRequired') | |
| const withAuthenticated = require('../middlewares/withAuthenticated') | |
| const withConnection = require('../middlewares/withConnection') | |
| @@ -9,7 +11,7 @@ const withIrcClient = require('../middlewares/withIrcClient') | |
| const withChannel = require('../middlewares/withChannel') | |
| const say = require('../../irc/say') | |
| const connect = require('../../irc/connect') | |
| -const store = require('../../store') | |
| +const { updateConnection } = require('../../postgres/queries/connections') | |
| const router = new KoaRouter() | |
| @@ -141,7 +143,18 @@ router.post('/connect', withAuthenticated, withConnection, async ctx => { | |
| return | |
| } | |
| - connect(connection) | |
| + const nextConnection = await updateConnection( | |
| + { id: connection.id }, | |
| + { autoConnect: true }, | |
| + ) | |
| + store.dispatch( | |
| + syncPostgres({ | |
| + table: 'connections', | |
| + change: { next: nextConnection }, | |
| + }), | |
| + ) | |
| + | |
| + connect(nextConnection) | |
| ctx.body = {} | |
| }) | |
| @@ -152,10 +165,21 @@ router.post( | |
| withConnection, | |
| withIrcClient, | |
| async ctx => { | |
| - const { ircClient } = ctx | |
| + const { ircClient, connection } = ctx | |
| ircClient.quit() | |
| + const nextConnection = await updateConnection( | |
| + { id: connection.id }, | |
| + { autoConnect: false }, | |
| + ) | |
| + store.dispatch( | |
| + syncPostgres({ | |
| + table: 'connections', | |
| + change: { next: nextConnection }, | |
| + }), | |
| + ) | |
| + | |
| ctx.body = {} | |
| }, | |
| ) | |
| diff --git a/backend/yarn.lock b/backend/yarn.lock | |
| index 5fbedbf..946788c 100644 | |
| --- a/backend/yarn.lock | |
| +++ b/backend/yarn.lock | |
| @@ -23,6 +23,13 @@ | |
| resolved "https://registry.yarnpkg.com/@blakeembrey/deque/-/deque-1.0.3.tgz#f83871859441ba4ad9997fca5a3050dcfd9e2363" | |
| integrity sha512-w6e4y0QqbPMZJrvZZQ4vP/4yxdsnG3Kr5J3isq6neMrqwo32vGk/LyGMGN9y79XP0wR8UuGROILhTsg5NnhCAw== | |
| +"@koa/cors@^2.2.3": | |
| + version "2.2.3" | |
| + resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-2.2.3.tgz#c32a9907acbee1e72fedfb0b9ac840d2e6f9be57" | |
| + integrity sha512-tCVVXa39ETsit5kGBtEWWimjLn1sDaeu8+0phgb8kT3GmBDZOykkI3ZO8nMjV2p3MGkJI4K5P+bxR8Ztq0bwsA== | |
| + dependencies: | |
| + vary "^1.1.2" | |
| + | |
| "@types/events@*": | |
| version "1.2.0" | |
| resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" | |
| @@ -5861,7 +5868,7 @@ validate-npm-package-license@^3.0.1: | |
| spdx-correct "^3.0.0" | |
| spdx-expression-parse "^3.0.0" | |
| -vary@^1.0.0: | |
| +vary@^1.0.0, vary@^1.1.2: | |
| version "1.1.2" | |
| resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" | |
| integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= | |
| diff --git a/config.example.toml b/config.example.toml | |
| index a7a7730..864d4d3 100644 | |
| --- a/config.example.toml | |
| +++ b/config.example.toml | |
| @@ -22,3 +22,4 @@ rateLimit = [5, 60000] | |
| port = 3001 | |
| clientPath = '../client/build' | |
| # clientPath = { msks = "/srv/msks", developerslv = "/srv/developerslv" } | |
| +# cors = '*' | |
| diff --git a/frontend/src/components/MessageInput.js b/frontend/src/components/MessageInput.js | |
| index 3dcf792..d9df9bf 100644 | |
| --- a/frontend/src/components/MessageInput.js | |
| +++ b/frontend/src/components/MessageInput.js | |
| @@ -21,6 +21,7 @@ class MessageInput extends React.Component { | |
| state = { | |
| text: '', | |
| + prevText: '', | |
| } | |
| onDocumentKeyDown = ev => { | |
| @@ -121,7 +122,7 @@ class MessageInput extends React.Component { | |
| render() { | |
| const { connection, channel, isDisabled } = this.props | |
| - const { text } = this.state | |
| + const { text, prevText } = this.state | |
| const isCommand = fp.startsWith('/', text) && !fp.startsWith('//', text) | |
| @@ -144,7 +145,18 @@ class MessageInput extends React.Component { | |
| onKeyDown={ev => { | |
| const { value } = this.textNode | |
| - if (ev.key === 'Tab') { | |
| + const isPrevTextCompletion = ev.key === 'ArrowUp' && prevText | |
| + const isTabCompletion = ev.key === 'Tab' | |
| + const isSpaceCompletion = | |
| + ev.key === ' ' && value.slice(-1) === ' ' | |
| + | |
| + if (isPrevTextCompletion) { | |
| + ev.preventDefault() | |
| + | |
| + this.complete(this.textNode, prevText, prevText.length) | |
| + } | |
| + | |
| + if (isTabCompletion) { | |
| ev.preventDefault() | |
| const { nextValue, nextSelection } = this.findCompletion( | |
| @@ -152,7 +164,9 @@ class MessageInput extends React.Component { | |
| this.textNode.selectionStart, | |
| ) | |
| this.complete(this.textNode, nextValue, nextSelection) | |
| - } else if (value.slice(-1) === ' ' && ev.key === ' ') { | |
| + } | |
| + | |
| + if (isSpaceCompletion) { | |
| const { nextValue, nextSelection } = this.findCompletion( | |
| value.slice(0, -1), | |
| value.length - 1, | |
| @@ -172,7 +186,7 @@ class MessageInput extends React.Component { | |
| text, | |
| }) | |
| - this.setState({ text: '' }) | |
| + this.setState({ text: '', prevText: text }) | |
| } | |
| }} | |
| spellCheck={false} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment