basic gifs implementation
This commit is contained in:
parent
3d21ccbb75
commit
982dd7df48
6 changed files with 89 additions and 38 deletions
|
@ -19,6 +19,7 @@ chrono = "0.4.31"
|
||||||
sqlx = {version="0.7.3", features=["runtime-tokio", "sqlite"]}
|
sqlx = {version="0.7.3", features=["runtime-tokio", "sqlite"]}
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
reqwest = "0.11.24"
|
reqwest = "0.11.24"
|
||||||
|
form_urlencoded = "1.2.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
DEBUG = []
|
DEBUG = []
|
||||||
|
|
|
@ -14,8 +14,6 @@ use message_handler::handle;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
// use chrono::Utc;
|
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ impl EventHandler for Handler {
|
||||||
use util::debug::hello;
|
use util::debug::hello;
|
||||||
hello(ctx.http.clone()).await;
|
hello(ctx.http.clone()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sched = JobScheduler::new().await.unwrap();
|
let sched = JobScheduler::new().await.unwrap();
|
||||||
|
|
||||||
let job_closure = move |_, _| -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
let job_closure = move |_, _| -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use chrono::{Datelike, Local};
|
||||||
|
|
||||||
use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, client::Context, http::Http, model::Colour};
|
use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, client::Context, http::Http, model::Colour};
|
||||||
|
|
||||||
use anyhow::Ok;
|
// use anyhow::Ok;
|
||||||
|
|
||||||
use sqlx::{Connection, FromRow, SqliteConnection};
|
use sqlx::{Connection, FromRow, SqliteConnection};
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ use crate::util::utilities;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use super::{tenor, tenor_builder::Tenor, tenor_types::{ContentFilter, MediaFilter}};
|
||||||
|
|
||||||
// pub async fn notice_wrapper(http: Arc<Http>) {
|
// pub async fn notice_wrapper(http: Arc<Http>) {
|
||||||
pub async fn notice_wrapper(ctx: Context) {
|
pub async fn notice_wrapper(ctx: Context) {
|
||||||
match notice(ctx.http.clone()).await {
|
match notice(ctx.http.clone()).await {
|
||||||
|
@ -24,6 +26,7 @@ pub async fn notice_wrapper(ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
|
|
||||||
let mut event_embed = CreateEmbed::new()
|
let mut event_embed = CreateEmbed::new()
|
||||||
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
||||||
.title("Today's event is:");
|
.title("Today's event is:");
|
||||||
|
@ -45,13 +48,35 @@ async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, ht
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
|
|
||||||
|
const LIMIT: u8 = 20;
|
||||||
|
|
||||||
|
let tenor_response = Tenor::new()
|
||||||
|
.random(true)
|
||||||
|
.contentfilter(ContentFilter::low)
|
||||||
|
.add_media_filter(MediaFilter::gif)
|
||||||
|
.search("vsetko najlepsie").await?;
|
||||||
|
|
||||||
|
let index = rand::random::<usize>() % LIMIT as usize;
|
||||||
|
let gif_url = match tenor::get_gif_url(MediaFilter::gif, tenor_response) {
|
||||||
|
Ok(urls) => Some(urls),
|
||||||
|
Err(e) => {
|
||||||
|
send_error(http.clone(), e.to_string()).await;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?;
|
let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?;
|
||||||
|
|
||||||
let embed = CreateEmbed::new()
|
let mut embed = CreateEmbed::new()
|
||||||
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
.color(Colour::new(rand::random::<u32>() % 0xFFFFFF))
|
||||||
.title(format!("HAPPY BIRTHDAY {}!", nick))
|
.title(format!("HAPPY BIRTHDAY {}!", nick))
|
||||||
.description(format!("<@{}>'s birthday is today!!! Yay!", user_id.get()));
|
.description(format!("<@{}>'s birthday is today!!! Yay!", user_id.get()));
|
||||||
|
|
||||||
|
if gif_url.is_some() {
|
||||||
|
embed = embed.image(gif_url.unwrap()[index].as_str());
|
||||||
|
}
|
||||||
|
|
||||||
system_channel.send_message(http.clone(), CreateMessage::new().add_embed(embed.clone())).await?;
|
system_channel.send_message(http.clone(), CreateMessage::new().add_embed(embed.clone())).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -90,19 +115,19 @@ async fn notice(http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
"SELECT id, nick FROM birthdays
|
"SELECT id, nick FROM birthdays
|
||||||
WHERE day=? AND month=?;"
|
WHERE day=? AND month=?;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
.bind(month)
|
.bind(month)
|
||||||
.fetch_all(&mut db)
|
.fetch_all(&mut db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let global_events = sqlx::query_as::<_, EventRow>(
|
let global_events = sqlx::query_as::<_, EventRow>(
|
||||||
"SELECT id, guild, name, year, special_message from events
|
"SELECT id, guild, name, year, special_message from events
|
||||||
WHERE day=? AND month=? AND guild=0;"
|
WHERE day=? AND month=? AND guild=0;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
.bind(month)
|
.bind(month)
|
||||||
.fetch_all(&mut db)
|
.fetch_all(&mut db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let guilds = http.get_guilds(None, None).await?;
|
let guilds = http.get_guilds(None, None).await?;
|
||||||
|
|
||||||
|
@ -127,18 +152,18 @@ async fn notice(http: Arc<Http>) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let global_events = sqlx::query_as::<_, EventRow>(
|
let guild_events = sqlx::query_as::<_, EventRow>(
|
||||||
"SELECT id, guild, name, year, special_message from events
|
"SELECT id, guild, name, year, special_message from events
|
||||||
WHERE day=? AND month=? AND guild!=0;"
|
WHERE day=? AND month=? AND guild!=0;"
|
||||||
)
|
)
|
||||||
.bind(day)
|
.bind(day)
|
||||||
.bind(month)
|
.bind(month)
|
||||||
.fetch_all(&mut db)
|
.fetch_all(&mut db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// TODO if has year delete it from announce and delete
|
// TODO if has year delete it from announce and delete
|
||||||
|
|
||||||
for e in &global_events {
|
for e in &guild_events {
|
||||||
announce_event(GuildId::new(e.guild), e.name.as_str(), e.special_message.as_str(), http.clone()).await?;
|
announce_event(GuildId::new(e.guild), e.name.as_str(), e.special_message.as_str(), http.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
use super::tenor_types::MediaFilter;
|
||||||
|
|
||||||
|
use json::JsonValue;
|
||||||
|
|
||||||
|
pub fn get_gif_url(filter: MediaFilter, tenor_response: JsonValue) -> anyhow::Result<Vec<String>> {
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
|
let mut urls: Vec<String> = Vec::new();
|
||||||
|
let results = tenor_response["results"].members();
|
||||||
|
|
||||||
|
for result in results {
|
||||||
|
let url = result["media_formats"][filter.to_string()]["url"].as_str().context("Value not found in Json")?;
|
||||||
|
urls.push(url.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(urls)
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
use std::{collections::hash_map::RandomState, fmt};
|
|
||||||
|
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -40,7 +38,7 @@ pub struct Tenor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tenor {
|
impl Tenor {
|
||||||
fn new(q: String) -> Self {
|
pub fn new() -> Self {
|
||||||
Tenor {
|
Tenor {
|
||||||
country: None,
|
country: None,
|
||||||
locale: None,
|
locale: None,
|
||||||
|
@ -54,31 +52,31 @@ impl Tenor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces current country with the passed one
|
/// Replaces current country with the passed one
|
||||||
fn country(mut self, country: String) -> Self {
|
pub fn country(mut self, country: String) -> Self {
|
||||||
self.country = Some(country);
|
self.country = Some(country);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces current locale with the passed one
|
/// Replaces current locale with the passed one
|
||||||
fn locale(mut self, locale: String) -> Self {
|
pub fn locale(mut self, locale: String) -> Self {
|
||||||
self.locale = Some(locale);
|
self.locale = Some(locale);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces current media_filter with the passed one
|
/// Replaces current media_filter with the passed one
|
||||||
fn media_filter(mut self, filter: HashSet<MediaFilter>) -> Self {
|
pub fn media_filter(mut self, filter: HashSet<MediaFilter>) -> Self {
|
||||||
self.media_filter = Some(filter);
|
self.media_filter = Some(filter);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces current contentfilter with the passed one
|
/// Replaces current contentfilter with the passed one
|
||||||
fn contentfilter(mut self, filter: ContentFilter) -> Self {
|
pub fn contentfilter(mut self, filter: ContentFilter) -> Self {
|
||||||
self.contentfilter = Some(filter);
|
self.contentfilter = Some(filter);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces current media_filter with the passed one
|
/// Replaces current media_filter with the passed one
|
||||||
fn add_media_filter(mut self, filter: MediaFilter) -> Self {
|
pub fn add_media_filter(mut self, filter: MediaFilter) -> Self {
|
||||||
if self.media_filter.is_none() {
|
if self.media_filter.is_none() {
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
set.insert(filter);
|
set.insert(filter);
|
||||||
|
@ -90,17 +88,17 @@ impl Tenor {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ar_range(mut self, range: ArRange) -> Self {
|
pub fn ar_range(mut self, range: ArRange) -> Self {
|
||||||
self.ar_range = Some(range);
|
self.ar_range = Some(range);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random(mut self, random: bool) -> Self {
|
pub fn random(mut self, random: bool) -> Self {
|
||||||
self.random = Some(random);
|
self.random = Some(random);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn limit(mut self, mut limit: u8) -> Self {
|
pub fn limit(mut self, mut limit: u8) -> Self {
|
||||||
if limit < 20 {
|
if limit < 20 {
|
||||||
limit = 20;
|
limit = 20;
|
||||||
}
|
}
|
||||||
|
@ -112,19 +110,21 @@ impl Tenor {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(mut self, pos: String) -> Self {
|
pub fn pos(mut self, pos: String) -> Self {
|
||||||
self.pos = Some(pos);
|
self.pos = Some(pos);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn search(self, query: String) -> Result<JsonValue, Error> {
|
pub async fn search(self, query: &str) -> Result<JsonValue, Error> {
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
|
let q: String = form_urlencoded::byte_serialize(query.as_bytes()).collect();
|
||||||
|
|
||||||
// TODO encode query for urls (replace special characters and stuff)
|
// TODO encode query for urls (replace special characters and stuff)
|
||||||
let base_url = "https://tenor.googleapis.com/v2/search?";
|
let base_url = "https://tenor.googleapis.com/v2/search?";
|
||||||
let api_key = dotenv_var("TENORV2").context("TENORV2 key not found in the .env")?;
|
let api_key = dotenv_var("TENORV2").context("TENORV2 key not found in the .env")?;
|
||||||
|
|
||||||
let mut request = format!("{base_url}q={query}&key={api_key}");
|
let mut request = format!("{base_url}q={q}&key={api_key}");
|
||||||
|
|
||||||
if self.country.is_some() {
|
if self.country.is_some() {
|
||||||
request.push_str(&format!("&country={}", self.country.unwrap()));
|
request.push_str(&format!("&country={}", self.country.unwrap()));
|
||||||
|
@ -134,10 +134,21 @@ impl Tenor {
|
||||||
request.push_str(&format!("&locale={}", self.locale.unwrap()));
|
request.push_str(&format!("&locale={}", self.locale.unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.media_filter.is_some() {
|
if self.contentfilter.is_some() {
|
||||||
// TODO implement
|
request.push_str(&format!("&contentfilter={}", self.contentfilter.unwrap()))
|
||||||
// self.media_filter_to_string()
|
}
|
||||||
// request.push_str();
|
|
||||||
|
if self.media_filter.is_some() && self.media_filter.as_ref().unwrap().len() > 0 {
|
||||||
|
request.push_str(
|
||||||
|
format!("&media_filter={}",
|
||||||
|
self.media_filter.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(",")
|
||||||
|
.as_str()
|
||||||
|
).as_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.ar_range.is_some() {
|
if self.ar_range.is_some() {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ContentFilter {
|
pub enum ContentFilter {
|
||||||
off,
|
off,
|
||||||
|
|
Loading…
Reference in a new issue