a way to split long match blocks
phaux opened this issue · 0 comments
Is your feature request related to a problem? Please describe.
I'm making a telegram bot and the main part of it is a function like this (I'm not using any library, just typed jsons):
async function handleUpdate(update: TgUpdate) {
await match(update)
// bot added to group
.with({
my_chat_member: {
chat: { type: P.union("group", "supergroup") },
new_chat_member: { status: P.union("member", "administrator") },
},
}, async (update) => {
await handleGroupJoin(update.my_chat_member)
})
// command /set_threshold in group chat
.with({
message: {
text: P.string.startsWith("/set_threshold"),
entities: [{ type: "bot_command", offset: 0 }, ...P.array()],
chat: { type: P.union("group", "supergroup") },
},
}, async (update) => {
await handleSetThresholdCommand(update.message)
})
// reply to command /set_threshold
.with({
message: {
reply_to_message: {
text: P.string.includes("Tell me the threshold"),
from: { is_bot: true },
},
text: P.string,
},
}, async (update) => {
await handleSetThresholdReply(update.message)
})
// message_reaction
.with({
message_reaction: {
chat: { type: P.union("group", "supergroup", "channel") },
},
}, async (update) => {
await handleReaction(update.message_reaction)
})
// many more match arms later...
.otherwise(async () => { /* ignore */ })
}
Describe the solution you'd like
I wish there was a way to split the long match block into smaller parts. For example:
export const matchThresholdCommand = (match: _) => match
// command /set_threshold in group chat
.with({
...
}, async (update) => {
...
})
// reply to command /set_threshold
.with({
...
}, async (update) => {
...
})
async function handleUpdate(update: TgUpdate) {
await match(update)
.use(matchThresholdCommand)
.use(matchOtherCommand)
// etc
.otherwise(async () => { /* ignore */ })
}
#209 could improve the api further.
Describe alternatives you've considered
I can match the updates by their type first (all messages, replies, reactions, joins) and then do inner match for each (e.g. for messages, what command it contains), but I would like to split them based on what functionality they provide, not what type they are.
Additional context
I wonder if its possible without any changes to the library and only using the Match
type somehow? I tried it but couldn't get the types right:
async function handleUpdate(update: TgUpdate) {
await withBazCommand(withBarCommand(withFooCommand(match(update))))
.otherwise(async () => { /* ignore */ })
}
const withFooCommand = <_>(match: Match<_>): Match<_> => match
.with({...}, async (update) => {...})
.with({...}, async (update) => {...})
Maybe exporting some helper types for this use case would be enough.