Merge pull request 'allow timeline manipulation from plm' (#1113) from timeline-cli into main
Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/1113 Reviewed-by: KitaitiMakoto <kitaitimakoto@noreply@joinplu.me>
This commit is contained in:
		
						commit
						97cbe7f446
					
				
							
								
								
									
										262
									
								
								plume-cli/src/list.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								plume-cli/src/list.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,262 @@ | ||||
| use clap::{App, Arg, ArgMatches, SubCommand}; | ||||
| 
 | ||||
| use plume_models::{blogs::Blog, instance::Instance, lists::*, users::User, Connection}; | ||||
| 
 | ||||
| pub fn command<'a, 'b>() -> App<'a, 'b> { | ||||
|     SubCommand::with_name("lists") | ||||
|         .about("Manage lists") | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("new") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of this list"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("type") | ||||
|                         .short("t") | ||||
|                         .long("type") | ||||
|                         .takes_value(true) | ||||
|                         .help( | ||||
|                             r#"The type of this list (one of "user", "blog", "word" or "prefix")"#, | ||||
|                         ), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help("Username of whom this list is for. Empty for an instance list"), | ||||
|                 ) | ||||
|                 .about("Create a new list"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("delete") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the list to delete"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help("Username of whom this list was for. Empty for instance list"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("yes") | ||||
|                         .short("y") | ||||
|                         .long("yes") | ||||
|                         .help("Confirm the deletion"), | ||||
|                 ) | ||||
|                 .about("Delete a list"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("add") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the list to add an element to"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help("Username of whom this list is for. Empty for instance list"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("value") | ||||
|                         .short("v") | ||||
|                         .long("value") | ||||
|                         .takes_value(true) | ||||
|                         .help("The value to add"), | ||||
|                 ) | ||||
|                 .about("Add element to a list"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("rm") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the list to remove an element from"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help("Username of whom this list is for. Empty for instance list"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("value") | ||||
|                         .short("v") | ||||
|                         .long("value") | ||||
|                         .takes_value(true) | ||||
|                         .help("The value to remove"), | ||||
|                 ) | ||||
|                 .about("Remove element from list"), | ||||
|         ) | ||||
| } | ||||
| 
 | ||||
