Skip to content

Instantly share code, notes, and snippets.

@negezor
Last active February 3, 2021 21:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save negezor/ac802b1ebe1db639ecb6d967d74341f5 to your computer and use it in GitHub Desktop.
Save negezor/ac802b1ebe1db639ecb6d967d74341f5 to your computer and use it in GitHub Desktop.
Command prototype using Composition API for vk-io
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);
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