Skip to content

Commit

Permalink
feat: derive calls to telegram api and replies #15
Browse files Browse the repository at this point in the history
  • Loading branch information
bondiano committed Jun 22, 2024
1 parent afa0f42 commit db27c65
Show file tree
Hide file tree
Showing 20 changed files with 416 additions and 363 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# telega
# Telega

[![Package Version](https://img.shields.io/hexpm/v/telega)](https://hex.pm/packages/telega)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/telega/)

A [Gleam](https://gleam.run/) library for the Telegram Bot API.

## It provides:
## It provides

- an interface to the Telegram Bot HTTP-based APIs `telega/api`
- adapter to use with [wisp](https://github.com/gleam-wisp/wisp)
Expand Down Expand Up @@ -35,7 +35,7 @@ import gleam/result
import mist
import telega
import telega/adapters/wisp as telega_wisp
import telega/api as telega_api
import telega/reply
import telega/update.{CommandUpdate, TextUpdate}
import wisp
Expand All @@ -48,8 +48,8 @@ fn echo_handler(ctx) {
use <- telega.log_context(ctx, "echo")
case ctx.update {
TextUpdate(text: text, ..) -> telega_api.reply(ctx, text)
CommandUpdate(command: command, ..) -> telega_api.reply(ctx, command.text)
TextUpdate(text: text, ..) -> reply.with_text(ctx, text)
CommandUpdate(command: command, ..) -> reply.with_text(ctx, command.text)
_ -> Error("No text message")
}
|> result.map(fn(_) { Nil })
Expand Down
5 changes: 2 additions & 3 deletions examples/00-echo-bot/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ description = "A Telega Echo Bot example"

[dependencies]
gleam_stdlib = "~> 0.34 or ~> 1.0"
mist = "~> 0.17"
mist = "~> 1.2.0"
gleam_erlang = "~> 0.25"
wisp = "~> 0.12"
dotenv_gleam = "~> 1.0"
wisp = "~> 0.14"
telega = { path = "../.." }

[dev-dependencies]
Expand Down
6 changes: 3 additions & 3 deletions examples/00-echo-bot/src/bot.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import gleam/result
import mist
import telega
import telega/adapters/wisp as telega_wisp
import telega/api as telega_api
import telega/reply
import telega/update.{CommandUpdate, TextUpdate}
import wisp

Expand All @@ -17,8 +17,8 @@ fn echo_handler(ctx) {
use <- telega.log_context(ctx, "echo")

case ctx.update {
TextUpdate(text: text, ..) -> telega_api.reply(ctx, text)
CommandUpdate(command: command, ..) -> telega_api.reply(ctx, command.text)
TextUpdate(text: text, ..) -> reply.with_text(ctx, text)
CommandUpdate(command: command, ..) -> reply.with_text(ctx, command.text)
_ -> Error("No text message")
}
|> result.map(fn(_) { Nil })
Expand Down
6 changes: 3 additions & 3 deletions examples/01-commands-bot/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ description = "A Telega Commands example"

[dependencies]
gleam_stdlib = "~> 0.34 or ~> 1.0"
mist = "~> 0.17"
mist = "~> 1.2.0"
gleam_erlang = "~> 0.25"
wisp = "~> 0.12"
dotenv_gleam = "~> 1.0"
wisp = "~> 0.14"
dotenv_gleam = "1.0.5"
telega = { path = "../.." }

[dev-dependencies]
Expand Down
7 changes: 4 additions & 3 deletions examples/01-commands-bot/src/bot.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import telega/adapters/wisp as telega_wisp
import telega/api as telega_api
import telega/bot.{type Context}
import telega/model as telega_model
import telega/reply
import wisp.{type Request, type Response}

type Bot =
Expand Down Expand Up @@ -42,20 +43,20 @@ fn handle_request(bot: Bot, req: Request) -> Response {
fn dice_command_handler(ctx: NilContext, _) -> Result(Nil, String) {
use <- telega.log_context(ctx, "dice")

telega_api.send_dice(ctx, None)
reply.with_dice(ctx, None)
|> result.map(fn(_) { Nil })
}

fn start_command_handler(ctx: NilContext, _) -> Result(Nil, String) {
use <- telega.log_context(ctx, "start")

telega_api.set_my_commands(
ctx.config,
ctx.config.api,
telega_model.bot_commands_from([#("/dice", "Roll a dice")]),
None,
)
|> result.then(fn(_) {
telega_api.reply(
reply.with_text(
ctx,
"Hello! I'm a dice bot. You can roll a dice by sending /dice command.",
)
Expand Down
6 changes: 3 additions & 3 deletions examples/02-session-bot/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ description = "A Telega Session example"

[dependencies]
gleam_stdlib = "~> 0.34 or ~> 1.0"
mist = "~> 0.17"
mist = "~> 1.2.0"
gleam_erlang = "~> 0.25"
wisp = "~> 0.12"
dotenv_gleam = "~> 1.0"
wisp = "~> 0.14"
dotenv_gleam = "1.0.5"
telega = { path = "../.." }
carpenter = "~> 0.3.1"

Expand Down
11 changes: 6 additions & 5 deletions examples/02-session-bot/src/bot.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import telega/adapters/wisp as telega_wisp
import telega/api as telega_api
import telega/bot.{type Context}
import telega/model as telega_model
import telega/reply
import wisp.{type Response}

type BotContext =
Expand Down Expand Up @@ -41,7 +42,7 @@ fn set_name_command_handler(
use <- bool.guard(ctx.session.state != WaitName, Ok(ctx.session))
use <- telega.log_context(ctx, "set_name command")

telega_api.reply(ctx, "What's your name?")
reply.with_text(ctx, "What's your name?")
|> result.map(fn(_) { NameBotSession(name: ctx.session.name, state: SetName) })
}

Expand All @@ -52,7 +53,7 @@ fn set_name_message_handler(
use <- bool.guard(ctx.session.state != SetName, Ok(ctx.session))
use <- telega.log_context(ctx, "set_name")

telega_api.reply(ctx, "Your name is: " <> name <> " set!")
reply.with_text(ctx, "Your name is: " <> name <> " set!")
|> result.map(fn(_) { NameBotSession(name: name, state: WaitName) })
}

Expand All @@ -62,23 +63,23 @@ fn get_name_command_handler(
) -> Result(NameBotSession, String) {
use <- telega.log_context(ctx, "get_name command")

telega_api.reply(ctx, "Your name is: " <> ctx.session.name)
reply.with_text(ctx, "Your name is: " <> ctx.session.name)
|> result.map(fn(_) { ctx.session })
}

fn start_command_handler(ctx, _) -> Result(NameBotSession, String) {
use <- telega.log_context(ctx, "start")

telega_api.set_my_commands(
ctx.config,
ctx.config.api,
telega_model.bot_commands_from([
#("/set_name", "Set name"),
#("/get_name", "Get name"),
]),
None,
)
|> result.then(fn(_) {
telega_api.reply(
reply.with_text(
ctx,
"Hello! I'm a Name bot. You can set your name with /set_name command.",
)
Expand Down
2 changes: 1 addition & 1 deletion examples/03-conversation-bot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ gleam run # Run the server
gleam test # Run the tests
```

This is an example of a simple Session bot using the Telega library.
This is an example of a simple Conversation bot using the Telega library.
6 changes: 3 additions & 3 deletions examples/03-conversation-bot/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ description = "A Telega Session example"

[dependencies]
gleam_stdlib = "~> 0.34 or ~> 1.0"
mist = "~> 0.17"
mist = "~> 1.2.0"
gleam_erlang = "~> 0.25"
wisp = "~> 0.12"
dotenv_gleam = "~> 1.0"
wisp = "~> 0.14"
dotenv_gleam = "1.0.5"
telega = { path = "../.." }
carpenter = "~> 0.3.1"

Expand Down
11 changes: 6 additions & 5 deletions examples/03-conversation-bot/src/bot.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import telega/adapters/wisp as telega_wisp
import telega/api as telega_api
import telega/bot.{type Context}
import telega/model as telega_model
import telega/reply
import wisp.{type Response}

type BotContext =
Expand Down Expand Up @@ -38,9 +39,9 @@ fn set_name_command_handler(
_,
) -> Result(NameBotSession, String) {
use <- telega.log_context(ctx, "set_name command")
use _ <- result.try(telega_api.reply(ctx, "What's your name?"))
use _ <- result.try(reply.with_text(ctx, "What's your name?"))
use ctx, name <- telega.wait_text(ctx)
use _ <- result.try(telega_api.reply(ctx, "Your name is: " <> name <> " set!"))
use _ <- result.try(reply.with_text(ctx, "Your name is: " <> name <> " set!"))

Ok(NameBotSession(name: name))
}
Expand All @@ -51,23 +52,23 @@ fn get_name_command_handler(
) -> Result(NameBotSession, String) {
use <- telega.log_context(ctx, "get_name command")

telega_api.reply(ctx, "Your name is: " <> ctx.session.name)
reply.with_text(ctx, "Your name is: " <> ctx.session.name)
|> result.map(fn(_) { ctx.session })
}

fn start_command_handler(ctx, _) -> Result(NameBotSession, String) {
use <- telega.log_context(ctx, "start")

telega_api.set_my_commands(
ctx.config,
ctx.config.api,
telega_model.bot_commands_from([
#("/set_name", "Set name"),
#("/get_name", "Get name"),
]),
None,
)
|> result.then(fn(_) {
telega_api.reply(
reply.with_text(
ctx,
"Hello! I'm a Name bot. You can set your name with /set_name command.",
)
Expand Down
4 changes: 2 additions & 2 deletions examples/04-keyboard-bot/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Telega Conversation Bot
# Telega Bot With Keyboard

```sh
gleam run # Run the server
gleam test # Run the tests
```

This is an example of a simple Session bot using the Telega library.
This is an example of a simple bot with keyboard using the Telega library.
6 changes: 3 additions & 3 deletions examples/04-keyboard-bot/gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ description = "A Telega Session example"

[dependencies]
gleam_stdlib = "~> 0.34 or ~> 1.0"
mist = "~> 0.17"
mist = "~> 1.2.0"
gleam_erlang = "~> 0.25"
wisp = "~> 0.12"
dotenv_gleam = "~> 1.0"
wisp = "~> 0.14"
dotenv_gleam = "1.0.5"
telega = { path = "../.." }
carpenter = "~> 0.3.1"

Expand Down
18 changes: 8 additions & 10 deletions examples/04-keyboard-bot/src/bot.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import telega/api as telega_api
import telega/bot.{type Context}
import telega/keyboard as telega_keyboard
import telega/model.{EditMessageTextParameters, Stringed} as telega_model
import telega/reply
import wisp.{type Response}

type BotContext =
Expand Down Expand Up @@ -66,18 +67,15 @@ fn change_languages_keyboard(

let language = ctx.session.lang
let keyboard = language_keyboard.new_keyboard(language)
use _ <- result.try(telega_api.reply_with_markup(
use _ <- result.try(reply.with_markup(
ctx,
t_change_language_message(language),
telega_keyboard.build(keyboard),
))

use _, text <- telega.wait_hears(ctx, telega_keyboard.hear(keyboard))
let language = language_keyboard.option_to_language(text)
use _ <- result.try(telega_api.reply(
ctx,
t_language_changed_message(language),
))
use _ <- result.try(reply.with_text(ctx, t_language_changed_message(language)))
Ok(LanguageBotSession(language))
}

Expand All @@ -90,7 +88,7 @@ fn handle_inline_change_language(
let language = ctx.session.lang
let callback_data = language_keyboard.build_keyboard_callback_data()
let keyboard = language_keyboard.new_inline_keyboard(language, callback_data)
use message <- result.try(telega_api.reply_with_markup(
use message <- result.try(reply.with_markup(
ctx,
t_change_language_message(language),
telega_keyboard.build_inline(keyboard),
Expand All @@ -106,12 +104,12 @@ fn handle_inline_change_language(

let language = language_callback.data

use _ <- result.try(telega_api.answer_callback_query(
use _ <- result.try(reply.answer_callback_query(
ctx,
telega_model.new_answer_callback_query_parameters(callback_query_id),
))

use _ <- result.try(telega_api.edit_message_text(
use _ <- result.try(reply.edit_message_text(
ctx,
EditMessageTextParameters(
..telega_model.default_edit_message_text_parameters(),
Expand All @@ -131,15 +129,15 @@ fn start_command_handler(
use <- telega.log_context(ctx, "start")

telega_api.set_my_commands(
ctx.config,
ctx.config.api,
telega_model.bot_commands_from([
#("/lang", "Shows custom keyboard with languages"),
#("/lang_inline", "Change language inline"),
]),
None,
)
|> result.then(fn(_) {
telega_api.reply(ctx, t_welcome_message(ctx.session.lang))
reply.with_text(ctx, t_welcome_message(ctx.session.lang))
|> result.map(fn(_) { ctx.session })
})
}
Expand Down
9 changes: 4 additions & 5 deletions src/telega.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import gleam/otp/actor
import gleam/otp/supervisor
import gleam/result
import gleam/string
import telega/api
import telega/bot.{
type CallbackQueryFilter, type Context, type Handler, type Hears,
type RegistryMessage, type SessionSettings, CallbackQueryFilter, Context,
HandleAll, HandleBotRegistryMessage, HandleCallbackQuery, HandleCommand,
HandleCommands, HandleHears, HandleText, SessionSettings,
}
import telega/config.{type Config}
import telega/internal/config.{type Config}
import telega/log
import telega/update.{type Command, type Update}

Expand All @@ -33,14 +32,14 @@ pub opaque type TelegaBuilder(session) {
///
/// Usefull if you plan to implement own adapter.
pub fn is_webhook_path(telega: Telega(session), path: String) -> Bool {
config.get_webhook_path(telega.config) == path
telega.config.webhook_path == path
}

/// Check if a secret token is valid.
///
/// Usefull if you plan to implement own adapter.
pub fn is_secret_token_valid(telega: Telega(session), token: String) -> Bool {
config.get_secret_token(telega.config) == token
telega.config.secret_token == token
}

/// Create a new Telega instance.
Expand Down Expand Up @@ -261,7 +260,7 @@ pub fn init_nil_session(
/// It will set the webhook and start the `Registry`.
pub fn init(builder: TelegaBuilder(session)) -> Result(Telega(session), String) {
let TelegaBuilder(telega) = builder
use is_ok <- result.try(api.set_webhook(telega.config))
use is_ok <- result.try(bot.set_webhook(telega.config))
use <- bool.guard(!is_ok, Error("Failed to set webhook"))

let session_settings =
Expand Down
Loading

0 comments on commit db27c65

Please sign in to comment.