Last active
February 3, 2021 21:00
-
-
Save negezor/ac802b1ebe1db639ecb6d967d74341f5 to your computer and use it in GitHub Desktop.
Command prototype using Composition API for vk-io
This file contains 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
const { VK } = require('vk-io'); | |
const { Commander, useMessage, useViewer, onEnter, ref, watch } = require('./core'); | |
const vk = new VK({ | |
token: '' | |
}); | |
const commander = new Commander(); | |
vk.updates.on('message_new', commander.middleware); | |
commander.addCommand({ | |
pattern: /^\/hello$/, | |
setup() { | |
const { viewer } = useViewer(); | |
const { send } = useMessage(); | |
onEnter(async () => { | |
await send(`Hello! Your user ID is ${viewer.value.id}`); | |
}); | |
} | |
}); | |
commander.addCommand({ | |
pattern: /^\/counter$/, | |
setup() { | |
const { send } = useMessage(); | |
const counter = ref(0); | |
watch(counter, async () => { | |
await send(`Counter ${counter.value}`); | |
}); | |
onEnter(async () => { | |
for (let i = 0; i < 3; i += 1) { | |
counter.value += 1; | |
await new Promise(resolve => setTimeout(resolve, 1000)); | |
} | |
}); | |
} | |
}); | |
vk.updates.start() | |
.then(() => { | |
console.log('Bot started'); | |
}) | |
.catch(console.error); |
This file contains 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
let currentInstance; | |
const setCurrentInstance = (instance) => { | |
currentInstance = instance; | |
}; | |
/** | |
* @return {{ | |
* message: import('vk-io').MessageContext | |
* }} | |
*/ | |
const getCurrentInstance = () => currentInstance; | |
const onChangeHooksSymbol = Symbol('onChangeHooks'); | |
const ref = (defaultValue) => { | |
/** | |
* @type {{ value: any }} | |
*/ | |
const internalRef = { | |
[onChangeHooksSymbol]: [] | |
}; | |
let internalValue = defaultValue; | |
Object.defineProperty(internalRef, 'value', { | |
get: () => internalValue, | |
set: (val) => { | |
internalValue = val; | |
for (const hook of internalRef[onChangeHooksSymbol]) { | |
hook(); | |
} | |
} | |
}); | |
return internalRef; | |
}; | |
const watch = (refLink, callback) => { | |
refLink[onChangeHooksSymbol].push(callback); | |
}; | |
const onEnter = (callback) => { | |
const instance = getCurrentInstance(); | |
instance.hooks.onEnter.push(callback); | |
}; | |
const onLeave = (callback) => { | |
const instance = getCurrentInstance(); | |
instance.hooks.onLeave.push(callback); | |
}; | |
const useMessage = () => { | |
const instance = getCurrentInstance(); | |
const senderId = ref(instance.message.senderId); | |
const text = ref(instance.message.text); | |
/** | |
* @type {import('vk-io').MessageContext['send']} | |
*/ | |
const send = instance.message.send.bind(instance.message); | |
return { send, senderId, text }; | |
}; | |
const users = new Map(); | |
const useViewer = () => { | |
const { senderId } = useMessage(); | |
const viewer = ref(null); | |
onEnter(async () => { | |
await new Promise(resolve => setTimeout(resolve, 250)); | |
viewer.value = users.get(senderId.value) || { | |
id: users.size + 1, | |
vkId: senderId.value, | |
balance: 0 | |
}; | |
}); | |
onLeave(async () => { | |
users.set(senderId.value, viewer.value); | |
}); | |
return { | |
viewer | |
}; | |
}; | |
class Commander { | |
commands = []; | |
addCommand(command) { | |
this.commands.push(command); | |
} | |
get middleware() { | |
return async (context) => { | |
const command = this.commands.find(item => ( | |
item.pattern.test(context.text) | |
)); | |
if (!command) { | |
await context.send('Command not found'); | |
return; | |
} | |
const instance = { | |
message: context, | |
hooks: { | |
onEnter: [], | |
onLeave: [] | |
} | |
}; | |
setCurrentInstance(instance); | |
command.setup(); | |
for (const hook of instance.hooks.onEnter) { | |
await hook(); | |
} | |
for (const hook of instance.hooks.onLeave) { | |
await hook(); | |
} | |
setCurrentInstance(undefined); | |
}; | |
} | |
} | |
module.exports = { | |
getCurrentInstance, | |
setCurrentInstance, | |
ref, | |
watch, | |
onEnter, | |
onLeave, | |
useMessage, | |
useViewer, | |
Commander | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment