diff --git a/Iceshrimp.Backend/Controllers/Mastodon/SearchController.cs b/Iceshrimp.Backend/Controllers/Mastodon/SearchController.cs index 23d36e67..8563ff9e 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/SearchController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/SearchController.cs @@ -130,8 +130,8 @@ public class SearchController( return await db.Users .IncludeCommonProperties() - .Where(p => p.DisplayNameContainsCaseInsensitive(search.Query!) || - p.UsernameContainsCaseInsensitive(search.Query!)) + .Where(p => p.DisplayNameOrUsernameOrFqnContainsCaseInsensitive(search.Query!, + config.Value.AccountDomain)) .Where(p => !search.Following || p.IsFollowedBy(user)) .Paginate(pagination, ControllerContext) //TODO: this will mess up our sorting .OrderByDescending(p => p.NotesCount) diff --git a/Iceshrimp.Backend/Core/Database/Tables/User.cs b/Iceshrimp.Backend/Core/Database/Tables/User.cs index 6bacc465..79f385c9 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/User.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/User.cs @@ -439,7 +439,7 @@ public class User : IEntity [InverseProperty(nameof(SwSubscription.User))] public virtual ICollection SwSubscriptions { get; set; } = new List(); - + [InverseProperty(nameof(PushSubscription.User))] public virtual ICollection PushSubscriptions { get; set; } = new List(); @@ -499,12 +499,32 @@ public class User : IEntity [StringLength(32)] public string Id { get; set; } = null!; + [Projectable] + public string GetFqnLower(string accountDomain) => UsernameLower + "@" + (Host ?? accountDomain); + + [Projectable] + public string GetFqn(string accountDomain) => Username + "@" + (Host ?? accountDomain); + [Projectable] public bool DisplayNameContainsCaseInsensitive(string str) => DisplayName != null && EF.Functions.ILike(DisplayName, "%" + EfHelpers.EscapeLikeQuery(str) + "%", @"\"); [Projectable] - public bool UsernameContainsCaseInsensitive(string str) => UsernameLower.Contains(str); + public bool UsernameContainsCaseInsensitive(string str) => UsernameLower.Contains(str.ToLowerInvariant()); + + [Projectable] + public bool FqnContainsCaseInsensitive(string str, string accountDomain) => + GetFqnLower(accountDomain).Contains(str.ToLowerInvariant()); + + [Projectable] + public bool UsernameOrFqnContainsCaseInsensitive(string str, string accountDomain) => + str.Contains('@') ? FqnContainsCaseInsensitive(str, accountDomain) : UsernameContainsCaseInsensitive(str); + + [Projectable] + public bool DisplayNameOrUsernameOrFqnContainsCaseInsensitive(string str, string accountDomain) => + str.Contains('@') && !str.Contains(' ') + ? FqnContainsCaseInsensitive(str, accountDomain) + : UsernameContainsCaseInsensitive(str) || DisplayNameContainsCaseInsensitive(str); [Projectable] public bool IsBlockedBy(User user) => BlockedBy.Contains(user); @@ -582,9 +602,9 @@ public class User : IEntity return this; } - public string GetPublicUrl(Config.InstanceSection config) => GetPublicUrl(config.WebDomain); - public string GetPublicUri(Config.InstanceSection config) => GetPublicUri(config.WebDomain); - public string GetIdenticonUrl(Config.InstanceSection config) => GetIdenticonUrl(config.WebDomain); + public string GetPublicUrl(Config.InstanceSection config) => GetPublicUrl(config.WebDomain); + public string GetPublicUri(Config.InstanceSection config) => GetPublicUri(config.WebDomain); + public string GetIdenticonUrl(Config.InstanceSection config) => GetIdenticonUrl(config.WebDomain); public string GetIdenticonUrlPng(Config.InstanceSection config) => GetIdenticonUrl(config.WebDomain) + ".png"; public string GetPublicUri(string webDomain) => Host == null