mirror of
https://gitlab.com/slondr/BeerHolderBot.git
synced 2024-06-14 05:06:43 +00:00
Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
99dae44e60 | ||
|
d348b548c1 | ||
|
788dca687f | ||
|
60b2a78ecb | ||
|
ebea0b8aa1 | ||
|
04459d1bb6 | ||
|
dfa79f1dc1 | ||
|
6e8e428636 | ||
|
21f4a7dc85 | ||
|
f96a436afe | ||
|
29acc30833 | ||
|
2ec7fe50a9 | ||
|
43af2d2062 | ||
|
b1d0fb4505 | ||
|
ee8e05fedf | ||
|
18bff88dce | ||
|
0c174fc956 | ||
|
0c428aec87 | ||
|
bc9e778e15 | ||
|
b21a1b582e | ||
|
42add528a8 | ||
|
b102a3e6dc | ||
|
3a0161f525 | ||
|
5360eaedf7 | ||
|
993f224d65 | ||
|
aa45fa0081 | ||
|
ccea41fb50 | ||
|
98bc21291d | ||
|
7fa09426e9 | ||
|
ab04b8c56d | ||
|
37e0cb343c | ||
|
6636f38d1a | ||
|
f0e08e2e0e | ||
|
234420adc0 | ||
|
b85e473ab4 | ||
|
59005690eb | ||
|
cd093adb6e | ||
|
7d2b37fbe8 | ||
|
42988b2755 | ||
|
31680db976 | ||
|
a3d284f8c6 | ||
|
fa5a9dbccd | ||
|
22b50397f4 | ||
|
4ceffb6071 | ||
|
db9f6edfef | ||
|
459e58a478 | ||
|
0004a34d40 | ||
|
5ebedb4046 | ||
|
8812b3472c | ||
|
b0a1267872 | ||
|
645c6012b2 | ||
|
bb05bc4a31 | ||
|
89cc5822f9 | ||
|
d1ee2418de | ||
|
7a1e397958 | ||
|
82135166cd | ||
|
53e6fe9b6e | ||
|
6a69b51148 | ||
|
9880695fad | ||
|
aa3ae7b42e | ||
|
581c607cb6 | ||
|
faf492acbf | ||
|
2546759368 | ||
|
b8293dae47 | ||
|
59f9a1b696 | ||
|
4bedfb1b08 | ||
|
9398fe5217 | ||
|
84e5728d03 | ||
|
370fca7197 | ||
|
308845b949 | ||
|
f166ecf582 | ||
|
e74b2b4dbe | ||
|
9f5b939391 | ||
|
d9e6023a5c | ||
|
1393883077 | ||
|
c9f6a0f499 | ||
|
4a463aafd2 |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
/target
|
||||
token.gpg
|
||||
*.db
|
||||
nohup.out
|
||||
result.json
|
||||
|
|
|
@ -2,9 +2,46 @@ image: rust
|
|||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
build:
|
||||
stage: build
|
||||
cache:
|
||||
key: one-key-to-rule-them-all
|
||||
paths:
|
||||
- target
|
||||
script:
|
||||
- cargo build
|
||||
|
||||
lint:
|
||||
stage: test
|
||||
cache:
|
||||
key: one-key-to-rule-them-all
|
||||
paths:
|
||||
- target
|
||||
script:
|
||||
- rustup component add clippy
|
||||
- cargo clippy --all-targets --all-features
|
||||
|
||||
test:
|
||||
stage: test
|
||||
cache:
|
||||
key: one-key-to-rule-them-all
|
||||
paths:
|
||||
- target
|
||||
script:
|
||||
- cargo test
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
dependencies:
|
||||
- test
|
||||
script:
|
||||
- mkdir ~/.ssh
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_KEY" | ssh-add -
|
||||
- ssh-keyscan -H -t rsa ssh.api.ericlondres.tech >> ~/.ssh/known_hosts
|
||||
- ssh -t root@ssh.api.ericlondres.tech "cd /root/packages/bot/BeerHolderBot; git pull origin master; bash --login -c 'gpg --passphrase $GPG_PASS --decrypt secret.sh.gpg > secret.sh; source secret.sh; exit 0'"
|
||||
only:
|
||||
- master
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
* 0.3.8
|
||||
+ Responses to =/corn= commands are now embedded rather than posted as a link
|
||||
* 0.3.7
|
||||
+ Added =/yasd=
|
||||
+ Automate deployments
|
||||
+ Fix some style issues raised by Clippy
|
||||
* 0.3.6
|
||||
+ Added some deployment quality-of-life scripts
|
||||
* 0.3.5
|
||||
+ Added =/count=
|
||||
+ Beer count is now determined via SQL query instead of an incorrect in-memory counter
|
||||
* 0.3.4
|
||||
+ Implement new =/post= command which generates a new post via markov chain
|
||||
* 0.3.3
|
||||
+ Remove explicit dependency on teloxide-core, as this isn't needed
|
||||
* 0.3.2
|
||||
|
|
584
Cargo.lock
generated
584
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "BeerHolderBot"
|
||||
version = "0.3.3"
|
||||
version = "0.3.8"
|
||||
authors = ["Eric S. Londres <elondres@stevens.edu>"]
|
||||
edition = "2018"
|
||||
description = "A Telegram bot which holds your beer"
|
||||
|
@ -17,5 +17,7 @@ pretty_env_logger = "0.4"
|
|||
tokio = { version = "1.3", features = [ "rt-multi-thread", "macros" ] }
|
||||
lazy_static = "1.4.0"
|
||||
sqlite = "0.25.3"
|
||||
reqwest = "0.10.10"
|
||||
json = "0.12.4"
|
||||
reqwest = "0.11"
|
||||
json = "0.12.4"
|
||||
telegram-markov-chain = "0.1.2"
|
||||
rand = "0.8.3"
|
|
@ -1,6 +1,8 @@
|
|||
#+title: BeerHolderBot
|
||||
A Telegram bot that holds your beer
|
||||
#+html: <a href="https://crates.io/crates/BeerHolderBot"><img alt="Crates.io" src="https://img.shields.io/crates/d/BeerHolderBot?style=for-the-badge"></img></a>
|
||||
#+html: <a href="https://gitlab.com/slondr/BeerHolderBot/-/commits/master"><img alt="pipeline status" src="https://gitlab.com/slondr/BeerHolderBot/badges/master/pipeline.svg" /></a>
|
||||
|
||||
* Commands
|
||||
- =/beer <text>=
|
||||
|
||||
|
@ -15,6 +17,12 @@ A Telegram bot that holds your beer
|
|||
- =/corn=
|
||||
|
||||
Harvest some corn.
|
||||
- =/count=
|
||||
|
||||
Get the current count of stored beers for this tap.
|
||||
- =/yasd=
|
||||
|
||||
Die stupidly.
|
||||
* Building & Running
|
||||
This project is managed with Cargo, so just build it with =cargo build= and whatever flags you want.
|
||||
|
||||
|
|
1107
deaths.txt
Normal file
1107
deaths.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
secret.sh.gpg
BIN
secret.sh.gpg
Binary file not shown.
329
src/main.rs
329
src/main.rs
|
@ -1,26 +1,28 @@
|
|||
// BeerHolderBot
|
||||
// Copyright (C) 2021 Eric S. Londres
|
||||
// BeerHolderBot
|
||||
// Copyright (C) 2021 Eric S. Londres
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use teloxide::{prelude::*, utils::command::BotCommand, requests::ResponseResult};
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use lazy_static::lazy_static;
|
||||
use std::error::Error;
|
||||
use std::{error::Error, fs::File, io::prelude::*};
|
||||
use rand::prelude::*;
|
||||
|
||||
type AsyncResult<T> = Result<T, Box<dyn Error + Send + Sync>>;
|
||||
|
||||
struct Beer {
|
||||
id: i64,
|
||||
|
@ -29,11 +31,39 @@ struct Beer {
|
|||
|
||||
lazy_static! {
|
||||
static ref TAP: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
||||
static ref BEERS: AtomicU64 = AtomicU64::new(0);
|
||||
static ref CONNECTION: Mutex<sqlite::Connection> = Mutex::new(sqlite::open("tap.db").unwrap());
|
||||
}
|
||||
|
||||
async fn initialize_database() -> Result<(), Box<dyn std::error::Error>> {
|
||||
async fn die() -> AsyncResult<String> {
|
||||
// first, open the deaths file
|
||||
let path = std::path::Path::new("deaths.txt");
|
||||
let lines = 1107; // number of choices
|
||||
|
||||
// open the file (read-only)
|
||||
let mut file = match File::open(&path) {
|
||||
Ok(f) => f,
|
||||
Err(e) => return Err(Box::new(e))
|
||||
};
|
||||
|
||||
// read the file's contents into a string
|
||||
let mut contents = String::new();
|
||||
match file.read_to_string(&mut contents) {
|
||||
Ok(_) => (),
|
||||
Err(reason) => return Err(Box::new(reason))
|
||||
}
|
||||
|
||||
// vectorize contents
|
||||
let contents: Vec<&str> = contents.split('\n').collect::<Vec<&str>>();
|
||||
|
||||
// generate a random death index
|
||||
let mut rng = rand::thread_rng();
|
||||
let index: usize = rng.gen_range(0..lines - 1);
|
||||
|
||||
// return the chosen death
|
||||
Ok(String::from(contents[index]))
|
||||
}
|
||||
|
||||
async fn initialize_database() -> AsyncResult<()> {
|
||||
CONNECTION.lock().await.execute("CREATE TABLE IF NOT EXISTS tap (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
chat_id INTEGER NOT NULL,
|
||||
|
@ -41,53 +71,75 @@ async fn initialize_database() -> Result<(), Box<dyn std::error::Error>> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_beer(chat_id: i64, content: String) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
async fn create_beer(chat_id: i64, content: String) -> AsyncResult<()> {
|
||||
CONNECTION.lock().await
|
||||
.execute(format!("INSERT INTO tap (chat_id, text) VALUES ('{}', '{}')", chat_id, content))?;
|
||||
.execute(format!("INSERT INTO tap (chat_id, text) VALUES ('{}', '{}')", chat_id, content))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_all_beers(chat_id: i64) -> Result<Vec<Beer>, Box<dyn Error + Send + Sync>> {
|
||||
async fn get_all_beers(chat_id: i64) -> AsyncResult<Vec<Beer>> {
|
||||
let mut beers: Vec<Beer> = Vec::new();
|
||||
let c = CONNECTION.lock().await;
|
||||
let mut statement = c.prepare(format!("SELECT id, text FROM tap WHERE chat_id={}", chat_id))?;
|
||||
while let sqlite::State::Row = statement.next().unwrap() {
|
||||
beers.push(Beer {
|
||||
id: statement.read::<i64>(0)?,
|
||||
text: statement.read::<String>(1)?
|
||||
});
|
||||
beers.push(Beer {
|
||||
id: statement.read::<i64>(0)?,
|
||||
text: statement.read::<String>(1)?
|
||||
});
|
||||
}
|
||||
Ok(beers)
|
||||
}
|
||||
|
||||
async fn quaff(id: i64) -> Result<String, Box<dyn Error + Send + Sync>> {
|
||||
async fn get_beer_count(chat_id: i64) -> AsyncResult<i64> {
|
||||
let c = CONNECTION.lock().await;
|
||||
let mut statement = c.prepare(format!("SELECT text FROM tap WHERE id={}", id))?;
|
||||
if let sqlite::State::Row = statement.next()? {
|
||||
let text = statement.read::<String>(0)?;
|
||||
// remove the beer from the database
|
||||
c.execute(format!("DELETE FROM tap WHERE id={}", id))?;
|
||||
Ok(text)
|
||||
let mut statement = c.prepare(format!("SELECT COUNT(id) FROM tap WHERE chat_id={}", chat_id))?;
|
||||
if let sqlite::State::Row = statement.next().unwrap() {
|
||||
Ok(statement.read::<i64>(0)?)
|
||||
} else {
|
||||
Err("could not retrieve beer text")?
|
||||
Err("could not retrieve beer count".into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn harvest_corn() -> Result<String, Box<dyn Error + Send + Sync>> {
|
||||
if let Some(access) = std::env::var_os("UNSPLASH_ACCESS") {
|
||||
// call API to get a random picture of corn
|
||||
let auth_uri = format!("https://api.unsplash.com/photos/random/?client_id={}&query={}", access.into_string().unwrap(), "corn");
|
||||
let response = reqwest::get(&auth_uri)
|
||||
.await.unwrap().text().await.unwrap();
|
||||
// response format is some pretty nested json
|
||||
let parsed_response = json::parse(&response);
|
||||
let img_url = &parsed_response.unwrap()["urls"]["raw"];
|
||||
Ok(img_url.to_string())
|
||||
async fn quaff(id: i64) -> AsyncResult<String> {
|
||||
let c = CONNECTION.lock().await;
|
||||
let mut statement = c.prepare(format!("SELECT text FROM tap WHERE id={}", id))?;
|
||||
if let sqlite::State::Row = statement.next()? {
|
||||
let text = statement.read::<String>(0)?;
|
||||
// remove the beer from the database
|
||||
c.execute(format!("DELETE FROM tap WHERE id={}", id))?;
|
||||
Ok(text)
|
||||
} else {
|
||||
Err("You don't have a farm.")?
|
||||
Err("could not retrieve beer text".into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn grab_photo(query: &'static str) -> AsyncResult<String> {
|
||||
if let Some(access) = std::env::var_os("UNSPLASH_ACCESS") {
|
||||
// call API to get a random picture of corn
|
||||
let auth_uri = format!("https://api.unsplash.com/photos/random/?client_id={}&query={}", access.into_string().unwrap(), query);
|
||||
let response = reqwest::get(&auth_uri)
|
||||
.await.unwrap().text().await.unwrap();
|
||||
// response format is some pretty nested json
|
||||
let parsed_response = json::parse(&response);
|
||||
if let Ok(url) = parsed_response {
|
||||
let img_url = &url["urls"]["regular"];
|
||||
Ok(img_url.to_string())
|
||||
} else {
|
||||
Err("No corn to harvest.".into())
|
||||
}
|
||||
} else {
|
||||
Err("You don't have a farm.".into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn harvest_corn() -> AsyncResult<String> {
|
||||
grab_photo("corn").await
|
||||
}
|
||||
|
||||
async fn bovine() -> AsyncResult<String> {
|
||||
grab_photo("cow").await
|
||||
}
|
||||
|
||||
//// TO IMPLEMENT A NEW COMMAND
|
||||
// Add the command name to the Command enum with a description
|
||||
// Implement the logic of the command in the match statement in answer()
|
||||
|
@ -104,86 +156,133 @@ enum Command {
|
|||
#[command(description = "Drink a beer by index")]
|
||||
Quaff(String),
|
||||
#[command(description = "Harvest corn")]
|
||||
Corn
|
||||
Corn,
|
||||
#[command(description = "Post a new message")]
|
||||
Post,
|
||||
#[command(description = "Get the number of beers on tap")]
|
||||
Count,
|
||||
#[command(description = "Die stupidly")]
|
||||
Yasd,
|
||||
#[command(description = "Take a tripe to the pasture")]
|
||||
Bovine
|
||||
}
|
||||
|
||||
async fn answer(cx: UpdateWithCx<AutoSend<Bot>, Message>, command: Command) -> ResponseResult<()> {
|
||||
match command {
|
||||
Command::Help => cx.answer(Command::descriptions()).await?,
|
||||
Command::Beer(b) => {
|
||||
if b != "" {
|
||||
log::info!("Adding {} to list of beers", b);
|
||||
// add the beer to the database
|
||||
match create_beer(cx.chat_id(), b).await {
|
||||
Err(e) => cx.reply_to(format!("Er, something went wrong.\n{}", e)).await?,
|
||||
Ok(_) => {
|
||||
// increment the global beer counter
|
||||
let cur = BEERS.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
// respond with how many beers are held (globally)
|
||||
cx.reply_to(format!("Currently holding {} beer{}", cur, if cur == 1 { "" } else { "s" }))
|
||||
.await?
|
||||
}
|
||||
Command::Help => cx.answer(Command::descriptions()).await?,
|
||||
Command::Beer(b) => {
|
||||
if !b.is_empty() {
|
||||
log::info!("Adding {} to list of beers", b);
|
||||
// add the beer to the database
|
||||
match create_beer(cx.chat_id(), b).await {
|
||||
Err(e) => cx.reply_to(format!("Er, something went wrong.\n{}", e)).await?,
|
||||
Ok(_) => {
|
||||
// increment the global beer counter
|
||||
let cur = get_beer_count(cx.chat_id()).await.unwrap();
|
||||
// respond with how many beers are held (globally)
|
||||
cx.reply_to(format!("Currently holding {} beer{}", cur, if cur == 1 { "" } else { "s" }))
|
||||
.await?
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// the given beer was an empty string, so don't actually store it
|
||||
cx.reply_to("Sorry, I can't hold that beer.").await?
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// the given beer was an empty string, so don't actually store it
|
||||
cx.reply_to("Sorry, I can't hold that beer.").await?
|
||||
}
|
||||
},
|
||||
Command::OnTap => {
|
||||
log::info!("Printing list of beers");
|
||||
// if the tap is empty, print a special message so the Telegram API doesn't freak out
|
||||
match get_all_beers(cx.chat_id()).await {
|
||||
Err(e) => cx.reply_to(format!("Uh, something went wrong.\n{}", e)).await?,
|
||||
Ok(beers) => {
|
||||
let mut m: String = String::new();
|
||||
if beers.len() == 0 {
|
||||
cx.reply_to("Sorry, I'm all empty.").await?
|
||||
} else {
|
||||
for beer in beers {
|
||||
m += format!("[{}] {}\n", beer.id, beer.text).as_str();
|
||||
}
|
||||
cx.reply_to(m.as_str()).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Command::Quaff(beer) => {
|
||||
log::info!("Quaffing beer #{}", beer);
|
||||
// try to parse the user input as an integer
|
||||
if let Ok(index) = beer.parse::<i64>() {
|
||||
/* let tap_lock = TAP.lock().await;
|
||||
if let Some(quaffed_beer) = tap_lock.get(index) {
|
||||
let quaffed_beer = quaffed_beer.to_string();
|
||||
drop(tap_lock);
|
||||
let mut tap_lock = TAP.lock().await;
|
||||
tap_lock.remove(index);
|
||||
*/
|
||||
let quaff_attempt = quaff(index);
|
||||
log::info!("Printing list of beers");
|
||||
// if the tap is empty, print a special message so the Telegram API doesn't freak out
|
||||
match get_all_beers(cx.chat_id()).await {
|
||||
Err(e) => cx.reply_to(format!("Uh, something went wrong.\n{}", e)).await?,
|
||||
Ok(beers) => {
|
||||
let mut m: String = String::new();
|
||||
if beers.is_empty() {
|
||||
cx.reply_to("Sorry, I'm all empty.").await?
|
||||
} else {
|
||||
for beer in beers {
|
||||
m += format!("[{}] {}\n", beer.id, beer.text).as_str();
|
||||
}
|
||||
cx.reply_to(m.as_str()).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Command::Quaff(beer) => {
|
||||
log::info!("Quaffing beer #{}", beer);
|
||||
// try to parse the user input as an integer
|
||||
if let Ok(index) = beer.parse::<i64>() {
|
||||
let quaff_attempt = quaff(index);
|
||||
|
||||
match quaff_attempt.await {
|
||||
Err(e) => cx.reply_to(format!("Sorry, we can't do that.\n{}", e)).await?,
|
||||
Ok(m) => {
|
||||
// reduce the global beer counter
|
||||
let _ = BEERS.fetch_sub(1, Ordering::Relaxed);
|
||||
// send a message informing which beer was quaffed
|
||||
cx.reply_to(format!("You have quaffed \"{}\"", m)).await?
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cx.reply_to("Sorry, we don't have that beer on tap.").await?
|
||||
}
|
||||
},
|
||||
Command::Corn => {
|
||||
// harvest corn
|
||||
log::info!("Harvesting corn");
|
||||
if let Ok(corn) = harvest_corn().await {
|
||||
cx.reply_to(corn).await?
|
||||
} else {
|
||||
log::error!("An error occurred within harvest_corn()");
|
||||
cx.reply_to("You don't have a farm.").await?
|
||||
}
|
||||
}
|
||||
match quaff_attempt.await {
|
||||
Err(e) => cx.reply_to(format!("Sorry, we can't do that.\n{}", e)).await?,
|
||||
Ok(m) => {
|
||||
// send a message informing which beer was quaffed
|
||||
cx.reply_to(format!("You have quaffed \"{}\"", m)).await?
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cx.reply_to("Sorry, we don't have that beer on tap.").await?
|
||||
}
|
||||
},
|
||||
Command::Corn => {
|
||||
// harvest corn
|
||||
log::info!("Harvesting corn");
|
||||
if let Ok(corn) = harvest_corn().await {
|
||||
cx.answer_photo(teloxide::types::InputFile::url(corn)).await?
|
||||
// cx.reply_to(format!("<img src=\"{}\"/>", corn)).parse_mode(teloxide::types::ParseMode::Html).await?
|
||||
} else {
|
||||
log::error!("An error occurred within harvest_corn()");
|
||||
cx.reply_to("You don't have a farm.").await?
|
||||
}
|
||||
},
|
||||
Command::Bovine => {
|
||||
log::info!("cow time");
|
||||
if let Ok(bovine) = bovine().await {
|
||||
cx.answer_photo(teloxide::types::InputFile::url(bovine)).await?
|
||||
} else {
|
||||
log::error!("An error occurred within bovine()");
|
||||
cx.reply_to("No bovine").await?
|
||||
}
|
||||
},
|
||||
Command::Post => {
|
||||
log::info!("Generating new message");
|
||||
let new_msg = telegram_markov_chain::chain();
|
||||
log::info!("Posting new message");
|
||||
cx.reply_to(new_msg).await?
|
||||
},
|
||||
Command::Count => {
|
||||
log::info!("Counting bottles of beer on the wall");
|
||||
if let Ok(count) = get_beer_count(cx.chat_id()).await {
|
||||
cx.reply_to(format!("{} bottles of beer on the wall.", count)).await?
|
||||
} else {
|
||||
cx.reply_to("I can't seem to find any beers.").await?
|
||||
}
|
||||
},
|
||||
Command::Yasd => {
|
||||
log::info!("Dying stupidly...");
|
||||
if let Ok(death) = die().await {
|
||||
let caller = cx.update.from().unwrap().username.as_ref().unwrap();
|
||||
cx.reply_to(format!("<code>
|
||||
----------
|
||||
/ \\
|
||||
/ REST \\
|
||||
/ IN \\
|
||||
/ PEACE \\
|
||||
/ \\
|
||||
| @{}
|
||||
| {}
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| 2021 |
|
||||
*| * * * | *
|
||||
_________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______</code>", caller, death)).parse_mode(teloxide::types::ParseMode::Html).await?
|
||||
} else {
|
||||
cx.reply_to("I just can't seem to die.").await?
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in New Issue
Block a user