Some changes and add links command, for now populated with eurosport.
This commit is contained in:
parent
9e03e8be42
commit
5d05c220ec
70
command_permissions.py
Normal file
70
command_permissions.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
import requests
|
||||
import toml
|
||||
import json
|
||||
import sys
|
||||
|
||||
CONFIG_FILE = "data/config/01-discord.toml"
|
||||
CONFIG_FILE2 = "data/config/30-high-tier.toml"
|
||||
|
||||
|
||||
data1 = toml.load(CONFIG_FILE2)
|
||||
ROLE_ID = data1.get("high_tier", {}).get("role", 294950710737502209)
|
||||
GUILD = data1.get("high_tier", {}).get("guild", 117992911781494787)
|
||||
HT_COMS = data1.get("high_tier", {}).get("coms", ["links"])
|
||||
|
||||
data = toml.load(CONFIG_FILE)
|
||||
app_id = data["discord"].get("app_id", 936990391847223316)
|
||||
|
||||
print("Using token: ", data["discord"]["token"])
|
||||
token = "Bot " + data["discord"]["token"]
|
||||
print(token)
|
||||
|
||||
|
||||
Headers = {
|
||||
"Authorization": token,
|
||||
"User=Agent": "DiscordBot https://github.com/ 1 manual browser requests",
|
||||
}
|
||||
|
||||
r = requests.get(f"https://discord.com/api/v8/applications/{app_id}/guilds/{GUILD}/commands", headers=Headers)
|
||||
|
||||
print(json.dumps(r.json(), indent=2))
|
||||
commands = r.json()
|
||||
com_id = None
|
||||
|
||||
|
||||
json = {
|
||||
"permissions": [
|
||||
{
|
||||
"id": ROLE_ID,
|
||||
"type": 1,
|
||||
"permission": True
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
count = 0
|
||||
for command in commands:
|
||||
if command["name"] in HT_COMS:
|
||||
id = command["id"]
|
||||
url = f"https://discord.com/api/v8/applications/{app_id}/guilds/{GUILD}/commands/{str(id)}"
|
||||
r = requests.patch(url, headers=Headers, json={"default_permission": False})
|
||||
print(r.json())
|
||||
r = requests.put(url+"/permissions", headers=Headers, json=json)
|
||||
print(r.json())
|
||||
count += 1
|
||||
|
||||
print("Updated", count, "commands")
|
||||
|
||||
# print("Which id to set")
|
||||
# id = input()
|
||||
|
||||
# url = f"https://discord.com/api/v8/applications/{app_id}/guilds/{GUILD}/commands/{str(id)}"
|
||||
|
||||
|
||||
|
||||
# r = requests.patch(url, headers=Headers, json={"default_permission": False})
|
||||
# print(r.json())
|
||||
|
||||
# r = requests.put(url+"/permissions", headers=Headers, json=json)
|
||||
|
||||
# print(r.json())
|
496
src/commands/links/eurosport.rs
Normal file
496
src/commands/links/eurosport.rs
Normal file
|
@ -0,0 +1,496 @@
|
|||
use crate::{commands::utils, Context, Error};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::*;
|
||||
use reqwest::header::{HeaderName, ACCEPT_LANGUAGE, COOKIE};
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::Timeframe;
|
||||
|
||||
mod es_date_time {
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use serde::{self, Deserialize, Deserializer};
|
||||
|
||||
const FORMAT: &'static str = "%Y-%m-%dT%H:%M:%SZ";
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Utc.datetime_from_str(&s, FORMAT)
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct VideoAttributes {
|
||||
// #[serde(rename = "earliestPlayableStart")]
|
||||
// #[serde(with = "es_date_time")]
|
||||
// earliest_playable_start: DateTime<Utc>,
|
||||
name: String,
|
||||
#[serde(rename = "secondaryTitle")]
|
||||
#[serde(default)]
|
||||
secondary: String,
|
||||
#[serde(rename = "publishEnd")]
|
||||
#[serde(with = "es_date_time")]
|
||||
publish_end: DateTime<Utc>,
|
||||
#[serde(rename = "publishStart")]
|
||||
#[serde(with = "es_date_time")]
|
||||
publish_start: DateTime<Utc>,
|
||||
#[serde(default)]
|
||||
description: String,
|
||||
// #[serde(rename = "drmEnabled")]
|
||||
// drm_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct SportVal {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct SportID {
|
||||
data: Vec<SportVal>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct VideoRelations {
|
||||
#[serde(alias = "txSports")]
|
||||
#[serde(alias = "txOlympicssport")]
|
||||
sport_id: Option<SportID>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct TaxonomyNodeAttributes {
|
||||
name: String,
|
||||
// kind: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(tag = "type")]
|
||||
enum Includes {
|
||||
#[serde(rename = "video")]
|
||||
Video {
|
||||
attributes: VideoAttributes,
|
||||
id: String,
|
||||
relationships: VideoRelations,
|
||||
},
|
||||
#[serde(rename = "taxonomyNode")]
|
||||
TaxonomyNode {
|
||||
attributes: TaxonomyNodeAttributes,
|
||||
id: String,
|
||||
},
|
||||
#[serde(rename = "channel")]
|
||||
Channels,
|
||||
#[serde(rename = "collection")]
|
||||
Collection,
|
||||
#[serde(rename = "collectionItem")]
|
||||
CollectionItem,
|
||||
#[serde(rename = "image")]
|
||||
Image,
|
||||
#[serde(rename = "link")]
|
||||
Link,
|
||||
#[serde(rename = "package")]
|
||||
Package,
|
||||
#[serde(rename = "page")]
|
||||
Page,
|
||||
#[serde(rename = "pageItem")]
|
||||
PageItem,
|
||||
#[serde(rename = "route")]
|
||||
Route,
|
||||
#[serde(rename = "show")]
|
||||
Show,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Eurosport {
|
||||
included: Vec<Includes>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ESEvents {
|
||||
id: String,
|
||||
sport: Option<String>,
|
||||
name: String,
|
||||
secondary: String,
|
||||
description: String,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>,
|
||||
// early_start: DateTime<Utc>,
|
||||
// drm_enabled: bool,
|
||||
}
|
||||
|
||||
impl ESEvents {
|
||||
fn filter(&self, filter: &str) -> bool {
|
||||
if self.name.to_lowercase().contains(filter) {
|
||||
return true;
|
||||
};
|
||||
if self.description.to_lowercase().contains(filter) {
|
||||
return true;
|
||||
};
|
||||
if self.secondary.to_lowercase().contains(filter) {
|
||||
return true;
|
||||
};
|
||||
if let Some(sport) = &self.sport {
|
||||
if sport.to_lowercase().contains(filter) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn comp(&self, when: &Option<Timeframe>) -> bool {
|
||||
let now = Utc::now();
|
||||
match when {
|
||||
Some(Timeframe::Everything) => true,
|
||||
Some(Timeframe::Current) => self.start <= now && self.end >= now,
|
||||
Some(Timeframe::Future) => self.end >= now,
|
||||
Some(Timeframe::Past) => self.end <= now,
|
||||
_ => self.end >= now,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_events(v: Eurosport) -> Result<Vec<ESEvents>, serde_json::Error> {
|
||||
let mut sports: HashMap<String, String> = HashMap::new();
|
||||
|
||||
let nodes = v.included.iter().filter(|x| match x {
|
||||
Includes::TaxonomyNode { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
for node in nodes {
|
||||
if let Includes::TaxonomyNode { attributes, id } = node {
|
||||
sports.insert(id.to_string(), attributes.name.to_string());
|
||||
}
|
||||
}
|
||||
debug!("Sports: {:?}", sports);
|
||||
|
||||
let mut events: Vec<ESEvents> = vec![];
|
||||
|
||||
let nodes = v.included.iter().filter(|x| match x {
|
||||
Includes::Video { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
for node in nodes {
|
||||
if let Includes::Video {
|
||||
attributes,
|
||||
id,
|
||||
relationships,
|
||||
} = node
|
||||
{
|
||||
// sports.insert(id.to_string(), attributes.name.to_string());
|
||||
|
||||
let sport_name = match &relationships.sport_id {
|
||||
None => None,
|
||||
Some(sportid) => match sportid.data.get(0) {
|
||||
None => None,
|
||||
Some(sv) => match sports.get(&sv.id) {
|
||||
None => None,
|
||||
Some(s) => Some(s.to_owned()),
|
||||
},
|
||||
},
|
||||
};
|
||||
events.push(ESEvents {
|
||||
id: id.to_string(),
|
||||
sport: sport_name,
|
||||
name: attributes.name.to_string(),
|
||||
secondary: attributes.secondary.to_string(),
|
||||
description: attributes.description.to_string(),
|
||||
start: attributes.publish_start,
|
||||
end: attributes.publish_end,
|
||||
// early_start: attributes.earliest_playable_start,
|
||||
// drm_enabled: attributes.drm_enabled,
|
||||
});
|
||||
}
|
||||
}
|
||||
events.sort_by(|a, b| b.start.cmp(&a.start));
|
||||
debug!("Events: {:?}", events);
|
||||
return Ok(events);
|
||||
}
|
||||
|
||||
fn stringify_events(events: Vec<ESEvents>) -> Vec<String> {
|
||||
let mut result = vec![];
|
||||
for event in events {
|
||||
result.push(match event.sport {
|
||||
// None => format!("```md\n({}) {}```\n", event.name, event.secondary),
|
||||
None => format!(
|
||||
"```md\n({}) {}```(<t:{}:R>-<t:{}:R>) {}\n https://tom.al/ms/euro/{} https://tom.al/ms/euro/{}",
|
||||
event.name,
|
||||
event.secondary,
|
||||
event.start.timestamp(),
|
||||
event.end.timestamp(),
|
||||
event.description,
|
||||
event.id,
|
||||
event.id
|
||||
),
|
||||
Some(sport) => format!(
|
||||
"```md\n[{}]({}) {}```(<t:{}:R>-<t:{}:R>) {}\n https://tom.al/ms/euro/{} https://tom.al/ms/euro/{}",
|
||||
sport,
|
||||
event.name,
|
||||
event.secondary,
|
||||
event.start.timestamp(),
|
||||
event.end.timestamp(),
|
||||
event.description,
|
||||
event.id,
|
||||
event.id
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#[cached(time = 3600)]
|
||||
#[allow(dead_code)]
|
||||
async fn get_eurosport_events(url: String) -> Option<Vec<ESEvents>> {
|
||||
let cookie = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("eurosport")
|
||||
.expect("Expecting an eurosport section in the config")
|
||||
.get("cookie")
|
||||
.expect("Config error, please set the eurosport[cookie] value")
|
||||
.clone()
|
||||
.into_str()
|
||||
.expect("Config error, please make sure eurosport[cookie] is a string");
|
||||
let client = reqwest::Client::new();
|
||||
let x_disco_client = HeaderName::from_lowercase(b"x-disco-client").unwrap();
|
||||
let req = client
|
||||
.get(url)
|
||||
.header(COOKIE, cookie)
|
||||
.header(ACCEPT_LANGUAGE, "en-US,en;q=0.5")
|
||||
.header(x_disco_client, "WEB:UNKNOWN:esplayer:prod")
|
||||
.send()
|
||||
.await;
|
||||
|
||||
let result: Option<Vec<ESEvents>> = match req {
|
||||
Err(e) => {
|
||||
warn!("Error getting Eurosport schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 404 => {
|
||||
warn!("404 on getting ES events");
|
||||
return None;
|
||||
}
|
||||
Ok(req) if req.status().as_u16() == 200 => {
|
||||
let data = req.json::<Eurosport>().await;
|
||||
match data {
|
||||
Err(e) => {
|
||||
warn!("Error getting Eurosport schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(es) => {
|
||||
debug!("Eurosport data: {:?}", es);
|
||||
match get_events(es) {
|
||||
Err(e) => {
|
||||
warn!("Error getting Eurosport schedule {}", e);
|
||||
None
|
||||
}
|
||||
Ok(events) => {
|
||||
// events.sort_by(|a: ESEvents, b: ESEvents| b.start.cmp(a));
|
||||
Some(events)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
// #[derive(Debug, poise::SlashChoiceParameter)]
|
||||
// pub enum Timeframe {
|
||||
// #[name = "Currently happening"]
|
||||
// Current,
|
||||
// #[name = "Currently happening or starting in the future"]
|
||||
// Future,
|
||||
// #[name = "Currently happening or already ended"]
|
||||
// Past,
|
||||
// #[name = "Everything"]
|
||||
// Everything,
|
||||
// }
|
||||
|
||||
// /// Eurosport player events
|
||||
// #[poise::command(slash_command)]
|
||||
// pub async fn eurosport(
|
||||
// ctx: Context<'_>,
|
||||
// #[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
// timeframe: Option<Timeframe>,
|
||||
// #[description = "Content to filter on"] filter: Option<String>,
|
||||
// ) -> Result<(), Error> {
|
||||
// if !utils::high_tier(ctx.channel_id()) {
|
||||
// ctx.say("This command can only be used in high tier channels for security")
|
||||
// .await?;
|
||||
// return Ok(());
|
||||
// }
|
||||
// let url = super::super::super::SETTINGS
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .get_table("eurosport")
|
||||
// .expect("Expecting an eurosport section in the config")
|
||||
// .get("url")
|
||||
// .expect("Config error, please set the eurosport[url] value")
|
||||
// .clone()
|
||||
// .into_str()
|
||||
// .expect("Config error, please make sure eurosport[url] is a string");
|
||||
// let events = get_eurosport_events(url).await;
|
||||
// match events {
|
||||
// None => {
|
||||
// ctx.say("Oh no something went wrong").await?;
|
||||
// }
|
||||
// Some(evs) => {
|
||||
// info!("Found {} events from eurosport", evs.len());
|
||||
// let strings = stringify_events(
|
||||
// evs.into_iter()
|
||||
// .filter(|e| e.comp(&timeframe))
|
||||
// .filter(|e| match &filter {
|
||||
// None => true,
|
||||
// Some(f) => e.filter(f.as_str()),
|
||||
// })
|
||||
// .collect(),
|
||||
// );
|
||||
// let pages = utils::paginator(strings, 1900, "\n".to_string());
|
||||
|
||||
// utils::paginate_string(ctx, pages).await?;
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
/// Eurosport player events
|
||||
pub async fn proc_eurosport(
|
||||
ctx: Context<'_>,
|
||||
timeframe: Option<Timeframe>,
|
||||
filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let url = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("eurosport")
|
||||
.expect("Expecting an eurosport section in the config")
|
||||
.get("url")
|
||||
.expect("Config error, please set the eurosport[url] value")
|
||||
.clone()
|
||||
.into_str()
|
||||
.expect("Config error, please make sure eurosport[url] is a string");
|
||||
let events = get_eurosport_events(url).await;
|
||||
match events {
|
||||
None => {
|
||||
ctx.say("Oh no something went wrong").await?;
|
||||
}
|
||||
Some(evs) => {
|
||||
info!("Found {} events from eurosport", evs.len());
|
||||
let strings = stringify_events(
|
||||
evs.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
let pages = utils::paginator(strings, 1900, "\n".to_string());
|
||||
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// /// Eurosport olympics events
|
||||
// #[poise::command(slash_command)]
|
||||
// pub async fn olympics(
|
||||
// ctx: Context<'_>,
|
||||
// #[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
// timeframe: Option<Timeframe>,
|
||||
// #[description = "Content to filter on"] filter: Option<String>,
|
||||
// ) -> Result<(), Error> {
|
||||
// // if !utils::high_tier(ctx.channel_id()) {
|
||||
// // ctx.say("This command can only be used in high tier channels for security")
|
||||
// // .await?;
|
||||
// // return Ok(());
|
||||
// // }
|
||||
// if !utils::high_tier_mess(ctx).await {
|
||||
// ctx.say("This command can only be used in high tier channels for security")
|
||||
// .await?;
|
||||
// return Ok(());
|
||||
// }
|
||||
// let url = super::super::super::SETTINGS
|
||||
// .read()
|
||||
// .unwrap()
|
||||
// .get_table("eurosport")
|
||||
// .expect("Expecting an eurosport section in the config")
|
||||
// .get("olympics")
|
||||
// .expect("Config error, please set the eurosport[olympics] value")
|
||||
// .clone()
|
||||
// .into_str()
|
||||
// .expect("Config error, please make sure eurosport[olympics] is a string");
|
||||
// let events = get_eurosport_events(url).await;
|
||||
// match events {
|
||||
// None => {
|
||||
// ctx.say("Oh no something went wrong").await?;
|
||||
// }
|
||||
// Some(evs) => {
|
||||
// info!("Found {} events from eurosport olympics ", evs.len());
|
||||
// let strings = stringify_events(
|
||||
// evs.into_iter()
|
||||
// .filter(|e| e.comp(&timeframe))
|
||||
// .filter(|e| match &filter {
|
||||
// None => true,
|
||||
// Some(f) => e.filter(f.as_str()),
|
||||
// })
|
||||
// .collect(),
|
||||
// );
|
||||
// let pages = utils::paginator(strings, 1900, "\n".to_string());
|
||||
|
||||
// utils::paginate_string(ctx, pages).await?;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
/// Eurosport olympics events
|
||||
pub async fn proc_olympics(
|
||||
ctx: Context<'_>,
|
||||
timeframe: Option<Timeframe>,
|
||||
filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let url = super::super::super::SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("eurosport")
|
||||
.expect("Expecting an eurosport section in the config")
|
||||
.get("olympics")
|
||||
.expect("Config error, please set the eurosport[olympics] value")
|
||||
.clone()
|
||||
.into_str()
|
||||
.expect("Config error, please make sure eurosport[olympics] is a string");
|
||||
let events = get_eurosport_events(url).await;
|
||||
match events {
|
||||
None => {
|
||||
ctx.say("Oh no something went wrong").await?;
|
||||
}
|
||||
Some(evs) => {
|
||||
info!("Found {} events from eurosport olympics ", evs.len());
|
||||
let strings = stringify_events(
|
||||
evs.into_iter()
|
||||
.filter(|e| e.comp(&timeframe))
|
||||
.filter(|e| match &filter {
|
||||
None => true,
|
||||
Some(f) => e.filter(f.as_str()),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
let pages = utils::paginator(strings, 1900, "\n".to_string());
|
||||
|
||||
utils::paginate_string(ctx, pages).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
46
src/commands/links/mod.rs
Normal file
46
src/commands/links/mod.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::{commands::utils, Context, Error};
|
||||
|
||||
pub mod eurosport;
|
||||
|
||||
#[derive(Debug, poise::SlashChoiceParameter)]
|
||||
pub enum Timeframe {
|
||||
#[name = "Currently happening"]
|
||||
Current,
|
||||
#[name = "Currently happening or starting in the future"]
|
||||
Future,
|
||||
#[name = "Currently happening or already ended"]
|
||||
Past,
|
||||
#[name = "Everything"]
|
||||
Everything,
|
||||
}
|
||||
|
||||
#[derive(Debug, poise::SlashChoiceParameter)]
|
||||
pub enum Source {
|
||||
#[name = "Get links for the Eurosport player"]
|
||||
Eurosport,
|
||||
#[name = "Get links for the apocalympics Eurosport player"]
|
||||
Olympics,
|
||||
}
|
||||
|
||||
/// Get links for high tier commands.
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn links(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Where to git the juicy links from?"] source: Source,
|
||||
#[description = "Filter sessions for when they are/were happening, defaults to future"]
|
||||
timeframe: Option<Timeframe>,
|
||||
#[description = "Content to filter on"] filter: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
if !utils::high_tier(ctx).await {
|
||||
ctx.say("This command can only be used in high tier channels for security")
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match source {
|
||||
Source::Eurosport => eurosport::proc_eurosport(ctx, timeframe, filter).await,
|
||||
Source::Olympics => eurosport::proc_olympics(ctx, timeframe, filter).await,
|
||||
}
|
||||
|
||||
// Ok(())
|
||||
}
|
|
@ -2,6 +2,7 @@ use crate::{Context, Error};
|
|||
use poise::serenity_prelude as serenity;
|
||||
|
||||
pub mod invites;
|
||||
pub mod links;
|
||||
pub mod planning;
|
||||
pub mod schedule;
|
||||
pub mod utils;
|
||||
|
@ -12,7 +13,7 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
let uuid_boop = ctx.id();
|
||||
|
||||
ctx.send(|m| {
|
||||
m.content("I want some boops!").components(|c| {
|
||||
m.content("I want some boops! 🐇").components(|c| {
|
||||
c.create_action_row(|ar| {
|
||||
ar.create_button(|b| {
|
||||
b.style(serenity::ButtonStyle::Primary)
|
||||
|
@ -24,11 +25,10 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
})
|
||||
.await?;
|
||||
|
||||
let mut boop_count = 0;
|
||||
let mut boop_count: i32 = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
.author_id(ctx.author().id)
|
||||
.channel_id(ctx.channel_id())
|
||||
.timeout(std::time::Duration::from_secs(120))
|
||||
// .timeout(std::time::Duration::from_secs(1200))
|
||||
.filter(move |mci| mci.data.custom_id == uuid_boop.to_string())
|
||||
.await
|
||||
{
|
||||
|
@ -36,7 +36,26 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
|
||||
let mut msg = mci.message.clone();
|
||||
msg.edit(ctx.discord(), |m| {
|
||||
m.content(format!("Boop count: {}", boop_count))
|
||||
m.content(match boop_count {
|
||||
2 => "Boop count: <:HamSmile:738765923401596991>".to_string(),
|
||||
3 => "Boop 3".to_string(),
|
||||
4 => "Boop four".to_string(),
|
||||
5 => "Boop five".to_string(),
|
||||
42 => "Boop count: 42, but what is the question?".to_string(),
|
||||
43 => "Boop count: 43 A wild <@230001507481681920> appeared".to_string(),
|
||||
69 => "Boop count: 69 Nice!".to_string(),
|
||||
77 => "Boop count: 77 <@547041420733841409> Approved".to_string(),
|
||||
308 => "Redirect 308: Boop count is in another castle".to_string(),
|
||||
400 => "ERROR 400: Bad booping".to_string(),
|
||||
401 => "ERROR 401: Unauthorized booping".to_string(),
|
||||
402 => "ERROR 402: Payment required, no free boops".to_string(),
|
||||
403 => "ERROR 403: Forbidden boop".to_string(),
|
||||
404 => "ERROR 404: Boop count not found".to_string(),
|
||||
420 => "Boop count: 420 Blaze it".to_string(),
|
||||
666 => "Boop count: 666 😈".to_string(),
|
||||
777 => "Boop count: 777 A wild <@117992484310745097> appeared".to_string(),
|
||||
_ => format!("Boop count: {}", boop_count),
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
@ -48,3 +67,18 @@ pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_links(
|
||||
) -> poise::Command<super::Data, Box<(dyn std::error::Error + Sync + std::marker::Send + 'static)>>
|
||||
{
|
||||
// poise::Command {
|
||||
// subcommands: vec![
|
||||
// links::eurosport::eurosport(),
|
||||
// links::eurosport::olympics(),
|
||||
// links::links(),
|
||||
// // Let's make sure poise isn't confused by the duplicate names!
|
||||
// ],
|
||||
// ..links::links()
|
||||
// };
|
||||
links::links()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
use std::vec;
|
||||
|
||||
use crate::{Context, Error};
|
||||
use poise::serenity_prelude as serenity;
|
||||
use poise::serenity_prelude::{self as serenity, ChannelId};
|
||||
|
||||
pub async fn high_tier(ctx: Context<'_>) -> bool {
|
||||
let ChannelId(chan_id) = ctx.channel_id();
|
||||
match chan_id {
|
||||
117992911781494787 => return true, // private general
|
||||
332337657113739265 => return true, // Testing
|
||||
_ => (),
|
||||
}
|
||||
|
||||
match ctx.discord().cache.guild_channel(ctx.channel_id()) {
|
||||
None => return false,
|
||||
Some(chan) => match chan.parent_id {
|
||||
None => return false,
|
||||
Some(cat_id) => match cat_id {
|
||||
ChannelId(547551264498515978) => return true,
|
||||
ChannelId(884698356360818708) => return true,
|
||||
_ => return false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn paginator(input: Vec<String>, chunk_size: usize, join_string: String) -> Vec<String> {
|
||||
if input.len() == 0 {
|
||||
|
|
147
src/main.rs
147
src/main.rs
|
@ -35,65 +35,57 @@ lazy_static! {
|
|||
owners_only=true,
|
||||
)]
|
||||
async fn register(ctx: Context<'_>, #[flag] global: bool) -> Result<(), Error> {
|
||||
poise::builtins::register_application_commands(ctx, global).await?;
|
||||
// poise::builtins::register_application_commands(ctx, global).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Boop the bot!
|
||||
#[poise::command(prefix_command, track_edits, slash_command)]
|
||||
pub async fn boop(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let uuid_boop = ctx.id();
|
||||
|
||||
ctx.send(|m| {
|
||||
m.content("I want some boops! 🐇").components(|c| {
|
||||
c.create_action_row(|ar| {
|
||||
ar.create_button(|b| {
|
||||
b.style(serenity::ButtonStyle::Primary)
|
||||
.label("Boop me!")
|
||||
.custom_id(uuid_boop)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
let mut boop_count = 0;
|
||||
while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
|
||||
.channel_id(ctx.channel_id())
|
||||
.timeout(std::time::Duration::from_secs(1200))
|
||||
.filter(move |mci| mci.data.custom_id == uuid_boop.to_string())
|
||||
.await
|
||||
{
|
||||
boop_count += 1;
|
||||
|
||||
let mut msg = mci.message.clone();
|
||||
msg.edit(ctx.discord(), |m| {
|
||||
m.content(match &boop_count {
|
||||
2 => "Boop count: <:HamSmile:738765923401596991>".to_string(),
|
||||
42 => "Boop count: 42, but what is the question?".to_string(),
|
||||
43 => "Boop count: 43 A wild <@230001507481681920> appeared".to_string(),
|
||||
69 => "Boop count: 69 Nice!".to_string(),
|
||||
77 => "Boop count: 77 <@547041420733841409> Aproved".to_string(),
|
||||
308 => "Redirect 308: Boop count is in another castle".to_string(),
|
||||
400 => "ERROR 400: Bad booping".to_string(),
|
||||
401 => "ERROR 401: Unauthorized booping".to_string(),
|
||||
402 => "ERROR 402: Payment required, no free boops".to_string(),
|
||||
403 => "ERROR 403: Forbidden boop".to_string(),
|
||||
404 => "ERROR 404: Boop count not found".to_string(),
|
||||
420 => "Boop count: 420 Blaze it".to_string(),
|
||||
666 => "Boop count: 666 😈".to_string(),
|
||||
777 => "Boop count: 777 A wild <@117992484310745097> appeared".to_string(),
|
||||
_ => format!("Boop count: {}", boop_count),
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
mci.create_interaction_response(ctx.discord(), |ir| {
|
||||
ir.kind(serenity::InteractionResponseType::DeferredUpdateMessage)
|
||||
})
|
||||
.await?;
|
||||
let mut commands_builder = serenity::CreateApplicationCommands::default();
|
||||
let commands = &ctx.framework().options().commands;
|
||||
for command in commands {
|
||||
if let Some(slash_command) = command.create_as_slash_command() {
|
||||
commands_builder.add_application_command(slash_command);
|
||||
}
|
||||
if let Some(context_menu_command) = command.create_as_context_menu_command() {
|
||||
commands_builder.add_application_command(context_menu_command);
|
||||
}
|
||||
}
|
||||
let commands_builder = serenity::json::Value::Array(commands_builder.0);
|
||||
|
||||
let is_bot_owner = ctx.framework().options().owners.contains(&ctx.author().id);
|
||||
if global {
|
||||
if !is_bot_owner {
|
||||
ctx.say("Can only be used by bot owner").await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ctx.say(format!("Registering {} commands...", commands.len()))
|
||||
.await?;
|
||||
ctx.discord()
|
||||
.http
|
||||
.create_global_application_commands(&commands_builder)
|
||||
.await?;
|
||||
} else {
|
||||
let guild = match ctx.guild() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
ctx.say("Must be called in guild").await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let is_guild_owner = ctx.author().id == guild.owner_id;
|
||||
|
||||
if !is_guild_owner && !is_bot_owner {
|
||||
ctx.say("Can only be used by server owner").await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ctx.say(format!("Registering {} commands...", commands.len()))
|
||||
.await?;
|
||||
ctx.discord()
|
||||
.http
|
||||
.create_guild_application_commands(guild.id.0, &commands_builder)
|
||||
.await?;
|
||||
}
|
||||
|
||||
ctx.say("Done!").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -162,8 +154,8 @@ async fn app() -> Result<(), Error> {
|
|||
let prefix: String = discord
|
||||
.get("prefix")
|
||||
.expect("Config error, please set the discord[token] value")
|
||||
.clone()
|
||||
.into_str()
|
||||
.to_owned()
|
||||
.try_into()
|
||||
.expect("Config error, please make sure discord[token] is a string");
|
||||
let options = poise::FrameworkOptions {
|
||||
commands: vec![
|
||||
|
@ -173,16 +165,7 @@ async fn app() -> Result<(), Error> {
|
|||
commands::schedule::schedule(),
|
||||
commands::boop(),
|
||||
commands::planning::get_command(),
|
||||
// poise::Command {
|
||||
// subcommands: vec![
|
||||
// commands::planning::series(),
|
||||
// commands::planning::sessions(),
|
||||
// commands::planning::events(),
|
||||
// // Let's make sure poise isn't confused by the duplicate names!
|
||||
// // commands::planning::planning(),
|
||||
// ],
|
||||
// ..commands::planning::planning()
|
||||
// },
|
||||
commands::get_links(),
|
||||
],
|
||||
prefix_options: poise::PrefixFrameworkOptions {
|
||||
prefix: Some(prefix.into()),
|
||||
|
@ -247,7 +230,31 @@ async fn main() {
|
|||
setup_config().unwrap();
|
||||
// env_logger::init();
|
||||
// init_log();
|
||||
SimpleLogger::init(LevelFilter::Warn, simplelog::Config::default()).unwrap();
|
||||
let log_default = LevelFilter::Warn;
|
||||
let logger = match SETTINGS
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_table("logging")
|
||||
.unwrap_or_default()
|
||||
.get("level")
|
||||
{
|
||||
Some(val) => match val.clone().into_str() {
|
||||
Ok(level) => match level.to_lowercase().as_str() {
|
||||
"trace" => LevelFilter::Trace,
|
||||
"debug" => LevelFilter::Debug,
|
||||
"info" => LevelFilter::Info,
|
||||
"warn" => LevelFilter::Warn,
|
||||
"error" => LevelFilter::Error,
|
||||
_ => log_default,
|
||||
},
|
||||
_ => log_default,
|
||||
},
|
||||
_ => log_default,
|
||||
};
|
||||
|
||||
println!("Logging level: {:?}", logger);
|
||||
|
||||
SimpleLogger::init(logger, simplelog::Config::default()).unwrap();
|
||||
|
||||
if let Err(e) = app().await {
|
||||
log::error!("{}", e);
|
||||
|
|
Loading…
Reference in a new issue