mirror of
https://github.com/Steffo99/patched-porobot.git
synced 2024-12-23 01:54:22 +00:00
Complete most of the telegram bot
This commit is contained in:
parent
b2a2535b93
commit
25df599586
9 changed files with 189 additions and 78 deletions
|
@ -7,6 +7,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/card-data" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/card-data" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1036,8 +1036,10 @@ version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"itertools 0.10.3",
|
"itertools 0.10.3",
|
||||||
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -12,7 +12,9 @@ categories = ["games", "parser-implementations"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# base
|
# base
|
||||||
log = { version = "0.4.17" }
|
log = { version = "0.4.17" }
|
||||||
itertools = { version = "0.10.3" } # Not using this yet
|
itertools = { version = "0.10.3" }
|
||||||
|
regex = { version = "1.6.0" }
|
||||||
|
lazy_static = { version = "1.4.0" }
|
||||||
# exec
|
# exec
|
||||||
pretty_env_logger = { version = "0.4.0", optional = true }
|
pretty_env_logger = { version = "0.4.0", optional = true }
|
||||||
glob = { version = "0.3.0", optional = true }
|
glob = { version = "0.3.0", optional = true }
|
||||||
|
|
127
src/bin/patched_porobot_telegram.rs
Normal file
127
src/bin/patched_porobot_telegram.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#[cfg(not(feature = "telegram"))]
|
||||||
|
fn main() {
|
||||||
|
println!("The `telegram` feature was not included on compilation, therefore this binary is not available.")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "telegram")]
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use log::*;
|
||||||
|
use patched_porobot::data::setbundle::card::{Card, CardIndex};
|
||||||
|
use patched_porobot::data::corebundle::CoreBundle;
|
||||||
|
use patched_porobot::data::setbundle::SetBundle;
|
||||||
|
use patched_porobot::data::corebundle::globals::LocalizedGlobalsIndexes;
|
||||||
|
use patched_porobot::search::cardsearch::CardSearchEngine;
|
||||||
|
use patched_porobot::telegram::inline::card_to_inlinequeryresult;
|
||||||
|
use teloxide::payloads::AnswerInlineQuery;
|
||||||
|
use teloxide::requests::JsonRequest;
|
||||||
|
use teloxide::prelude::*;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
pretty_env_logger::init();
|
||||||
|
debug!("Logger initialized successfully!");
|
||||||
|
|
||||||
|
debug!("Loading bundles...");
|
||||||
|
let core = CoreBundle::load(&*PathBuf::from("./card-data/core-en_us")).expect("to be able to load `core-en_us` bundle");
|
||||||
|
let set1 = SetBundle::load(&*PathBuf::from("./card-data/set1-en_us")).expect("to be able to load `set1-en_us` bundle");
|
||||||
|
let set2 = SetBundle::load(&*PathBuf::from("./card-data/set2-en_us")).expect("to be able to load `set2-en_us` bundle");
|
||||||
|
let set3 = SetBundle::load(&*PathBuf::from("./card-data/set3-en_us")).expect("to be able to load `set3-en_us` bundle");
|
||||||
|
let set4 = SetBundle::load(&*PathBuf::from("./card-data/set4-en_us")).expect("to be able to load `set4-en_us` bundle");
|
||||||
|
let set5 = SetBundle::load(&*PathBuf::from("./card-data/set5-en_us")).expect("to be able to load `set5-en_us` bundle");
|
||||||
|
let set6 = SetBundle::load(&*PathBuf::from("./card-data/set6-en_us")).expect("to be able to load `set6-en_us` bundle");
|
||||||
|
debug!("Loaded all bundles!");
|
||||||
|
|
||||||
|
debug!("Indexing globals...");
|
||||||
|
let globals = LocalizedGlobalsIndexes::from(core.globals);
|
||||||
|
debug!("Indexed globals!");
|
||||||
|
|
||||||
|
debug!("Indexing cards...");
|
||||||
|
let cards: Vec<Card> = [
|
||||||
|
set1.cards,
|
||||||
|
set2.cards,
|
||||||
|
set3.cards,
|
||||||
|
set4.cards,
|
||||||
|
set5.cards,
|
||||||
|
set6.cards
|
||||||
|
].concat();
|
||||||
|
|
||||||
|
let mut index = CardIndex::new();
|
||||||
|
for card in cards {
|
||||||
|
index.insert(card.code.clone(), card);
|
||||||
|
}
|
||||||
|
let cards = index;
|
||||||
|
debug!("Indexed cards!");
|
||||||
|
|
||||||
|
debug!("Creating search engine...");
|
||||||
|
let engine = CardSearchEngine::new(globals, cards);
|
||||||
|
debug!("Created search engine!");
|
||||||
|
|
||||||
|
debug!("Creating Telegram bot with parameters from the environment...");
|
||||||
|
let bot = Bot::from_env();
|
||||||
|
let me = bot.get_me().send().await.expect("Telegram bot parameters to be valid");
|
||||||
|
debug!("Created Telegram bot!");
|
||||||
|
|
||||||
|
debug!("Creating inline query handler...");
|
||||||
|
let handler = Update::filter_inline_query().chain(dptree::endpoint(move |query: InlineQuery, bot: Bot| {
|
||||||
|
info!("Handling inline query: `{}`", &query.query);
|
||||||
|
|
||||||
|
debug!("Querying the search engine...");
|
||||||
|
let performed_query = engine.query(&query.query, 50);
|
||||||
|
|
||||||
|
let payload = match performed_query {
|
||||||
|
Ok(results) => {
|
||||||
|
if results.len() > 0 {
|
||||||
|
AnswerInlineQuery {
|
||||||
|
inline_query_id: query.id.clone(),
|
||||||
|
results: results
|
||||||
|
.iter()
|
||||||
|
.map(|card| card_to_inlinequeryresult(&engine.globals, card))
|
||||||
|
.collect_vec(),
|
||||||
|
cache_time: Some(86400),
|
||||||
|
is_personal: Some(false),
|
||||||
|
next_offset: None,
|
||||||
|
switch_pm_text: None,
|
||||||
|
switch_pm_parameter: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AnswerInlineQuery {
|
||||||
|
inline_query_id: query.id.clone(),
|
||||||
|
results: vec![],
|
||||||
|
cache_time: None,
|
||||||
|
is_personal: Some(false),
|
||||||
|
next_offset: None,
|
||||||
|
switch_pm_text: Some("No results found".to_string()),
|
||||||
|
switch_pm_parameter: Some("err-no-results".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
AnswerInlineQuery {
|
||||||
|
inline_query_id: query.id.clone(),
|
||||||
|
results: vec![],
|
||||||
|
cache_time: None,
|
||||||
|
is_personal: Some(false),
|
||||||
|
next_offset: None,
|
||||||
|
switch_pm_text: Some("Invalid query syntax".to_string()),
|
||||||
|
switch_pm_parameter: Some("err-invalid-query".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let telegram_reply = JsonRequest::new(bot.clone(), payload).send().await;
|
||||||
|
|
||||||
|
if let Err(e) = telegram_reply {
|
||||||
|
error!("{:?}", &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
debug!("Create inline query handler!");
|
||||||
|
|
||||||
|
info!("@{} is ready!", &me.username.as_ref().expect("bot to have an username"));
|
||||||
|
Dispatcher::builder(bot, handler).enable_ctrlc_handler().build().dispatch().await;
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
#[cfg(not(feature = "telegram"))]
|
|
||||||
fn main() {
|
|
||||||
println!("The `telegram` feature was not included on compilation, therefore this binary is not available.")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "telegram")]
|
|
||||||
fn main() {
|
|
||||||
println!("Hello telegram world!")
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
//! Module defining [CardArt].
|
//! Module defining [CardArt].
|
||||||
|
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
/// The illustration of a [Card](super::card::Card), also referred to as an *art asset*.
|
/// The illustration of a [Card](super::card::Card), also referred to as an *art asset*.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct CardArt {
|
pub struct CardArt {
|
||||||
|
@ -40,9 +43,13 @@ impl CardArt {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
pub fn card_jpg(&self) -> String {
|
pub fn card_jpg(&self) -> String {
|
||||||
self.card_png
|
lazy_static! {
|
||||||
.replace("https://dd.b.pvp.net/latest/set1", "https://poro.steffo.eu/set1-en_us")
|
static ref GET_JPG: Regex = Regex::new(
|
||||||
.replace(".png", ".jpg")
|
r#"https?://dd[.]b[.]pvp[.]net/[^/]+/(?P<bundle>[^/]+)/(?P<locale>[^/]+)/img/cards/(?P<code>.+)[.]png$"#
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_JPG.replace_all(&self.card_png, "https://poro.steffo.eu/$bundle-$locale/$locale/img/cards/$code.jpg").to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// URL to the `.jpg` image of the `en_us` locale of the full card art, via `poro.steffo.eu`.
|
/// URL to the `.jpg` image of the `en_us` locale of the full card art, via `poro.steffo.eu`.
|
||||||
|
@ -56,9 +63,13 @@ impl CardArt {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
pub fn full_jpg(&self) -> String {
|
pub fn full_jpg(&self) -> String {
|
||||||
self.full_png
|
lazy_static! {
|
||||||
.replace("https://dd.b.pvp.net/latest/set1", "https://poro.steffo.eu/set1-en_us")
|
static ref GET_JPG: Regex = Regex::new(
|
||||||
.replace(".png", ".jpg")
|
r#"https?://dd[.]b[.]pvp[.]net/[^/]+/(?P<bundle>[^/]+)/(?P<locale>[^/]+)/img/cards/(?P<code>.+)[.]png$"#
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_JPG.replace_all(&self.full_png, "https://poro.steffo.eu/$bundle-$locale/$locale/img/cards/$code.jpg").to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,12 +47,17 @@ impl CardSearchEngine {
|
||||||
/// Create the [tantivy::schema::TextOptions] for card codes.
|
/// Create the [tantivy::schema::TextOptions] for card codes.
|
||||||
///
|
///
|
||||||
/// Card codes should:
|
/// Card codes should:
|
||||||
/// - never be tokenized;
|
/// - TODO: be tokenized without alterations;
|
||||||
|
/// - ignore positioning;
|
||||||
/// - be retrievable (what [tantivy] calls "stored").
|
/// - be retrievable (what [tantivy] calls "stored").
|
||||||
fn options_code() -> TextOptions {
|
fn options_code() -> TextOptions {
|
||||||
use tantivy::schema::*;
|
use tantivy::schema::*;
|
||||||
|
|
||||||
TextOptions::default()
|
TextOptions::default()
|
||||||
|
.set_indexing_options(TextFieldIndexing::default()
|
||||||
|
.set_tokenizer("card")
|
||||||
|
.set_index_option(IndexRecordOption::Basic)
|
||||||
|
)
|
||||||
.set_stored()
|
.set_stored()
|
||||||
.set_fast()
|
.set_fast()
|
||||||
}
|
}
|
||||||
|
@ -253,7 +258,14 @@ impl CardSearchEngine {
|
||||||
fn parser(index: &Index, fields: CardSchemaFields) -> QueryParser {
|
fn parser(index: &Index, fields: CardSchemaFields) -> QueryParser {
|
||||||
QueryParser::for_index(
|
QueryParser::for_index(
|
||||||
&index,
|
&index,
|
||||||
Vec::from(fields)
|
vec![
|
||||||
|
fields.code,
|
||||||
|
fields.name,
|
||||||
|
fields.description,
|
||||||
|
fields.flavor,
|
||||||
|
fields.subtypes,
|
||||||
|
fields.supertype,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,28 +358,3 @@ struct CardSchemaFields {
|
||||||
/// [Card::supertype].
|
/// [Card::supertype].
|
||||||
pub supertype: Field,
|
pub supertype: Field,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CardSchemaFields> for Vec<Field> {
|
|
||||||
fn from(fields: CardSchemaFields) -> Self {
|
|
||||||
vec![
|
|
||||||
fields.code,
|
|
||||||
fields.name,
|
|
||||||
fields.r#type,
|
|
||||||
fields.set,
|
|
||||||
fields.rarity,
|
|
||||||
fields.collectible,
|
|
||||||
fields.regions,
|
|
||||||
fields.attack,
|
|
||||||
fields.cost,
|
|
||||||
fields.health,
|
|
||||||
fields.spellspeed,
|
|
||||||
fields.keywords,
|
|
||||||
fields.description,
|
|
||||||
fields.levelup,
|
|
||||||
fields.flavor,
|
|
||||||
fields.artist,
|
|
||||||
fields.subtypes,
|
|
||||||
fields.supertype,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,24 +22,23 @@ use crate::data::setbundle::supertype::CardSupertype;
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
pub fn display_card(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
pub fn display_card(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
||||||
let title = format!(
|
let title = format!(
|
||||||
r#"<a href="{}"><b><i>{}</b></i></a>"#,
|
"<b><u>{}</u></b>\n",
|
||||||
&card.main_art().expect("Card to have at least one illustration").card_png,
|
|
||||||
escape(&card.name),
|
escape(&card.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
let stats = match &card.r#type {
|
let stats = match &card.r#type {
|
||||||
CardType::Spell => format!(
|
CardType::Spell => format!(
|
||||||
"{} mana",
|
"{} mana\n",
|
||||||
escape(&card.cost.to_string()),
|
escape(&card.cost.to_string()),
|
||||||
),
|
),
|
||||||
CardType::Unit => format!(
|
CardType::Unit => format!(
|
||||||
"{} mana {}|{}",
|
"{} mana {}|{}\n",
|
||||||
escape(&card.cost.to_string()),
|
escape(&card.cost.to_string()),
|
||||||
escape(&card.attack.to_string()),
|
escape(&card.attack.to_string()),
|
||||||
escape(&card.health.to_string()),
|
escape(&card.health.to_string()),
|
||||||
),
|
),
|
||||||
CardType::Landmark => format!(
|
CardType::Landmark => format!(
|
||||||
"{} mana",
|
"{} mana\n",
|
||||||
&card.cost
|
&card.cost
|
||||||
),
|
),
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
|
@ -49,32 +48,25 @@ pub fn display_card(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
||||||
let regions = display_regions(&card.regions, &globals.regions);
|
let regions = display_regions(&card.regions, &globals.regions);
|
||||||
let r#type = display_types(&card.r#type, &card.supertype, &card.subtypes);
|
let r#type = display_types(&card.r#type, &card.supertype, &card.subtypes);
|
||||||
|
|
||||||
let breadcrumbs = format!("{} › {} › {}", &set, ®ions, &r#type);
|
let breadcrumbs = format!("{} › {} › {}\n", &set, ®ions, &r#type);
|
||||||
|
|
||||||
let keywords = display_keywords(&card.keywords, &globals.keywords);
|
let keywords = display_keywords(&card.keywords, &globals.keywords);
|
||||||
|
|
||||||
let description = escape(&card.localized_description_text);
|
let description = format!("{}\n", escape(&card.localized_description_text));
|
||||||
|
|
||||||
let flavor = format!(
|
let flavor = format!(
|
||||||
"<i>{}</i>",
|
"<i>{}</i>\n",
|
||||||
escape(&card.localized_flavor_text)
|
escape(&card.localized_flavor_text)
|
||||||
);
|
);
|
||||||
|
|
||||||
let artist = format!(
|
let artist = format!(
|
||||||
r#"<a href="{}">Illustration by {}</a>"#,
|
r#"<a href="{}">Illustration</a> by {}"#,
|
||||||
&card.main_art().expect("Card to have at least one illustration").full_png,
|
&card.main_art().expect("Card to have at least one illustration").full_png,
|
||||||
escape(&card.artist_name)
|
escape(&card.artist_name)
|
||||||
);
|
);
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{title} {stats}\n{breadcrumbs}\n\n{keywords}\n{description}\n\n-----\n{flavor}\n\n{artist}",
|
"{title}{breadcrumbs}\n{keywords}{stats}{description}\n-----\n{flavor}{artist}",
|
||||||
title=title,
|
|
||||||
stats=stats,
|
|
||||||
breadcrumbs=breadcrumbs,
|
|
||||||
keywords=keywords,
|
|
||||||
description=description,
|
|
||||||
flavor=flavor,
|
|
||||||
artist=artist,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +137,16 @@ fn display_types(r#type: &CardType, supertype: &CardSupertype, subtypes: &[CardS
|
||||||
///
|
///
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
fn display_keywords(keywords: &[CardKeyword], hm: &LocalizedCardKeywordIndex) -> String {
|
fn display_keywords(keywords: &[CardKeyword], hm: &LocalizedCardKeywordIndex) -> String {
|
||||||
keywords
|
format!(
|
||||||
.iter()
|
"{}\n",
|
||||||
.map(|keyword| keyword
|
keywords
|
||||||
.localized(hm)
|
.iter()
|
||||||
.map(|o| format!("[<b>{}</b>]", escape(&o.name)))
|
.map(|keyword| keyword
|
||||||
.unwrap_or_else(|| "Unknown".to_string())
|
.localized(hm)
|
||||||
)
|
.map(|o| format!("[<b>{}</b>]", escape(&o.name)))
|
||||||
.join(" ")
|
.unwrap_or_else(|| "Unknown".to_string())
|
||||||
|
)
|
||||||
|
.join(" ")
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! [inline mode]: https://core.telegram.org/bots/api#inline-mode
|
//! [inline mode]: https://core.telegram.org/bots/api#inline-mode
|
||||||
|
|
||||||
use teloxide::types::{InlineQueryResult, InlineQueryResultPhoto, InputMessageContent, InputMessageContentText, ParseMode};
|
use teloxide::types::{InlineQueryResult, InlineQueryResultPhoto, ParseMode};
|
||||||
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
||||||
use crate::data::setbundle::card::Card;
|
use crate::data::setbundle::card::Card;
|
||||||
use crate::telegram::display::display_card;
|
use crate::telegram::display::display_card;
|
||||||
|
@ -13,6 +13,8 @@ pub fn card_to_inlinequeryresult(globals: &LocalizedGlobalsIndexes, card: &Card)
|
||||||
InlineQueryResult::Photo(InlineQueryResultPhoto {
|
InlineQueryResult::Photo(InlineQueryResultPhoto {
|
||||||
id: card.code.to_owned(),
|
id: card.code.to_owned(),
|
||||||
title: Some(card.name.to_owned()),
|
title: Some(card.name.to_owned()),
|
||||||
|
caption: Some(display_card(&globals, &card)),
|
||||||
|
parse_mode: Some(ParseMode::Html),
|
||||||
photo_url: card
|
photo_url: card
|
||||||
.main_art()
|
.main_art()
|
||||||
.expect("Card to have at least one illustration")
|
.expect("Card to have at least one illustration")
|
||||||
|
@ -26,17 +28,9 @@ pub fn card_to_inlinequeryresult(globals: &LocalizedGlobalsIndexes, card: &Card)
|
||||||
photo_width: Some(680),
|
photo_width: Some(680),
|
||||||
photo_height: Some(1024),
|
photo_height: Some(1024),
|
||||||
|
|
||||||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
|
||||||
message_text: display_card(&globals, &card),
|
|
||||||
parse_mode: Some(ParseMode::Html),
|
|
||||||
entities: None,
|
|
||||||
disable_web_page_preview: Some(true)
|
|
||||||
})),
|
|
||||||
|
|
||||||
description: None,
|
description: None,
|
||||||
caption: None,
|
|
||||||
parse_mode: None,
|
|
||||||
caption_entities: None,
|
caption_entities: None,
|
||||||
reply_markup: None,
|
reply_markup: None,
|
||||||
|
input_message_content: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue