Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Build

on:
push:
# On main, it's the build and release that will run
branches-ignore: [ "main" ]
pull_request:
branches:
- main

jobs:
detect-changes:
Expand Down Expand Up @@ -42,6 +42,8 @@ jobs:
- uses: actions/checkout@v3

- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true

- name: 🧯 - Check for compile errors
run: cargo check
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ example.json
schema.json

docker/.data

test-locally.sh
9 changes: 8 additions & 1 deletion src/agenda_cultural/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_retry::policies::ExponentialBackoff;
use reqwest_retry::RetryTransientMiddleware;
use scraper::{Html, Selector};
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::ops::Add;
use std::time::Duration;
use std::{cmp::Ordering, error::Error};
use tracing::{debug, error, info, instrument, trace, warn};
use voca_rs::strip::strip_tags;

Expand Down Expand Up @@ -169,6 +169,13 @@ impl AgendaCulturalAPI {
.get(format!("{}/{}", AGENDA_EVENTS_URL, event_id))
.send()
.await
.inspect_err(|err| {
error!(
"Failed with status {} source {}",
err.status().unwrap_or_default(),
err.source().unwrap()
)
})
.expect("Error sending request")
.error_for_status()
.expect("Request failed")
Expand Down
25 changes: 21 additions & 4 deletions src/discord/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,18 +236,35 @@ impl DiscordAPI {
.join(" ");
let message_content = format!("Interessados: {}", mentions);

if saved_for_later_user_ids.is_empty() && message.pinned {
message
.unpin(&self.client.http)
.await
.expect("Failed to unpin no longer saved for later message!");
}

if !saved_for_later_user_ids.is_empty() && !message.pinned {
message
.pin(&self.client.http)
.await
.expect("Failed to pin saved for later message!");
}

if message_content.trim() == message.content.trim() {
trace!("No new users saved for later");
return;
}

info!("Saved for later changed to '{}'", mentions);

let mut edit_message = EditMessage::new().content(message_content);

if saved_for_later_user_ids.is_empty() {
edit_message = edit_message.content("");
}

message
.edit(
&self.client.http,
EditMessage::new().content(message_content),
)
.edit(&self.client.http, edit_message)
.await
.expect("Failed to edit message!");
}
Expand Down
15 changes: 12 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async fn main() {
Category::Teatro,
config.teatro_channel_id,
)
.await;
.await;
}

