Compare commits

...

77 Commits

Author SHA1 Message Date
Eric S. Londres
99dae44e60 Merge branch 'bovine' into 'master'
add bovine

See merge request slondr/BeerHolderBot!29
2021-08-22 02:16:37 +00:00
Eric S. Londres
d348b548c1
add bovine 2021-08-21 22:05:29 -04:00
Eric S. Londres
788dca687f Merge branch 'yasd' into 'master'
[v0.3.8] /corn now embeds images rather than posting URLs

See merge request slondr/BeerHolderBot!28
2021-05-05 05:14:01 +00:00
Eric S. Londres
60b2a78ecb
I hate markdown 2021-05-05 01:07:05 -04:00
Eric S. Londres
ebea0b8aa1
argh 2021-05-05 01:05:10 -04:00
Eric S. Londres
04459d1bb6
[v0.3.8] /corn now embeds images rather than posting URLs 2021-05-05 01:04:14 -04:00
Eric S. Londres
dfa79f1dc1 Merge branch 'yasd' into 'master'
Yasd

See merge request slondr/BeerHolderBot!27
2021-04-23 05:44:30 +00:00
Eric S. Londres
6e8e428636
delete dumb readme 2021-04-23 01:38:26 -04:00
Eric S. Londres
21f4a7dc85
add dumb markdown file for creates.io 2021-04-23 01:37:17 -04:00
Eric S. Londres
f96a436afe
update readme 2021-04-23 01:36:23 -04:00
Eric S. Londres
29acc30833
fix a lot of stuff and add a fancy grave 2021-04-23 01:35:05 -04:00
Eric S. Londres
2ec7fe50a9
yell at the caller 2021-04-23 01:12:35 -04:00
Eric S. Londres
43af2d2062 Merge branch 'yasd' into 'master'
Yet Another Stupid Death

See merge request slondr/BeerHolderBot!26
2021-04-23 04:37:05 +00:00
Eric S. Londres
b1d0fb4505
make clippy happy (×2) 2021-04-23 00:30:59 -04:00
Eric S. Londres
ee8e05fedf
make clippy happy 2021-04-23 00:30:30 -04:00
Eric S. Londres
18bff88dce
implement death 2021-04-23 00:28:27 -04:00
Eric S. Londres
0c174fc956
implement death 2021-04-23 00:23:29 -04:00
Eric S. Londres
0c428aec87 add source dataset for YAST 2021-04-22 23:55:22 -04:00
Eric S. Londres
bc9e778e15 Merge branch 'v0.3.7' into 'master'
V0.3.7

See merge request slondr/BeerHolderBot!24
2021-03-29 03:16:20 +00:00
Eric S. Londres
b21a1b582e Merge branch 'chain-dep' into 'v0.3.7'
Chain dep

See merge request slondr/BeerHolderBot!25
2021-03-29 03:09:10 +00:00
Eric S. Londres
42add528a8
bump version number of chain 2021-03-28 23:01:51 -04:00
Eric S. Londres
b102a3e6dc
exit 2021-03-28 18:14:50 -04:00
Eric S. Londres
3a0161f525
markdown dumb 2021-03-28 18:12:15 -04:00
Eric S. Londres
5360eaedf7
add pipeline status badge 2021-03-28 18:11:42 -04:00
Eric S. Londres
993f224d65 Merge branch 'v0.3.7' into 'master'
V0.3.7

See merge request slondr/BeerHolderBot!23
2021-03-28 21:50:12 +00:00
Eric S. Londres
aa45fa0081
fix reqwest version 2021-03-28 17:42:09 -04:00
Eric S. Londres
ccea41fb50
pseudoterminal 2021-03-28 17:36:52 -04:00
Eric S. Londres
98bc21291d Merge branch 'v0.3.7' into 'master'
REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

See merge request slondr/BeerHolderBot!22
2021-03-28 21:24:34 +00:00
Eric S. Londres
7fa09426e9
REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE 2021-03-28 17:17:03 -04:00
Eric S. Londres
ab04b8c56d Merge branch 'v0.3.7' into 'master'
V0.3.7

See merge request slondr/BeerHolderBot!21
2021-03-28 21:03:18 +00:00
Eric S. Londres
37e0cb343c
fix script 2021-03-28 16:57:17 -04:00
Eric S. Londres
6636f38d1a
decript, then run 2021-03-28 16:48:47 -04:00
Eric S. Londres
f0e08e2e0e Merge branch 'v0.3.7' into 'master'
V0.3.7

See merge request slondr/BeerHolderBot!20
2021-03-28 20:15:09 +00:00
Eric S. Londres
234420adc0
ree 2021-03-28 16:09:06 -04:00
Eric S. Londres
b85e473ab4
fix CI again 2021-03-28 16:00:00 -04:00
Eric S. Londres
59005690eb Merge branch 'v0.3.7' into 'master'
fix ssh command

See merge request slondr/BeerHolderBot!19
2021-03-28 19:51:27 +00:00
Eric S. Londres
cd093adb6e
fix ssh command 2021-03-28 15:45:22 -04:00
Eric S. Londres
7d2b37fbe8 Merge branch 'v0.3.7' into 'master'
Clean up code and fix deplyoment CI

See merge request slondr/BeerHolderBot!18
2021-03-28 19:32:56 +00:00
Eric S. Londres
42988b2755
load ssh key 2021-03-28 15:26:47 -04:00
Eric S. Londres
31680db976
update changelog 2021-03-28 15:11:31 -04:00
Eric S. Londres
a3d284f8c6
change ".len() == 0" to ".is_empty()"
makes clippy happy
2021-03-28 15:10:59 -04:00
Eric S. Londres
fa5a9dbccd
change "!= """ to "!is_empty()"
makes clippy happy
2021-03-28 15:10:04 -04:00
Eric S. Londres
22b50397f4
change ? to into() in errors
makes clippy happy
2021-03-28 15:09:16 -04:00
Eric S. Londres
4ceffb6071 Merge branch 'v0.3.7' into 'master'
Automated deployments

See merge request slondr/BeerHolderBot!17
2021-03-28 19:07:37 +00:00
Eric S. Londres
db9f6edfef
implement caching in test phase 2021-03-28 14:56:02 -04:00
Eric S. Londres
459e58a478
update git repo on host when deploying 2021-03-28 14:52:29 -04:00
Eric S. Londres
0004a34d40
update changelog 2021-03-28 14:45:37 -04:00
Eric S. Londres
5ebedb4046
Merge remote-tracking branch 'origin/v0.3.7' into v0.3.7 2021-03-28 14:45:02 -04:00
Eric S. Londres
8812b3472c
add deploy script 2021-03-28 14:44:50 -04:00
Eric S. Londres
b0a1267872
add test stage 2021-03-28 14:44:50 -04:00
Eric S. Londres
645c6012b2
add test stage 2021-03-28 14:44:50 -04:00
Eric S. Londres
bb05bc4a31
add deploy script 2021-03-28 14:43:16 -04:00
Eric S. Londres
89cc5822f9 Merge branch 'v0.3.6' into 'master'
V0.3.6

See merge request slondr/BeerHolderBot!16
2021-03-28 18:42:06 +00:00
Eric S. Londres
d1ee2418de
add test stage 2021-03-28 14:40:19 -04:00
Eric S. Londres
7a1e397958
add test stage 2021-03-28 14:39:10 -04:00
Eric S. Londres
82135166cd
add logfile and message cache to ignore 2021-03-28 14:34:57 -04:00
Eric S. Londres
53e6fe9b6e
stop tracking json file 2021-03-28 14:32:44 -04:00
Eric S. Londres
6a69b51148
bump version number 2021-03-28 14:32:06 -04:00
Eric S. Londres
9880695fad
upcate changelog 2021-03-28 14:32:02 -04:00
Eric S. Londres
aa3ae7b42e
add run script 2021-03-28 14:30:22 -04:00
Eric S. Londres
581c607cb6
wait 2021-03-28 14:28:10 -04:00
Eric S. Londres
faf492acbf
update shell script to kill running versions of the bot 2021-03-28 14:27:39 -04:00
Eric S. Londres
2546759368 Merge branch 'v0.3.5' into 'master'
Count udpates

See merge request slondr/BeerHolderBot!15
2021-03-28 17:59:07 +00:00
Eric S. Londres
b8293dae47
update readme 2021-03-28 13:56:12 -04:00
Eric S. Londres
59f9a1b696
update shell script to actually launch the damn thing 2021-03-28 13:51:56 -04:00
Eric S. Londres
4bedfb1b08
implement Count command to explicitly request the beer count 2021-03-28 13:48:31 -04:00
Eric S. Londres
9398fe5217
remove dead commented-out code 2021-03-28 13:43:01 -04:00
Eric S. Londres
84e5728d03
implement count using sql instead of an in-memory counter
the counter wasn't accurate, anyway
2021-03-28 13:40:34 -04:00
Eric S. Londres
370fca7197
implement explicit type template 2021-03-28 13:30:10 -04:00
Eric S. Londres
308845b949
bump version number 2021-03-28 13:24:40 -04:00
Eric S. Londres
f166ecf582 Merge branch 'chain' into 'master'
Implement markov chain functionality

See merge request slondr/BeerHolderBot!14
2021-03-28 09:34:15 +00:00
Eric S. Londres
e74b2b4dbe
added json 2021-03-28 05:27:00 -04:00
Eric S. Londres
9f5b939391
add more useufl logging statements 2021-03-28 05:25:18 -04:00
Eric S. Londres
d9e6023a5c
use published function 2021-03-28 05:21:18 -04:00
Eric S. Londres
1393883077
fix syntax error 2021-03-28 05:20:32 -04:00
Eric S. Londres
c9f6a0f499
update changelog 2021-03-28 05:15:45 -04:00
Eric S. Londres
4a463aafd2
implement post 2021-03-28 05:15:05 -04:00
10 changed files with 1616 additions and 473 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
/target
token.gpg
*.db
nohup.out
result.json

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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

File diff suppressed because it is too large Load Diff

1
run.sh Executable file
View File

@ -0,0 +1 @@
source <(gpg --decrypt secret.sh.gpg)

Binary file not shown.

View File

@ -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(())