this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feature: adding sequence matcher helper

Signed-off-by: Nick Gerakines <12125+ngerakines@users.noreply.github.com>

+69 -10
+7 -2
src/bin/supercell.rs
··· 62 62 .flat_map(|(_, (_, allow))| allow.iter().cloned()) 63 63 .collect::<HashSet<String>>(); 64 64 65 - let cache = Cache::default(); 65 + let cache = Cache::new(20); 66 66 67 - let web_context = WebContext::new(pool.clone(), config.external_base.as_str(), feeds, cache.clone()); 67 + let web_context = WebContext::new( 68 + pool.clone(), 69 + config.external_base.as_str(), 70 + feeds, 71 + cache.clone(), 72 + ); 68 73 69 74 let app = build_router(web_context.clone()); 70 75
+3 -3
src/cache.rs
··· 43 43 } 44 44 45 45 impl Cache { 46 - pub(crate) fn new(page_size: u8) -> Self { 46 + pub fn new(page_size: u8) -> Self { 47 47 Self { 48 48 inner_cache: Arc::new(RwLock::new(InnerCache::new(page_size))), 49 49 } ··· 54 54 55 55 let feed_chunks = inner.cached_feeds.get(feed_id)?; 56 56 57 - if page as usize > feed_chunks.len() { 57 + if page > feed_chunks.len() { 58 58 return None; 59 59 } 60 60 61 61 feed_chunks.get(page).cloned() 62 62 } 63 63 64 + #[allow(clippy::ptr_arg)] 64 65 pub(crate) async fn update_feed(&self, feed_id: &str, posts: &Vec<String>) { 65 66 let mut inner = self.inner_cache.write().await; 66 67 ··· 136 137 .generate_popular(&feed.uri, gravity, *limit.as_ref()) 137 138 .await 138 139 { 139 - 140 140 tracing::error!(error = ?err, feed_uri = ?feed.uri, "failed to generate simple feed"); 141 141 } 142 142 }
+6 -4
src/http/handle_get_feed_skeleton.rs
··· 103 103 } 104 104 } 105 105 106 - let parsed_cursor = parse_cursor(feed_params.cursor).map(|value| value.clamp(0, 10000)).unwrap_or(0) as usize; 106 + let parsed_cursor = parse_cursor(feed_params.cursor) 107 + .map(|value| value.clamp(0, 10000)) 108 + .unwrap_or(0) as usize; 107 109 108 110 let posts = web_context.cache.get_posts(&feed_uri, parsed_cursor).await; 109 111 ··· 119 121 } 120 122 let posts = posts.unwrap(); 121 123 122 - let cursor = if posts.len() != 0 { 123 - Some((parsed_cursor + 1).to_string()) 124 - } else { 124 + let cursor = if posts.is_empty() { 125 125 Some(parsed_cursor.to_string()) 126 + } else { 127 + Some((parsed_cursor + 1).to_string()) 126 128 }; 127 129 128 130 let feed_item_views = posts
+38 -1
src/matcher.rs
··· 2 2 3 3 use serde_json_path::JsonPath; 4 4 5 - use rhai::{serde::to_dynamic, CustomType, Dynamic, Engine, Scope, TypeBuilder, AST}; 5 + use rhai::{ 6 + serde::to_dynamic, Array, CustomType, Dynamic, Engine, ImmutableString, Scope, TypeBuilder, AST, 7 + }; 6 8 use std::{collections::HashMap, path::PathBuf, str::FromStr}; 7 9 8 10 use crate::config; ··· 276 278 } 277 279 } 278 280 281 + pub fn matcher_sequence_matches(sequence: Array, text: ImmutableString) -> bool { 282 + let sequence = sequence 283 + .iter() 284 + .filter_map(|value| value.clone().try_cast::<String>()) 285 + .collect::<Vec<String>>(); 286 + sequence_matches(sequence.as_ref(), &text) 287 + } 288 + 289 + fn sequence_matches(sequence: &[String], text: &str) -> bool { 290 + let mut last_found: i32 = -1; 291 + 292 + let mut found_index = 0; 293 + for (index, expected) in sequence.iter().enumerate() { 294 + if let Some(current_found) = text.find(expected) { 295 + if (current_found as i32) > last_found { 296 + last_found = current_found as i32; 297 + found_index = index; 298 + } else { 299 + last_found = -1; 300 + break; 301 + } 302 + } else { 303 + last_found = -1; 304 + break; 305 + } 306 + } 307 + last_found != -1 && found_index == sequence.len() - 1 308 + } 309 + 279 310 fn extract_aturi(aturi: Option<&JsonPath>, event_value: &serde_json::Value) -> Option<String> { 280 311 if let Some(aturi_path) = aturi { 281 312 let nodes = aturi_path.query(event_value).all(); ··· 358 389 engine 359 390 .build_type::<Match>() 360 391 .register_fn("build_aturi", build_aturi) 392 + .register_fn("sequence_matches", matcher_sequence_matches) 361 393 .register_fn("update_match", Match::update) 362 394 .register_fn("upsert_match", Match::upsert); 363 395 let ast = engine ··· 680 712 "at://did:plc:cbkjy5n7bk3ax2wplmtjofq2/app.bsky.feed.post/3laadb7behk25", 681 713 ), 682 714 ("rhai_match_reply_root.rhai", false, ""), 715 + ( 716 + "rhai_match_sequence.rhai", 717 + true, 718 + "at://did:plc:cbkjy5n7bk3ax2wplmtjofq2/app.bsky.feed.post/3laadb7behk25", 719 + ), 683 720 ], 684 721 ), 685 722 (
+15
testdata/rhai_match_sequence.rhai
··· 1 + let rtype = event?.commit?.record["$type"]; 2 + 3 + switch rtype { 4 + "app.bsky.feed.post" => { 5 + let text = event?.commit?.record?.text ?? ""; 6 + let found = sequence_matches(["feed", "generator"], text.to_lower()); 7 + if found { 8 + return build_aturi(event); 9 + } 10 + } 11 + // noop 12 + _ => { } 13 + } 14 + 15 + false