if let Some((controller, join_handle)) = loki_controller {
Expand Down Expand Up @@ -103,10 +103,19 @@ async fn handle_reaction_features(

info!(
"Tagging save for later and sending votes in DM (on thread '{}' with {} messages)",
thread.name, messages.len()
thread.name,
messages.len()
);

for mut message in messages {
if message.author != *discord.own_user {
debug!(
"Ignoring message from a different user {}",
message.author.id
);
continue;
}

if message.embeds.is_empty() {
warn!(
"Found message without embed (id={}; content={})",
Expand Down Expand Up @@ -159,7 +168,7 @@ async fn send_new_events(

if debug_config.skip_feature_reactions {
info!("Skipping feature reactions");
continue
continue;
}

add_feature_reactions(discord, &message, emojis, *SAVE_FOR_LATER_EMOJI).await;
Expand Down
27 changes: 10 additions & 17 deletions tests/agenda_cultural_api_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ mod agenda_cultural {
let event: Event = AgendaCulturalAPI::get_event_by_id(208058).await.unwrap();

assert_eq!(event.title, "Nora Helmer");
assert!(event.details.description.starts_with("A história de Nora Helmer, protagonista de Casa de Bonecas, peça de Henrik Ibsen"));
assert!(event.details.description.starts_with(
"A história de Nora Helmer, protagonista de Casa de Bonecas, peça de Henrik Ibsen"
));
assert_eq!(event.details.image_url, "https://www.agendalx.pt/content/uploads/2025/02/Nora-Helmer_ensaios2©Filipe_Figueiredo.jpg");
assert_eq!(
event.details.subtitle,
Expand All @@ -84,8 +86,8 @@ mod agenda_cultural {
let event: Event = AgendaCulturalAPI::get_event_by_public_url(
"https://www.agendalx.pt/events/event/o-monte/",
)
.await
.unwrap();
.await
.unwrap();

assert_eq!(event.title, "O Monte");
assert!(event.details.description.starts_with("A partir de um texto de João Ascenso, O Monte é inspirado no relato da atriz Luísa Ortigoso sobre um ex-preso político que reencontra o seu torturador anos após a ditadura."));
Expand All @@ -94,10 +96,7 @@ mod agenda_cultural {
"https://www.agendalx.pt/content/uploads/2025/03/omonte.jpg"
);
assert_eq!(event.details.subtitle, "Teatro Livre");
assert_eq!(
event.link,
"https://www.agendalx.pt/events/event/o-monte/"
);
assert_eq!(event.link, "https://www.agendalx.pt/events/event/o-monte/");
assert_eq!(event.occurring_at.dates, "24 abril a 4 maio");
assert_eq!(
event.occurring_at.times,
Expand All @@ -117,8 +116,8 @@ mod agenda_cultural {
let event: Event = AgendaCulturalAPI::get_event_by_public_url(
"https://www.agendalx.pt/events/event/um-sapato-especial/",
)
.await
.unwrap();
.await
.unwrap();

assert_eq!(event.title, "Um sapato especial");
assert!(event.details.description.starts_with("O Ursinho José gosta muito de ir brincar para o jardim. Joga à bola, às corridas, anda de bicicleta e nos baloiços. E ele é o campeão dos saltos! Mas um dia acontece algo inesperado e começa um"));
Expand All @@ -132,16 +131,10 @@ mod agenda_cultural {
"https://www.agendalx.pt/events/event/um-sapato-especial/"
);
assert_eq!(event.occurring_at.dates, "14 junho");
assert_eq!(
event.occurring_at.times,
"16h00"
);
assert_eq!(event.occurring_at.times, "16h00");
assert_eq!(event.venue, "Fábrica Braço de Prata");
assert_eq!(event.tags.len(), 2);
assert_eq!(
event.tags,
["crianças", "famílias"]
);
assert_eq!(event.tags, ["crianças", "famílias"]);
assert!(event.is_for_children);
}
}
18 changes: 10 additions & 8 deletions tests/discord_api_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ mod discord {
}

#[test_log::test(tokio::test)]
async fn when_someone_reacts_with_save_later_should_add_that_person_to_message() {
async fn when_someone_reacts_with_save_later_should_add_that_person_to_message_and_pin_it() {
let api = build_api().await;
let (thread_id, link, mut message) = send_random_event(
&api,
Expand Down Expand Up @@ -118,17 +118,18 @@ mod discord {

assert!(saved_later.contains(tester_api.own_user.id.to_string().as_str()));
assert!(!saved_later.contains(api.own_user.id.to_string().as_str()));
assert!(message.pinned);
}

#[test_log::test(tokio::test)]
async fn when_someone_removes_save_for_later_react_should_add_remove_that_person_from_the_message(
async fn when_someone_removes_save_for_later_react_should_emove_that_person_from_the_message_and_unpin_it(
) {
let api = build_api().await;
let (thread_id, _, mut message) =
send_random_event(
&api,
"when_someone_removes_save_for_later_react_should_add_remove_that_person_from_the_message"
).await;
let (thread_id, _, mut message) = send_random_event(
&api,
"when_someone_removes_save_for_later_react_should_remove_that_person_from_the_message",
)
.await;

api.add_reaction_to_message(&message, *SAVE_FOR_LATER_EMOJI)
.await;
Expand Down Expand Up @@ -163,7 +164,6 @@ mod discord {
let message = tester_api
.client
.http
.clone()
.get_message(thread_id, message.id)
.await
.unwrap();
Expand All @@ -172,6 +172,8 @@ mod discord {

assert!(!saved_later.contains(tester_api.own_user.id.to_string().as_str()));
assert!(!saved_later.contains(api.own_user.id.to_string().as_str()));
assert!(saved_later.is_empty());
assert!(!message.pinned);
}

#[test_log::test(tokio::test)]
Expand Down
Loading