| pub fn run<'a>(args: &ArgMatches<'a>, conn: &Connection) { | ||||
|     let conn = conn; | ||||
|     match args.subcommand() { | ||||
|         ("new", Some(x)) => new(x, conn), | ||||
|         ("delete", Some(x)) => delete(x, conn), | ||||
|         ("add", Some(x)) => add(x, conn), | ||||
|         ("rm", Some(x)) => rm(x, conn), | ||||
|         ("", None) => command().print_help().unwrap(), | ||||
|         _ => println!("Unknown subcommand"), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_list_identifier(args: &ArgMatches<'_>) -> (String, Option<String>) { | ||||
|     let name = args | ||||
|         .value_of("name") | ||||
|         .map(String::from) | ||||
|         .expect("No name provided for the list"); | ||||
|     let user = args.value_of("user").map(String::from); | ||||
|     (name, user) | ||||
| } | ||||
| 
 | ||||
| fn get_list_type(args: &ArgMatches<'_>) -> ListType { | ||||
|     let typ = args | ||||
|         .value_of("type") | ||||
|         .map(String::from) | ||||
|         .expect("No name type for the list"); | ||||
|     match typ.as_str() { | ||||
|         "user" => ListType::User, | ||||
|         "blog" => ListType::Blog, | ||||
|         "word" => ListType::Word, | ||||
|         "prefix" => ListType::Prefix, | ||||
|         _ => panic!("Invalid list type: {}", typ), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_value(args: &ArgMatches<'_>) -> String { | ||||
|     args.value_of("value") | ||||
|         .map(String::from) | ||||
|         .expect("No query provided") | ||||
| } | ||||
| 
 | ||||
| fn resolve_user(username: &str, conn: &Connection) -> User { | ||||
|     let instance = Instance::get_local_uncached(conn).expect("Failed to load local instance"); | ||||
| 
 | ||||
|     User::find_by_name(conn, username, instance.id).expect("User not found") | ||||
| } | ||||
| 
 | ||||
| fn new(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_list_identifier(args); | ||||
|     let typ = get_list_type(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     List::new(conn, &name, user.as_ref(), typ).expect("failed to create list"); | ||||
| } | ||||
| 
 | ||||
| fn delete(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_list_identifier(args); | ||||
| 
 | ||||
|     if !args.is_present("yes") { | ||||
|         panic!("Warning, this operation is destructive. Add --yes to confirm you want to do it.") | ||||
|     } | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let list = | ||||
|         List::find_for_user_by_name(conn, user.map(|u| u.id), &name).expect("list not found"); | ||||
| 
 | ||||
|     list.delete(conn).expect("Failed to update list"); | ||||
| } | ||||
| 
 | ||||
| fn add(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_list_identifier(args); | ||||
|     let value = get_value(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let list = | ||||
|         List::find_for_user_by_name(conn, user.map(|u| u.id), &name).expect("list not found"); | ||||
| 
 | ||||
|     match list.kind() { | ||||
|         ListType::Blog => { | ||||
|             let blog_id = Blog::find_by_fqn(conn, &value).expect("unknown blog").id; | ||||
|             if !list.contains_blog(conn, blog_id).unwrap() { | ||||
|                 list.add_blogs(conn, &[blog_id]).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::User => { | ||||
|             let user_id = User::find_by_fqn(conn, &value).expect("unknown user").id; | ||||
|             if !list.contains_user(conn, user_id).unwrap() { | ||||
|                 list.add_users(conn, &[user_id]).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::Word => { | ||||
|             if !list.contains_word(conn, &value).unwrap() { | ||||
|                 list.add_words(conn, &[&value]).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::Prefix => { | ||||
|             if !list.contains_prefix(conn, &value).unwrap() { | ||||
|                 list.add_prefixes(conn, &[&value]).unwrap(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn rm(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_list_identifier(args); | ||||
|     let value = get_value(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let list = | ||||
|         List::find_for_user_by_name(conn, user.map(|u| u.id), &name).expect("list not found"); | ||||
| 
 | ||||
|     match list.kind() { | ||||
|         ListType::Blog => { | ||||
|             let blog_id = Blog::find_by_fqn(conn, &value).expect("unknown blog").id; | ||||
|             let mut blogs = list.list_blogs(conn).unwrap(); | ||||
|             if let Some(index) = blogs.iter().position(|b| b.id == blog_id) { | ||||
|                 blogs.swap_remove(index); | ||||
|                 let blogs = blogs.iter().map(|b| b.id).collect::<Vec<_>>(); | ||||
|                 list.set_blogs(conn, &blogs).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::User => { | ||||
|             let user_id = User::find_by_fqn(conn, &value).expect("unknown user").id; | ||||
|             let mut users = list.list_users(conn).unwrap(); | ||||
|             if let Some(index) = users.iter().position(|u| u.id == user_id) { | ||||
|                 users.swap_remove(index); | ||||
|                 let users = users.iter().map(|u| u.id).collect::<Vec<_>>(); | ||||
|                 list.set_users(conn, &users).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::Word => { | ||||
|             let mut words = list.list_words(conn).unwrap(); | ||||
|             if let Some(index) = words.iter().position(|w| *w == value) { | ||||
|                 words.swap_remove(index); | ||||
|                 let words = words.iter().map(String::as_str).collect::<Vec<_>>(); | ||||
|                 list.set_words(conn, &words).unwrap(); | ||||
|             } | ||||
|         } | ||||
|         ListType::Prefix => { | ||||
|             let mut prefixes = list.list_prefixes(conn).unwrap(); | ||||
|             if let Some(index) = prefixes.iter().position(|p| *p == value) { | ||||
|                 prefixes.swap_remove(index); | ||||
|                 let prefixes = prefixes.iter().map(String::as_str).collect::<Vec<_>>(); | ||||
|                 list.set_prefixes(conn, &prefixes).unwrap(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -4,8 +4,10 @@ use plume_models::{instance::Instance, Connection as Conn, CONFIG}; | ||||
| use std::io::{self, prelude::*}; | ||||
| 
 | ||||
| mod instance; | ||||
| mod list; | ||||
| mod migration; | ||||
| mod search; | ||||
| mod timeline; | ||||
| mod users; | ||||
| 
 | ||||
| fn main() { | ||||
| @ -16,6 +18,8 @@ fn main() { | ||||
|         .subcommand(instance::command()) | ||||
|         .subcommand(migration::command()) | ||||
|         .subcommand(search::command()) | ||||
|         .subcommand(timeline::command()) | ||||
|         .subcommand(list::command()) | ||||
|         .subcommand(users::command()); | ||||
|     let matches = app.clone().get_matches(); | ||||
| 
 | ||||
| @ -37,6 +41,10 @@ fn main() { | ||||
|         ("search", Some(args)) => { | ||||
|             search::run(args, &conn.expect("Couldn't connect to the database.")) | ||||
|         } | ||||
|         ("timeline", Some(args)) => { | ||||
|             timeline::run(args, &conn.expect("Couldn't connect to the database.")) | ||||
|         } | ||||
|         ("lists", Some(args)) => list::run(args, &conn.expect("Couldn't connect to the database.")), | ||||
|         ("users", Some(args)) => { | ||||
|             users::run(args, &conn.expect("Couldn't connect to the database.")) | ||||
|         } | ||||
|  | ||||
							
								
								
									
										257
									
								
								plume-cli/src/timeline.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								plume-cli/src/timeline.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,257 @@ | ||||
| use clap::{App, Arg, ArgMatches, SubCommand}; | ||||
| 
 | ||||
| use plume_models::{instance::Instance, posts::Post, timeline::*, users::*, Connection}; | ||||
| 
 | ||||
| pub fn command<'a, 'b>() -> App<'a, 'b> { | ||||
|     SubCommand::with_name("timeline") | ||||
|         .about("Manage public timeline") | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("new") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of this timeline"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("query") | ||||
|                         .short("q") | ||||
|                         .long("query") | ||||
|                         .takes_value(true) | ||||
|                         .help("The query posts in this timelines have to match"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help( | ||||
|                             "Username of whom this timeline is for. Empty for an instance timeline", | ||||
|                         ), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("preload-count") | ||||
|                         .short("p") | ||||
|                         .long("preload-count") | ||||
|                         .takes_value(true) | ||||
|                         .help("Number of posts to try to preload in this timeline at its creation"), | ||||
|                 ) | ||||
|                 .about("Create a new timeline"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("delete") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the timeline to delete"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help( | ||||
|                             "Username of whom this timeline was for. Empty for instance timeline", | ||||
|                         ), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("yes") | ||||
|                         .short("y") | ||||
|                         .long("yes") | ||||
|                         .help("Confirm the deletion"), | ||||
|                 ) | ||||
|                 .about("Delete a timeline"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("edit") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the timeline to edit"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help("Username of whom this timeline is for. Empty for instance timeline"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("query") | ||||
|                         .short("q") | ||||
|                         .long("query") | ||||
|                         .takes_value(true) | ||||
|                         .help("The query posts in this timelines have to match"), | ||||
|                 ) | ||||
|                 .about("Edit the query of a timeline"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("repopulate") | ||||
|                 .arg( | ||||
|                     Arg::with_name("name") | ||||
|                         .short("n") | ||||
|                         .long("name") | ||||
|                         .takes_value(true) | ||||
|                         .help("The name of the timeline to repopulate"), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("user") | ||||
|                         .short("u") | ||||
|                         .long("user") | ||||
|                         .takes_value(true) | ||||
|                         .help( | ||||
|                             "Username of whom this timeline was for. Empty for instance timeline", | ||||
|                         ), | ||||
|                 ) | ||||
|                 .arg( | ||||
|                     Arg::with_name("preload-count") | ||||
|                         .short("p") | ||||
|                         .long("preload-count") | ||||
|                         .takes_value(true) | ||||
|                         .help("Number of posts to try to preload in this timeline at its creation"), | ||||
|                 ) | ||||
|                 .about("Repopulate a timeline. Run this after modifying a list the timeline depends on."), | ||||
|         ) | ||||
| } | ||||
| 
 | ||||
| pub fn run<'a>(args: &ArgMatches<'a>, conn: &Connection) { | ||||
|     let conn = conn; | ||||
|     match args.subcommand() { | ||||
|         ("new", Some(x)) => new(x, conn), | ||||
|         ("edit", Some(x)) => edit(x, conn), | ||||
|         ("delete", Some(x)) => delete(x, conn), | ||||
|         ("repopulate", Some(x)) => repopulate(x, conn), | ||||
|         ("", None) => command().print_help().unwrap(), | ||||
|         _ => println!("Unknown subcommand"), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_timeline_identifier(args: &ArgMatches<'_>) -> (String, Option<String>) { | ||||
|     let name = args | ||||
|         .value_of("name") | ||||
|         .map(String::from) | ||||
|         .expect("No name provided for the timeline"); | ||||
|     let user = args.value_of("user").map(String::from); | ||||
|     (name, user) | ||||
| } | ||||
| 
 | ||||
| fn get_query(args: &ArgMatches<'_>) -> String { | ||||
|     let query = args | ||||
|         .value_of("query") | ||||
|         .map(String::from) | ||||
|         .expect("No query provided"); | ||||
| 
 | ||||
|     match TimelineQuery::parse(&query) { | ||||
|         Ok(_) => (), | ||||
|         Err(QueryError::SyntaxError(start, end, message)) => panic!( | ||||
|             "Query parsing error between {} and {}: {}", | ||||
|             start, end, message | ||||
|         ), | ||||
|         Err(QueryError::UnexpectedEndOfQuery) => { | ||||
|             panic!("Query parsing error: unexpected end of query") | ||||
|         } | ||||
|         Err(QueryError::RuntimeError(message)) => panic!("Query parsing error: {}", message), | ||||
|     } | ||||
| 
 | ||||
|     query | ||||
| } | ||||
| 
 | ||||
| fn get_preload_count(args: &ArgMatches<'_>) -> usize { | ||||
|     args.value_of("preload-count") | ||||
|         .map(|arg| arg.parse().expect("invalid preload-count")) | ||||
|         .unwrap_or(plume_models::ITEMS_PER_PAGE as usize) | ||||
| } | ||||
| 
 | ||||
| fn resolve_user(username: &str, conn: &Connection) -> User { | ||||
|     let instance = Instance::get_local_uncached(conn).expect("Failed to load local instance"); | ||||
| 
 | ||||
|     User::find_by_name(conn, username, instance.id).expect("User not found") | ||||
| } | ||||
| 
 | ||||
| fn preload(timeline: Timeline, count: usize, conn: &Connection) { | ||||
|     timeline.remove_all_posts(conn).unwrap(); | ||||
| 
 | ||||
|     if count == 0 { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     let mut posts = Vec::with_capacity(count as usize); | ||||
|     for post in Post::list_filtered(conn, None, None, None) | ||||
|         .unwrap() | ||||
|         .into_iter() | ||||
|         .rev() | ||||
|     { | ||||
|         if timeline.matches(conn, &post, Kind::Original).unwrap() { | ||||
|             posts.push(post); | ||||
|             if posts.len() >= count { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for post in posts.iter().rev() { | ||||
|         timeline.add_post(conn, post).unwrap(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn new(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_timeline_identifier(args); | ||||
|     let query = get_query(args); | ||||
|     let preload_count = get_preload_count(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let timeline = if let Some(user) = user { | ||||
|         Timeline::new_for_user(conn, user.id, name, query) | ||||
|     } else { | ||||
|         Timeline::new_for_instance(conn, name, query) | ||||
|     } | ||||
|     .expect("Failed to create new timeline"); | ||||
| 
 | ||||
|     preload(timeline, preload_count, conn); | ||||
| } | ||||
| 
 | ||||
| fn edit(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_timeline_identifier(args); | ||||
|     let query = get_query(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let mut timeline = Timeline::find_for_user_by_name(conn, user.map(|u| u.id), &name) | ||||
|         .expect("timeline not found"); | ||||
| 
 | ||||
|     timeline.query = query; | ||||
| 
 | ||||
|     timeline.update(conn).expect("Failed to update timeline"); | ||||
| } | ||||
| 
 | ||||
| fn delete(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_timeline_identifier(args); | ||||
| 
 | ||||
|     if !args.is_present("yes") { | ||||
|         panic!("Warning, this operation is destructive. Add --yes to confirm you want to do it.") | ||||
|     } | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let timeline = Timeline::find_for_user_by_name(conn, user.map(|u| u.id), &name) | ||||
|         .expect("timeline not found"); | ||||
| 
 | ||||
|     timeline.delete(conn).expect("Failed to update timeline"); | ||||
| } | ||||
| 
 | ||||
| fn repopulate(args: &ArgMatches<'_>, conn: &Connection) { | ||||
|     let (name, user) = get_timeline_identifier(args); | ||||
|     let preload_count = get_preload_count(args); | ||||
| 
 | ||||
|     let user = user.map(|user| resolve_user(&user, conn)); | ||||
| 
 | ||||
|     let timeline = Timeline::find_for_user_by_name(conn, user.map(|u| u.id), &name) | ||||
|         .expect("timeline not found"); | ||||
|     preload(timeline, preload_count, conn); | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     db_conn::DbConn, instance::*, medias::Media, posts::Post, safe_string::SafeString, | ||||
|     schema::blogs, users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, | ||||
|     instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs, users::User, | ||||
|     Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     actor::{ApActor, ApActorExt, AsApActor, Group}, | ||||
| @ -142,10 +142,10 @@ impl Blog { | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn find_by_fqn(conn: &DbConn, fqn: &str) -> Result<Blog> { | ||||
|     pub fn find_by_fqn(conn: &Connection, fqn: &str) -> Result<Blog> { | ||||
|         let from_db = blogs::table | ||||
|             .filter(blogs::fqn.eq(fqn)) | ||||
|             .first(&**conn) | ||||
|             .first(conn) | ||||
|             .optional()?; | ||||
|         if let Some(from_db) = from_db { | ||||
|             Ok(from_db) | ||||
| @ -154,7 +154,7 @@ impl Blog { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn fetch_from_webfinger(conn: &DbConn, acct: &str) -> Result<Blog> { | ||||
|     fn fetch_from_webfinger(conn: &Connection, acct: &str) -> Result<Blog> { | ||||
|         resolve_with_prefix(Prefix::Group, acct.to_owned(), true)? | ||||
|             .links | ||||
|             .into_iter() | ||||
| @ -372,15 +372,15 @@ impl IntoId for Blog { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Blog { | ||||
| impl FromId<Connection> for Blog { | ||||
|     type Error = Error; | ||||
|     type Object = CustomGroup; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Self::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, acct: CustomGroup) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, acct: CustomGroup) -> Result<Self> { | ||||
|         let (name, outbox_url, inbox_url) = { | ||||
|             let actor = acct.ap_actor_ref(); | ||||
|             let name = actor | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| use crate::{ | ||||
|     comment_seers::{CommentSeers, NewCommentSeers}, | ||||
|     db_conn::DbConn, | ||||
|     instance::Instance, | ||||
|     medias::Media, | ||||
|     mentions::Mention, | ||||
| @ -111,7 +110,7 @@ impl Comment { | ||||
|                 .unwrap_or(false) | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_activity(&self, conn: &DbConn) -> Result<Note> { | ||||
|     pub fn to_activity(&self, conn: &Connection) -> Result<Note> { | ||||
|         let author = User::get(conn, self.author_id)?; | ||||
|         let (html, mentions, _hashtags) = utils::md_to_html( | ||||
|             self.content.get().as_ref(), | ||||
| @ -149,7 +148,7 @@ impl Comment { | ||||
|         Ok(note) | ||||
|     } | ||||
| 
 | ||||
|     pub fn create_activity(&self, conn: &DbConn) -> Result<Create> { | ||||
|     pub fn create_activity(&self, conn: &Connection) -> Result<Create> { | ||||
|         let author = User::get(conn, self.author_id)?; | ||||
| 
 | ||||
|         let note = self.to_activity(conn)?; | ||||
| @ -217,15 +216,15 @@ impl Comment { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Comment { | ||||
| impl FromId<Connection> for Comment { | ||||
|     type Error = Error; | ||||
|     type Object = Note; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Self::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, note: Note) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, note: Note) -> Result<Self> { | ||||
|         let comm = { | ||||
|             let previous_url = note | ||||
|                 .in_reply_to() | ||||
| @ -354,21 +353,21 @@ impl FromId<DbConn> for Comment { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Create, &DbConn> for Comment { | ||||
| impl AsObject<User, Create, &Connection> for Comment { | ||||
|     type Error = Error; | ||||
|     type Output = Self; | ||||
| 
 | ||||
|     fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Self> { | ||||
|     fn activity(self, _conn: &Connection, _actor: User, _id: &str) -> Result<Self> { | ||||
|         // The actual creation takes place in the FromId impl
 | ||||
|         Ok(self) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Delete, &DbConn> for Comment { | ||||
| impl AsObject<User, Delete, &Connection> for Comment { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         if self.author_id != actor.id { | ||||
|             return Err(Error::Unauthorized); | ||||
|         } | ||||
| @ -387,8 +386,8 @@ impl AsObject<User, Delete, &DbConn> for Comment { | ||||
|         diesel::update(comments::table) | ||||
|             .filter(comments::in_response_to_id.eq(self.id)) | ||||
|             .set(comments::in_response_to_id.eq(self.in_response_to_id)) | ||||
|             .execute(&**conn)?; | ||||
|         diesel::delete(&self).execute(&**conn)?; | ||||
|             .execute(conn)?; | ||||
|         diesel::delete(&self).execute(conn)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     ap_url, db_conn::DbConn, instance::Instance, notifications::*, schema::follows, users::User, | ||||
|     Connection, Error, Result, CONFIG, | ||||
|     ap_url, instance::Instance, notifications::*, schema::follows, users::User, Connection, Error, | ||||
|     Result, CONFIG, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     activity::{Accept, ActorAndObjectRef, Follow as FollowAct, Undo}, | ||||
| @ -150,11 +150,11 @@ impl Follow { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, FollowAct, &DbConn> for User { | ||||
| impl AsObject<User, FollowAct, &Connection> for User { | ||||
|     type Error = Error; | ||||
|     type Output = Follow; | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Follow> { | ||||
|     fn activity(self, conn: &Connection, actor: User, id: &str) -> Result<Follow> { | ||||
|         // Mastodon (at least) requires the full Follow object when accepting it,
 | ||||
|         // so we rebuilt it here
 | ||||
|         let follow = FollowAct::new(actor.ap_url.parse::<IriString>()?, id.parse::<IriString>()?); | ||||
| @ -162,15 +162,15 @@ impl AsObject<User, FollowAct, &DbConn> for User { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Follow { | ||||
| impl FromId<Connection> for Follow { | ||||
|     type Error = Error; | ||||
|     type Object = FollowAct; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Follow::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, follow: FollowAct) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, follow: FollowAct) -> Result<Self> { | ||||
|         let actor = User::from_id( | ||||
|             conn, | ||||
|             follow | ||||
| @ -202,18 +202,18 @@ impl FromId<DbConn> for Follow { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Undo, &DbConn> for Follow { | ||||
| impl AsObject<User, Undo, &Connection> for Follow { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         let conn = conn; | ||||
|         if self.follower_id == actor.id { | ||||
|             diesel::delete(&self).execute(&**conn)?; | ||||
|             diesel::delete(&self).execute(conn)?; | ||||
| 
 | ||||
|             // delete associated notification if any
 | ||||
|             if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) { | ||||
|                 diesel::delete(¬if).execute(&**conn)?; | ||||
|                 diesel::delete(¬if).execute(conn)?; | ||||
|             } | ||||
| 
 | ||||
|             Ok(()) | ||||
|  | ||||
| @ -47,7 +47,7 @@ impl_into_inbox_result! { | ||||
| } | ||||
| 
 | ||||
| pub fn inbox(conn: &DbConn, act: serde_json::Value) -> Result<InboxResult, Error> { | ||||
|     Inbox::handle(conn, act) | ||||
|     Inbox::handle(&**conn, act) | ||||
|         .with::<User, Announce, Post>(CONFIG.proxy()) | ||||
|         .with::<User, Create, Comment>(CONFIG.proxy()) | ||||
|         .with::<User, Create, Post>(CONFIG.proxy()) | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     db_conn::DbConn, instance::Instance, notifications::*, posts::Post, schema::likes, timeline::*, | ||||
|     users::User, Connection, Error, Result, CONFIG, | ||||
|     instance::Instance, notifications::*, posts::Post, schema::likes, timeline::*, users::User, | ||||
|     Connection, Error, Result, CONFIG, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     activity::{ActorAndObjectRef, Like as LikeAct, Undo}, | ||||
| @ -85,11 +85,11 @@ impl Like { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, LikeAct, &DbConn> for Post { | ||||
| impl AsObject<User, LikeAct, &Connection> for Post { | ||||
|     type Error = Error; | ||||
|     type Output = Like; | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Like> { | ||||
|     fn activity(self, conn: &Connection, actor: User, id: &str) -> Result<Like> { | ||||
|         let res = Like::insert( | ||||
|             conn, | ||||
|             NewLike { | ||||
| @ -105,15 +105,15 @@ impl AsObject<User, LikeAct, &DbConn> for Post { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Like { | ||||
| impl FromId<Connection> for Like { | ||||
|     type Error = Error; | ||||
|     type Object = LikeAct; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Like::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, act: LikeAct) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, act: LikeAct) -> Result<Self> { | ||||
|         let res = Like::insert( | ||||
|             conn, | ||||
|             NewLike { | ||||
| @ -154,17 +154,17 @@ impl FromId<DbConn> for Like { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Undo, &DbConn> for Like { | ||||
| impl AsObject<User, Undo, &Connection> for Like { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         if actor.id == self.user_id { | ||||
|             diesel::delete(&self).execute(&**conn)?; | ||||
|             diesel::delete(&self).execute(conn)?; | ||||
| 
 | ||||
|             // delete associated notification if any
 | ||||
|             if let Ok(notif) = Notification::find(conn, notification_kind::LIKE, self.id) { | ||||
|                 diesel::delete(¬if).execute(&**conn)?; | ||||
|                 diesel::delete(¬if).execute(conn)?; | ||||
|             } | ||||
|             Ok(()) | ||||
|         } else { | ||||
|  | ||||
| @ -297,6 +297,28 @@ impl List { | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete(&self, conn: &Connection) -> Result<()> { | ||||
|         if let Some(user_id) = self.user_id { | ||||
|             diesel::delete( | ||||
|                 lists::table | ||||
|                     .filter(lists::user_id.eq(user_id)) | ||||
|                     .filter(lists::name.eq(&self.name)), | ||||
|             ) | ||||
|             .execute(conn) | ||||
|             .map(|_| ()) | ||||
|             .map_err(Error::from) | ||||
|         } else { | ||||
|             diesel::delete( | ||||
|                 lists::table | ||||
|                     .filter(lists::user_id.is_null()) | ||||
|                     .filter(lists::name.eq(&self.name)), | ||||
|             ) | ||||
|             .execute(conn) | ||||
|             .map(|_| ()) | ||||
|             .map_err(Error::from) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     func! {set: set_users, User, add_users} | ||||
|     func! {set: set_blogs, Blog, add_blogs} | ||||
|     func! {set: set_words, Word, add_words} | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     ap_url, db_conn::DbConn, instance::Instance, safe_string::SafeString, schema::medias, | ||||
|     users::User, Connection, Error, Result, CONFIG, | ||||
|     ap_url, instance::Instance, safe_string::SafeString, schema::medias, users::User, Connection, | ||||
|     Error, Result, CONFIG, | ||||
| }; | ||||
| use activitystreams::{object::Image, prelude::*}; | ||||
| use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; | ||||
| @ -206,7 +206,7 @@ impl Media { | ||||
|     } | ||||
| 
 | ||||
|     // TODO: merge with save_remote?
 | ||||
|     pub fn from_activity(conn: &DbConn, image: &Image) -> Result<Media> { | ||||
|     pub fn from_activity(conn: &Connection, image: &Image) -> Result<Media> { | ||||
|         let remote_url = image | ||||
|             .url() | ||||
|             .and_then(|url| url.to_as_uri()) | ||||
| @ -258,7 +258,7 @@ impl Media { | ||||
|                     updated = true; | ||||
|                 } | ||||
|                 if updated { | ||||
|                     diesel::update(&media).set(&media).execute(&**conn)?; | ||||
|                     diesel::update(&media).set(&media).execute(conn)?; | ||||
|                 } | ||||
|                 Ok(media) | ||||
|             }) | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     comments::Comment, db_conn::DbConn, notifications::*, posts::Post, schema::mentions, | ||||
|     users::User, Connection, Error, Result, | ||||
|     comments::Comment, notifications::*, posts::Post, schema::mentions, users::User, Connection, | ||||
|     Error, Result, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     base::BaseExt, | ||||
| @ -60,7 +60,7 @@ impl Mention { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn build_activity(conn: &DbConn, ment: &str) -> Result<link::Mention> { | ||||
|     pub fn build_activity(conn: &Connection, ment: &str) -> Result<link::Mention> { | ||||
|         let user = User::find_by_fqn(conn, ment)?; | ||||
|         let mut mention = link::Mention::new(); | ||||
|         mention.set_href(user.ap_url.parse::<IriString>()?); | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use crate::{ | ||||
|     ap_url, blogs::Blog, db_conn::DbConn, instance::Instance, medias::Media, mentions::Mention, | ||||
|     post_authors::*, safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User, | ||||
|     Connection, Error, PostEvent::*, Result, CONFIG, POST_CHAN, | ||||
|     ap_url, blogs::Blog, instance::Instance, medias::Media, mentions::Mention, post_authors::*, | ||||
|     safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User, Connection, Error, | ||||
|     PostEvent::*, Result, CONFIG, POST_CHAN, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     activity::{Create, Delete, Update}, | ||||
| @ -615,15 +615,15 @@ impl Post { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Post { | ||||
| impl FromId<Connection> for Post { | ||||
|     type Error = Error; | ||||
|     type Object = LicensedArticle; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Self::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, article: LicensedArticle) -> Result<Self> { | ||||
|         let license = article.ext_one.license.unwrap_or_default(); | ||||
|         let article = article.inner; | ||||
| 
 | ||||
| @ -821,21 +821,21 @@ impl FromId<DbConn> for Post { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Create, &DbConn> for Post { | ||||
| impl AsObject<User, Create, &Connection> for Post { | ||||
|     type Error = Error; | ||||
|     type Output = Self; | ||||
| 
 | ||||
|     fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Self::Output> { | ||||
|     fn activity(self, _conn: &Connection, _actor: User, _id: &str) -> Result<Self::Output> { | ||||
|         // TODO: check that _actor is actually one of the author?
 | ||||
|         Ok(self) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Delete, &DbConn> for Post { | ||||
| impl AsObject<User, Delete, &Connection> for Post { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<Self::Output> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<Self::Output> { | ||||
|         let can_delete = self | ||||
|             .get_authors(conn)? | ||||
|             .into_iter() | ||||
| @ -859,16 +859,16 @@ pub struct PostUpdate { | ||||
|     pub tags: Option<serde_json::Value>, | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for PostUpdate { | ||||
| impl FromId<Connection> for PostUpdate { | ||||
|     type Error = Error; | ||||
|     type Object = LicensedArticle; | ||||
| 
 | ||||
|     fn from_db(_: &DbConn, _: &str) -> Result<Self> { | ||||
|     fn from_db(_: &Connection, _: &str) -> Result<Self> { | ||||
|         // Always fail because we always want to deserialize the AP object
 | ||||
|         Err(Error::NotFound) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, updated: Self::Object) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, updated: Self::Object) -> Result<Self> { | ||||
|         let mut post_update = PostUpdate { | ||||
|             ap_url: updated | ||||
|                 .ap_object_ref() | ||||
| @ -923,11 +923,11 @@ impl FromId<DbConn> for PostUpdate { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Update, &DbConn> for PostUpdate { | ||||
| impl AsObject<User, Update, &Connection> for PostUpdate { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         let mut post = | ||||
|             Post::from_id(conn, &self.ap_url, None, CONFIG.proxy()).map_err(|(_, e)| e)?; | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     db_conn::DbConn, instance::Instance, notifications::*, posts::Post, schema::reshares, | ||||
|     timeline::*, users::User, Connection, Error, Result, CONFIG, | ||||
|     instance::Instance, notifications::*, posts::Post, schema::reshares, timeline::*, users::User, | ||||
|     Connection, Error, Result, CONFIG, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     activity::{ActorAndObjectRef, Announce, Undo}, | ||||
| @ -113,11 +113,11 @@ impl Reshare { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Announce, &DbConn> for Post { | ||||
| impl AsObject<User, Announce, &Connection> for Post { | ||||
|     type Error = Error; | ||||
|     type Output = Reshare; | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Reshare> { | ||||
|     fn activity(self, conn: &Connection, actor: User, id: &str) -> Result<Reshare> { | ||||
|         let conn = conn; | ||||
|         let reshare = Reshare::insert( | ||||
|             conn, | ||||
| @ -134,15 +134,15 @@ impl AsObject<User, Announce, &DbConn> for Post { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<DbConn> for Reshare { | ||||
| impl FromId<Connection> for Reshare { | ||||
|     type Error = Error; | ||||
|     type Object = Announce; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Reshare::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, act: Announce) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, act: Announce) -> Result<Self> { | ||||
|         let res = Reshare::insert( | ||||
|             conn, | ||||
|             NewReshare { | ||||
| @ -183,17 +183,17 @@ impl FromId<DbConn> for Reshare { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Undo, &DbConn> for Reshare { | ||||
| impl AsObject<User, Undo, &Connection> for Reshare { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         if actor.id == self.user_id { | ||||
|             diesel::delete(&self).execute(&**conn)?; | ||||
|             diesel::delete(&self).execute(conn)?; | ||||
| 
 | ||||
|             // delete associated notification if any
 | ||||
|             if let Ok(notif) = Notification::find(conn, notification_kind::RESHARE, self.id) { | ||||
|                 diesel::delete(¬if).execute(&**conn)?; | ||||
|                 diesel::delete(¬if).execute(conn)?; | ||||
|             } | ||||
| 
 | ||||
|             Ok(()) | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| use crate::{ | ||||
|     db_conn::DbConn, | ||||
|     lists::List, | ||||
|     posts::Post, | ||||
|     schema::{posts, timeline, timeline_definition}, | ||||
| @ -12,7 +11,7 @@ use std::ops::Deref; | ||||
| pub(crate) mod query; | ||||
| 
 | ||||
| pub use self::query::Kind; | ||||
| use self::query::{QueryError, TimelineQuery}; | ||||
| pub use self::query::{QueryError, TimelineQuery}; | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq, Queryable, Identifiable, AsChangeset)] | ||||
| #[table_name = "timeline_definition"] | ||||
| @ -220,7 +219,7 @@ impl Timeline { | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_to_all_timelines(conn: &DbConn, post: &Post, kind: Kind<'_>) -> Result<()> { | ||||
|     pub fn add_to_all_timelines(conn: &Connection, post: &Post, kind: Kind<'_>) -> Result<()> { | ||||
|         let timelines = timeline_definition::table | ||||
|             .load::<Self>(conn.deref()) | ||||
|             .map_err(Error::from)?; | ||||
| @ -246,7 +245,26 @@ impl Timeline { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn matches(&self, conn: &DbConn, post: &Post, kind: Kind<'_>) -> Result<bool> { | ||||
|     pub fn remove_post(&self, conn: &Connection, post: &Post) -> Result<bool> { | ||||
|         if self.includes_post(conn, post)? { | ||||
|             return Ok(false); | ||||
|         } | ||||
|         diesel::delete( | ||||
|             timeline::table | ||||
|                 .filter(timeline::timeline_id.eq(self.id)) | ||||
|                 .filter(timeline::post_id.eq(post.id)), | ||||
|         ) | ||||
|         .execute(conn)?; | ||||
|         Ok(true) | ||||
|     } | ||||
| 
 | ||||
|     pub fn remove_all_posts(&self, conn: &Connection) -> Result<u64> { | ||||
|         let count = diesel::delete(timeline::table.filter(timeline::timeline_id.eq(self.id))) | ||||
|             .execute(conn)?; | ||||
|         Ok(count as u64) | ||||
|     } | ||||
| 
 | ||||
|     pub fn matches(&self, conn: &Connection, post: &Post, kind: Kind<'_>) -> Result<bool> { | ||||
|         let query = TimelineQuery::parse(&self.query)?; | ||||
|         query.matches(conn, self, post, kind) | ||||
|     } | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| use crate::{ | ||||
|     blogs::Blog, | ||||
|     db_conn::DbConn, | ||||
|     lists::{self, ListType}, | ||||
|     posts::Post, | ||||
|     tags::Tag, | ||||
|     timeline::Timeline, | ||||
|     users::User, | ||||
|     Result, | ||||
|     Connection, Result, | ||||
| }; | ||||
| use plume_common::activity_pub::inbox::AsActor; | ||||
| use whatlang::{self, Lang}; | ||||
| @ -155,7 +154,7 @@ enum TQ<'a> { | ||||
| impl<'a> TQ<'a> { | ||||
|     fn matches( | ||||
|         &self, | ||||
|         conn: &DbConn, | ||||
|         conn: &Connection, | ||||
|         timeline: &Timeline, | ||||
|         post: &Post, | ||||
|         kind: Kind<'_>, | ||||
| @ -200,7 +199,7 @@ enum Arg<'a> { | ||||
| impl<'a> Arg<'a> { | ||||
|     pub fn matches( | ||||
|         &self, | ||||
|         conn: &DbConn, | ||||
|         conn: &Connection, | ||||
|         timeline: &Timeline, | ||||
|         post: &Post, | ||||
|         kind: Kind<'_>, | ||||
| @ -225,7 +224,7 @@ enum WithList { | ||||
| impl WithList { | ||||
|     pub fn matches( | ||||
|         &self, | ||||
|         conn: &DbConn, | ||||
|         conn: &Connection, | ||||
|         timeline: &Timeline, | ||||
|         post: &Post, | ||||
|         list: &List<'_>, | ||||
| @ -361,7 +360,7 @@ enum Bool { | ||||
| impl Bool { | ||||
|     pub fn matches( | ||||
|         &self, | ||||
|         conn: &DbConn, | ||||
|         conn: &Connection, | ||||
|         timeline: &Timeline, | ||||
|         post: &Post, | ||||
|         kind: Kind<'_>, | ||||
| @ -654,7 +653,7 @@ impl<'a> TimelineQuery<'a> { | ||||
| 
 | ||||
|     pub fn matches( | ||||
|         &self, | ||||
|         conn: &DbConn, | ||||
|         conn: &Connection, | ||||
|         timeline: &Timeline, | ||||
|         post: &Post, | ||||
|         kind: Kind<'_>, | ||||
|  | ||||
| @ -191,10 +191,10 @@ impl User { | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn find_by_fqn(conn: &DbConn, fqn: &str) -> Result<User> { | ||||
|     pub fn find_by_fqn(conn: &Connection, fqn: &str) -> Result<User> { | ||||
|         let from_db = users::table | ||||
|             .filter(users::fqn.eq(fqn)) | ||||
|             .first(&**conn) | ||||
|             .first(conn) | ||||
|             .optional()?; | ||||
|         if let Some(from_db) = from_db { | ||||
|             Ok(from_db) | ||||
| @ -219,7 +219,7 @@ impl User { | ||||
|         .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     fn fetch_from_webfinger(conn: &DbConn, acct: &str) -> Result<User> { | ||||
|     fn fetch_from_webfinger(conn: &Connection, acct: &str) -> Result<User> { | ||||
|         let link = resolve(acct.to_owned(), true)? | ||||
|             .links | ||||
|             .into_iter() | ||||
| @ -921,15 +921,15 @@ impl IntoId for User { | ||||
| 
 | ||||
| impl Eq for User {} | ||||
| 
 | ||||
| impl FromId<DbConn> for User { | ||||
| impl FromId<Connection> for User { | ||||
|     type Error = Error; | ||||
|     type Object = CustomPerson; | ||||
| 
 | ||||
|     fn from_db(conn: &DbConn, id: &str) -> Result<Self> { | ||||
|     fn from_db(conn: &Connection, id: &str) -> Result<Self> { | ||||
|         Self::find_by_ap_url(conn, id) | ||||
|     } | ||||
| 
 | ||||
|     fn from_activity(conn: &DbConn, acct: CustomPerson) -> Result<Self> { | ||||
|     fn from_activity(conn: &Connection, acct: CustomPerson) -> Result<Self> { | ||||
|         let actor = acct.ap_actor_ref(); | ||||
|         let username = actor | ||||
|             .preferred_username() | ||||
| @ -1030,7 +1030,7 @@ impl FromId<DbConn> for User { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsActor<&DbConn> for User { | ||||
| impl AsActor<&Connection> for User { | ||||
|     fn get_inbox_url(&self) -> String { | ||||
|         self.inbox_url.clone() | ||||
|     } | ||||
| @ -1046,11 +1046,11 @@ impl AsActor<&DbConn> for User { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsObject<User, Delete, &DbConn> for User { | ||||
| impl AsObject<User, Delete, &Connection> for User { | ||||
|     type Error = Error; | ||||
|     type Output = (); | ||||
| 
 | ||||
|     fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> { | ||||
|     fn activity(self, conn: &Connection, actor: User, _id: &str) -> Result<()> { | ||||
|         if self.id == actor.id { | ||||
|             self.delete(conn).map(|_| ()) | ||||
|         } else { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user