mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-09-02 19:23:49 +00:00
Remove unused items (#5870)
* Remove some unused functions * shear * remove more * full feature * remove more * some more * mroe
This commit is contained in:
parent
72d254b4db
commit
f65875c27a
28 changed files with 36 additions and 293 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3962,7 +3962,6 @@ dependencies = [
|
|||
"moka",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"reqwest-middleware",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smart-default",
|
||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -42,16 +42,11 @@ default = []
|
|||
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/api/api",
|
||||
"crates/api/api_crud",
|
||||
"crates/api/api_common",
|
||||
"crates/api/api_utils",
|
||||
"crates/apub",
|
||||
"crates/apub_objects",
|
||||
"crates/utils",
|
||||
"crates/db_schema",
|
||||
"crates/db_schema_file",
|
||||
"crates/db_schema_setup",
|
||||
"crates/email",
|
||||
"crates/db_views/private_message",
|
||||
"crates/db_views/local_user",
|
||||
"crates/db_views/local_image",
|
||||
|
@ -73,9 +68,14 @@ members = [
|
|||
"crates/db_views/report_combined",
|
||||
"crates/db_views/search_combined",
|
||||
"crates/db_views/site",
|
||||
"crates/routes",
|
||||
"crates/api/api",
|
||||
"crates/api/api_crud",
|
||||
"crates/api/api_common",
|
||||
"crates/api/api_utils",
|
||||
"crates/apub",
|
||||
"crates/apub_objects",
|
||||
"crates/federate",
|
||||
"crates/email",
|
||||
"crates/routes",
|
||||
]
|
||||
|
||||
[workspace.lints.clippy]
|
||||
|
|
|
@ -18,6 +18,9 @@ doctest = false
|
|||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
full = []
|
||||
|
||||
[dependencies]
|
||||
lemmy_db_views_comment = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_community = { workspace = true, features = ["full"] }
|
||||
|
|
|
@ -18,6 +18,7 @@ doctest = false
|
|||
workspace = true
|
||||
|
||||
[features]
|
||||
full = []
|
||||
ts-rs = [
|
||||
"lemmy_utils/ts-rs",
|
||||
"lemmy_db_schema/ts-rs",
|
||||
|
|
|
@ -13,6 +13,9 @@ rust-version.workspace = true
|
|||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
full = []
|
||||
|
||||
[dependencies]
|
||||
lemmy_db_views_comment = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_community = { workspace = true, features = ["full"] }
|
||||
|
|
|
@ -332,12 +332,6 @@ impl PictrsFile {
|
|||
self.file
|
||||
))
|
||||
}
|
||||
pub fn delete_url(&self, protocol_and_hostname: &str) -> Result<Url, url::ParseError> {
|
||||
Url::parse(&format!(
|
||||
"{protocol_and_hostname}/api/v4/image/{}",
|
||||
self.file
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores extra details about a Pictrs image.
|
||||
|
|
|
@ -206,19 +206,6 @@ pub fn check_local_user_deleted(local_user_view: &LocalUserView) -> LemmyResult<
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_person_valid(person_view: &PersonView) -> LemmyResult<()> {
|
||||
// Check for a site ban
|
||||
if person_view.creator_banned {
|
||||
Err(LemmyErrorType::SiteBan)?
|
||||
}
|
||||
// check for account deletion
|
||||
else if person_view.person.deleted {
|
||||
Err(LemmyErrorType::Deleted)?
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the user's email is verified if email verification is turned on
|
||||
/// However, skip checking verification if the user is an admin
|
||||
pub fn check_email_verified(
|
||||
|
|
|
@ -18,7 +18,7 @@ pub mod search;
|
|||
///
|
||||
/// In case the requesting user is logged in and the object was not found locally, it is attempted
|
||||
/// to fetch via webfinger from the original instance.
|
||||
pub async fn resolve_ap_identifier<ActorType, DbActor>(
|
||||
pub(crate) async fn resolve_ap_identifier<ActorType, DbActor>(
|
||||
identifier: &str,
|
||||
context: &Data<LemmyContext>,
|
||||
local_user_view: &Option<LocalUserView>,
|
||||
|
|
|
@ -45,7 +45,7 @@ pub(crate) struct CommunityPath {
|
|||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct CommunityIsFollowerQuery {
|
||||
pub(crate) struct CommunityIsFollowerQuery {
|
||||
is_follower: Option<ObjectId<SiteOrMultiOrCommunityOrUser>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -84,13 +84,13 @@ impl ReceiveActivityHook<SharedInboxActivities, UserOrCommunity, LemmyContext> f
|
|||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ActivityQuery {
|
||||
struct ActivityQuery {
|
||||
type_: String,
|
||||
id: String,
|
||||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local activity over HTTP.
|
||||
pub(crate) async fn get_activity(
|
||||
async fn get_activity(
|
||||
info: web::Path<ActivityQuery>,
|
||||
context: Data<LemmyContext>,
|
||||
) -> LemmyResult<HttpResponse> {
|
||||
|
|
|
@ -15,7 +15,7 @@ use lemmy_utils::{
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct PersonQuery {
|
||||
pub(crate) struct PersonQuery {
|
||||
user_name: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ impl InCommunity for Page {
|
|||
}
|
||||
|
||||
/// Only allows deserialization if the field is missing or null. If it is present, throws an error.
|
||||
pub fn deserialize_not_present<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
fn deserialize_not_present<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct Mention {
|
|||
pub kind: MentionType,
|
||||
}
|
||||
|
||||
pub struct MentionsAndAddresses {
|
||||
pub(crate) struct MentionsAndAddresses {
|
||||
pub ccs: Vec<Url>,
|
||||
pub tags: Vec<MentionOrValue>,
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ pub struct MentionsAndAddresses {
|
|||
/// This takes a comment, and builds a list of to_addresses, inboxes,
|
||||
/// and mention tags, so they know where to be sent to.
|
||||
/// Addresses are the persons / addresses that go in the cc field.
|
||||
pub async fn collect_non_local_mentions(
|
||||
pub(crate) async fn collect_non_local_mentions(
|
||||
comment: &ApubComment,
|
||||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<MentionsAndAddresses> {
|
||||
|
|
|
@ -349,38 +349,6 @@ impl CommunityActions {
|
|||
.with_lemmy_type(LemmyErrorType::NotFound)
|
||||
}
|
||||
|
||||
/// Checks to make sure the acting moderator was added earlier than the target moderator
|
||||
pub async fn is_higher_mod_check(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_community_id: CommunityId,
|
||||
mod_person_id: PersonId,
|
||||
target_person_ids: Vec<PersonId>,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
// Build the list of persons
|
||||
let mut persons = target_person_ids;
|
||||
persons.push(mod_person_id);
|
||||
persons.dedup();
|
||||
|
||||
let res = community_actions::table
|
||||
.filter(community_actions::became_moderator_at.is_not_null())
|
||||
.filter(community_actions::community_id.eq(for_community_id))
|
||||
.filter(community_actions::person_id.eq_any(persons))
|
||||
.order_by(community_actions::became_moderator_at)
|
||||
.select(community_actions::person_id)
|
||||
// This does a limit 1 select first
|
||||
.first::<PersonId>(conn)
|
||||
.await?;
|
||||
|
||||
// If the first result sorted by published is the acting mod
|
||||
if res == mod_person_id {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LemmyErrorType::NotHigherMod)?
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if we should accept activity in remote community. This requires either:
|
||||
/// - Local follower of the community
|
||||
/// - Local post or comment in the community
|
||||
|
@ -848,16 +816,6 @@ mod tests {
|
|||
let moderator_person_ids = vec![inserted_bobby.id, inserted_artemis.id];
|
||||
|
||||
// Make sure bobby is marked as a higher mod than artemis, and vice versa
|
||||
let bobby_higher_check = CommunityActions::is_higher_mod_check(
|
||||
pool,
|
||||
inserted_community.id,
|
||||
inserted_bobby.id,
|
||||
moderator_person_ids.clone(),
|
||||
)
|
||||
.await;
|
||||
assert!(bobby_higher_check.is_ok());
|
||||
|
||||
// Also check the other is_higher_mod_or_admin function just in case
|
||||
let bobby_higher_check_2 = LocalUser::is_higher_mod_or_admin_check(
|
||||
pool,
|
||||
inserted_community.id,
|
||||
|
@ -868,7 +826,7 @@ mod tests {
|
|||
assert!(bobby_higher_check_2.is_ok());
|
||||
|
||||
// This should throw an error, since artemis was added later
|
||||
let artemis_higher_check = CommunityActions::is_higher_mod_check(
|
||||
let artemis_higher_check = LocalUser::is_higher_mod_or_admin_check(
|
||||
pool,
|
||||
inserted_community.id,
|
||||
inserted_artemis.id,
|
||||
|
|
|
@ -517,25 +517,6 @@ impl PostActions {
|
|||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateReadComments)
|
||||
}
|
||||
|
||||
pub async fn remove_read_comments(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
post_id: PostId,
|
||||
) -> LemmyResult<UpleteCount> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
uplete(
|
||||
post_actions::table
|
||||
.filter(post_actions::post_id.eq(post_id))
|
||||
.filter(post_actions::person_id.eq(person_id)),
|
||||
)
|
||||
.set_null(post_actions::read_comments_amount)
|
||||
.set_null(post_actions::read_comments_at)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateReadComments)
|
||||
}
|
||||
}
|
||||
|
||||
impl PostActions {
|
||||
|
|
|
@ -33,10 +33,7 @@ pub mod utils;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString};
|
||||
#[cfg(feature = "full")]
|
||||
use {
|
||||
diesel::query_source::AliasedField,
|
||||
lemmy_db_schema_file::schema::{community_actions, instance_actions, person},
|
||||
};
|
||||
use {diesel::query_source::AliasedField, lemmy_db_schema_file::schema::person};
|
||||
|
||||
#[derive(
|
||||
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Hash,
|
||||
|
@ -236,47 +233,3 @@ pub type Person2AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person2, person::comment_count>,
|
||||
AliasedField<aliases::Person2, person::comment_score>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator community actions
|
||||
pub type CreatorCommunityActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::community_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::person_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::followed_at>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::follow_state>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::follow_approver_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::blocked_at>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::became_moderator_at>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::received_ban_at>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::ban_expires_at>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator home instance actions.
|
||||
pub type CreatorHomeInstanceActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::CreatorHomeInstanceActions, instance_actions::person_id>,
|
||||
AliasedField<aliases::CreatorHomeInstanceActions, instance_actions::instance_id>,
|
||||
AliasedField<aliases::CreatorHomeInstanceActions, instance_actions::blocked_at>,
|
||||
AliasedField<aliases::CreatorHomeInstanceActions, instance_actions::received_ban_at>,
|
||||
AliasedField<aliases::CreatorHomeInstanceActions, instance_actions::ban_expires_at>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator local instance actions.
|
||||
pub type CreatorLocalInstanceActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::CreatorLocalInstanceActions, instance_actions::person_id>,
|
||||
AliasedField<aliases::CreatorLocalInstanceActions, instance_actions::instance_id>,
|
||||
AliasedField<aliases::CreatorLocalInstanceActions, instance_actions::blocked_at>,
|
||||
AliasedField<aliases::CreatorLocalInstanceActions, instance_actions::received_ban_at>,
|
||||
AliasedField<aliases::CreatorLocalInstanceActions, instance_actions::ban_expires_at>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator home instance actions.
|
||||
pub type CreatorCommunityInstanceActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::CreatorCommunityInstanceActions, instance_actions::person_id>,
|
||||
AliasedField<aliases::CreatorCommunityInstanceActions, instance_actions::instance_id>,
|
||||
AliasedField<aliases::CreatorCommunityInstanceActions, instance_actions::blocked_at>,
|
||||
AliasedField<aliases::CreatorCommunityInstanceActions, instance_actions::received_ban_at>,
|
||||
AliasedField<aliases::CreatorCommunityInstanceActions, instance_actions::ban_expires_at>,
|
||||
);
|
||||
|
|
|
@ -5,7 +5,6 @@ use chrono::TimeDelta;
|
|||
use deadpool::Runtime;
|
||||
use diesel::{
|
||||
dsl,
|
||||
expression::AsExpression,
|
||||
helper_types::AsExprOf,
|
||||
pg::{data_types::PgInterval, Pg},
|
||||
query_builder::{Query, QueryFragment},
|
||||
|
@ -36,7 +35,6 @@ use lemmy_utils::{
|
|||
settings::{structs::Settings, SETTINGS},
|
||||
utils::validation::clean_url,
|
||||
};
|
||||
use regex::Regex;
|
||||
use rustls::{
|
||||
client::danger::{
|
||||
DangerousClientConfigBuilder,
|
||||
|
@ -52,7 +50,7 @@ use rustls::{
|
|||
};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::{Arc, LazyLock, OnceLock},
|
||||
sync::{Arc, OnceLock},
|
||||
time::Duration,
|
||||
};
|
||||
use tracing::error;
|
||||
|
@ -238,7 +236,7 @@ impl<T> Commented<T> {
|
|||
}
|
||||
|
||||
/// Adds `text` to the comment if `condition` is true
|
||||
pub fn text_if(mut self, text: &str, condition: bool) -> Self {
|
||||
fn text_if(mut self, text: &str, condition: bool) -> Self {
|
||||
if condition {
|
||||
if !self.comment.is_empty() {
|
||||
self.comment.push_str(", ");
|
||||
|
@ -304,10 +302,6 @@ pub fn limit_fetch(limit: Option<i64>) -> LemmyResult<i64> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn is_email_regex(test: &str) -> bool {
|
||||
EMAIL_REGEX.is_match(test)
|
||||
}
|
||||
|
||||
/// Takes an API optional text input, and converts it to an optional diesel DB update.
|
||||
pub fn diesel_string_update(opt: Option<&str>) -> Option<Option<String>> {
|
||||
match opt {
|
||||
|
@ -520,12 +514,6 @@ pub fn build_db_pool_for_tests() -> ActualDbPool {
|
|||
build_db_pool().expect("db pool missing")
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
static EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||
.expect("compile email regex")
|
||||
});
|
||||
|
||||
pub mod functions {
|
||||
use diesel::sql_types::{BigInt, Text, Timestamptz};
|
||||
|
||||
|
@ -539,13 +527,6 @@ pub mod functions {
|
|||
fn scaled_rank(score: BigInt, time: Timestamptz, interactions_month: BigInt) -> Double;
|
||||
}
|
||||
|
||||
define_sql_function! {
|
||||
#[sql_name = "r.controversy_rank"]
|
||||
fn controversy_rank(upvotes: BigInt, downvotes: BigInt, score: BigInt) -> Double;
|
||||
}
|
||||
|
||||
define_sql_function!(fn reverse_timestamp_sort(time: Timestamptz) -> BigInt);
|
||||
|
||||
define_sql_function!(fn lower(x: Text) -> Text);
|
||||
|
||||
define_sql_function!(fn random() -> Text);
|
||||
|
@ -574,31 +555,11 @@ pub fn seconds_to_pg_interval(seconds: i32) -> PgInterval {
|
|||
PgInterval::from_microseconds(i64::from(seconds) * 1_000_000)
|
||||
}
|
||||
|
||||
/// Trait alias for a type that can be converted to an SQL tuple using `IntoSql::into_sql`
|
||||
pub trait AsRecord: Expression + AsExpression<sql_types::Record<Self::SqlType>>
|
||||
where
|
||||
Self::SqlType: 'static,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: Expression + AsExpression<sql_types::Record<T::SqlType>>> AsRecord for T where
|
||||
T::SqlType: 'static
|
||||
{
|
||||
}
|
||||
|
||||
/// Output of `IntoSql::into_sql` for a type that implements `AsRecord`
|
||||
pub type AsRecordOutput<T> = dsl::AsExprOf<T, sql_types::Record<<T as Expression>::SqlType>>;
|
||||
|
||||
pub type ResultFuture<'a, T> = BoxFuture<'a, Result<T, DieselError>>;
|
||||
|
||||
pub trait ReadFn<'a, T, Args>: Fn(DbConn<'a>, Args) -> ResultFuture<'a, T> {}
|
||||
|
||||
impl<'a, T, Args, F: Fn(DbConn<'a>, Args) -> ResultFuture<'a, T>> ReadFn<'a, T, Args> for F {}
|
||||
|
||||
pub trait ListFn<'a, T, Args>: Fn(DbConn<'a>, Args) -> ResultFuture<'a, Vec<T>> {}
|
||||
|
||||
impl<'a, T, Args, F: Fn(DbConn<'a>, Args) -> ResultFuture<'a, Vec<T>>> ListFn<'a, T, Args> for F {}
|
||||
|
||||
pub fn paginate<Q, C>(
|
||||
query: Q,
|
||||
sort_direction: SortDirection,
|
||||
|
@ -664,12 +625,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_email() {
|
||||
assert!(is_email_regex("gush@gmail.com"));
|
||||
assert!(!is_email_regex("nada_neutho"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_diesel_option_overwrite() {
|
||||
assert_eq!(diesel_string_update(None), None);
|
||||
|
|
|
@ -63,22 +63,6 @@ impl CommunityFollowerView {
|
|||
.with_lemmy_type(LemmyErrorType::NotFound)
|
||||
}
|
||||
|
||||
pub async fn get_community_follower_inboxes(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
) -> LemmyResult<Vec<DbUrl>> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let res = Self::joins()
|
||||
.filter(community_actions::community_id.eq(community_id))
|
||||
.filter(not(person::local))
|
||||
.select(person::inbox_url)
|
||||
.distinct()
|
||||
.load::<DbUrl>(conn)
|
||||
.await?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn count_community_followers(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
|
|
|
@ -18,6 +18,9 @@ doctest = false
|
|||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
full = []
|
||||
|
||||
[dependencies]
|
||||
lemmy_utils = { workspace = true, features = ["full"] }
|
||||
lemmy_db_schema = { workspace = true, features = ["full"] }
|
||||
|
|
|
@ -26,7 +26,7 @@ const CLEANUP_INTERVAL_SECS: u32 = 120;
|
|||
/// Smaller than `std::time::Instant` because it uses a smaller integer for seconds and doesn't
|
||||
/// store nanoseconds
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Hash)]
|
||||
pub struct InstantSecs {
|
||||
struct InstantSecs {
|
||||
pub secs: u32,
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ workspace = true
|
|||
full = [
|
||||
"diesel",
|
||||
"actix-web",
|
||||
"reqwest-middleware",
|
||||
"tracing",
|
||||
"actix-web",
|
||||
"serde_json",
|
||||
|
@ -60,7 +59,6 @@ serde_json = { workspace = true, optional = true }
|
|||
url = { workspace = true, optional = true }
|
||||
actix-web = { workspace = true, optional = true }
|
||||
anyhow = { workspace = true, optional = true }
|
||||
reqwest-middleware = { workspace = true, optional = true }
|
||||
strum = { workspace = true }
|
||||
futures = { workspace = true, optional = true }
|
||||
diesel = { workspace = true, optional = true, features = ["chrono"] }
|
||||
|
|
|
@ -7,7 +7,7 @@ use actix_web::middleware::DefaultHeaders;
|
|||
/// * 3 days = 60s * 60m * 24h * 3d = `259200` seconds
|
||||
///
|
||||
/// Mastodon & other activitypub server defaults to 3d
|
||||
pub fn cache_header(seconds: usize) -> DefaultHeaders {
|
||||
fn cache_header(seconds: usize) -> DefaultHeaders {
|
||||
DefaultHeaders::new().add(("Cache-Control", format!("public, max-age={seconds}")))
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ cfg_if! {
|
|||
if #[cfg(feature = "full")] {
|
||||
pub mod cache_header;
|
||||
pub mod rate_limit;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
pub mod settings;
|
||||
pub mod utils;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
use std::future::Future;
|
||||
|
||||
pub async fn retry<F, Fut, T>(f: F) -> Result<T, reqwest_middleware::Error>
|
||||
where
|
||||
F: Fn() -> Fut,
|
||||
Fut: Future<Output = Result<T, reqwest_middleware::Error>>,
|
||||
{
|
||||
retry_custom(|| async { Ok((f)().await) }).await
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
async fn retry_custom<F, Fut, T>(f: F) -> Result<T, reqwest_middleware::Error>
|
||||
where
|
||||
F: Fn() -> Fut,
|
||||
Fut: Future<Output = Result<Result<T, reqwest_middleware::Error>, reqwest_middleware::Error>>,
|
||||
{
|
||||
let mut response: Option<Result<T, reqwest_middleware::Error>> = None;
|
||||
|
||||
for _ in 0u8..3 {
|
||||
match (f)().await? {
|
||||
Ok(t) => return Ok(t),
|
||||
Err(reqwest_middleware::Error::Reqwest(e)) => {
|
||||
if e.is_timeout() {
|
||||
response = Some(Err(reqwest_middleware::Error::Reqwest(e)));
|
||||
continue;
|
||||
}
|
||||
return Err(reqwest_middleware::Error::Reqwest(e));
|
||||
}
|
||||
Err(otherwise) => {
|
||||
return Err(otherwise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.expect("retry http request")
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{error::LemmyResult, location_info};
|
||||
use anyhow::{anyhow, Context};
|
||||
use deser_hjson::from_str;
|
||||
use regex::Regex;
|
||||
use std::{env, fs, sync::LazyLock};
|
||||
use structs::{PictrsConfig, Settings};
|
||||
use url::Url;
|
||||
|
@ -23,15 +22,6 @@ pub static SETTINGS: LazyLock<Settings> = LazyLock::new(|| {
|
|||
}
|
||||
});
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
static WEBFINGER_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(&format!(
|
||||
"^acct:([a-zA-Z0-9_]{{3,}})@{}$",
|
||||
SETTINGS.hostname
|
||||
))
|
||||
.expect("compile webfinger regex")
|
||||
});
|
||||
|
||||
impl Settings {
|
||||
/// Reads config from configuration file.
|
||||
///
|
||||
|
@ -59,7 +49,7 @@ impl Settings {
|
|||
}
|
||||
|
||||
/// Returns either "http" or "https", depending on tls_enabled setting
|
||||
pub fn get_protocol_string(&self) -> &'static str {
|
||||
fn get_protocol_string(&self) -> &'static str {
|
||||
if self.tls_enabled {
|
||||
"https"
|
||||
} else {
|
||||
|
@ -88,10 +78,6 @@ impl Settings {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn webfinger_regex(&self) -> Regex {
|
||||
WEBFINGER_REGEX.clone()
|
||||
}
|
||||
|
||||
pub fn pictrs(&self) -> LemmyResult<PictrsConfig> {
|
||||
self
|
||||
.pictrs
|
||||
|
|
|
@ -91,7 +91,7 @@ fn find_urls<T: NodeValue + UrlAndTitle>(src: &str) -> Vec<(usize, usize)> {
|
|||
links_offsets
|
||||
}
|
||||
|
||||
pub trait UrlAndTitle {
|
||||
trait UrlAndTitle {
|
||||
fn url_len(&self) -> usize;
|
||||
fn title_len(&self) -> usize;
|
||||
}
|
||||
|
|
|
@ -20,19 +20,6 @@ static MARKDOWN_PARSER: LazyLock<MarkdownIt> = LazyLock::new(|| {
|
|||
parser
|
||||
});
|
||||
|
||||
/// Replace special HTML characters in API parameters to prevent XSS attacks.
|
||||
///
|
||||
/// Taken from https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md#output-encoding-for-html-contexts
|
||||
///
|
||||
/// `>` is left in place because it is interpreted as markdown quote.
|
||||
pub fn sanitize_html(text: &str) -> String {
|
||||
text
|
||||
.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
.replace('\"', """)
|
||||
.replace('\'', "'")
|
||||
}
|
||||
|
||||
pub fn markdown_to_html(text: &str) -> String {
|
||||
MARKDOWN_PARSER.parse(text).xrender()
|
||||
}
|
||||
|
@ -231,16 +218,4 @@ mod tests {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_html() {
|
||||
let sanitized = sanitize_html("<script>alert('xss');</script> hello &\"'");
|
||||
let expected = "<script>alert('xss');</script> hello &"'";
|
||||
assert_eq!(expected, sanitized);
|
||||
|
||||
let sanitized =
|
||||
sanitize_html("Polling the group: what do y'all know about the Orion browser from Kagi?");
|
||||
let expected = "Polling the group: what do y'all know about the Orion browser from Kagi?";
|
||||
assert_eq!(expected, sanitized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ pub fn check_blocking_keywords_are_valid(blocking_keywords: &Vec<String>) -> Lem
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn build_url_str_without_scheme(url_str: &str) -> LemmyResult<String> {
|
||||
fn build_url_str_without_scheme(url_str: &str) -> LemmyResult<String> {
|
||||
// Parse and check for errors
|
||||
let mut url = Url::parse(url_str).or_else(|e| {
|
||||
if e == ParseError::RelativeUrlWithoutBase {
|
||||
|
@ -317,7 +317,7 @@ pub fn build_url_str_without_scheme(url_str: &str) -> LemmyResult<String> {
|
|||
|
||||
// Shorten a string to n chars, being mindful of unicode grapheme
|
||||
// boundaries
|
||||
pub fn truncate_for_db(text: &str, len: usize) -> String {
|
||||
fn truncate_for_db(text: &str, len: usize) -> String {
|
||||
if text.chars().count() <= len {
|
||||
text.to_string()
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue