const Future = require('fluture')
class Sequencer {
constructor(fut) {
this._fut = fut
}
get future() {
return this._fut
}
promise() {
return this.future.promise()
}
}
class Message extends Sequencer {
static of(data) {
return new Message(Future.of(data))
}
// static chain(fut) {
// return new Message(fut.chain(Future.of))
// }
wrap(fut) {
return new Message(fut)
}
finish(logFn) {
if (logFn) {
this.future.fork(logFn, logFn)
}
else {
this.future.value(() => {})
}
}
catch(fn) {
return this.wrap(this.future.chain(fn))
}
// =====
adminRequired() {
return this.wrap(this.future.map(ctx => {
if (ctx.from.id !== 0) {
return new Error('Restricted')
}
}))
}
reply(text) {
return this.wrap(this.future.map(ctx => {
ctx.reply(text)
return ctx
}))
}
/**
* Resolves with Future with [result, ctx]
*/
then(fut) {
return this.wrap(
this.future.chain(ctx =>
fut.map(res => [res, ctx])
)
)
}
map(fn) {
return this.wrap(
this.future.map(fn)
)
}
chain(fn) {
return this.wrap(
this.future.chain(fn)
)
}
chainRej(fn) {
return this.wrap(
this.future.chainRej(fn)
)
}
}
class Photo {
constructor(id) {
this._id = id
}
static fetch(id) {
return Future.node(done => {
setTimeout(done, 300, new Photo(id))
})
}
}
class TelegrafDemo {
constructor() {
this._commands = []
}
/**
* @param {string} cmd
* @param {ctx => void} resolver
*/
command(cmd, resolver) {
this._commands.push({
cmd,
resolver,
})
}
startPolling() {
this._commands.forEach(({ cmd, resolver }) => {
const ctx = {
from: {
id: 1,
},
chat: {
id: 12,
},
reply(text) {
console.log('REPLY:', text, { to: ctx.from })
}
}
resolver(ctx)
})
}
}
// ===== App code ===== /
const debug = (...args) => console.log('DEBUG:', ...args)
const bot = new TelegrafDemo()
bot.command('/foo', (ctx) => {
Message.of(ctx)
.adminRequired()
.catch(reason =>
Message.of(ctx).reply(`Not allowed: ${reason.message}`).future
)
.then(Photo.fetch(123))
.chainRej((ctx) => {
console.log('sdsd', ctx)
return Future.of(null)
})
.finish(debug)
})
bot.startPolling()