using DorkNet.Server.Data; using DorkNet.Server.Data.Entities; using Microsoft.EntityFrameworkCore; namespace DorkNet.Server.Services; /// /// Effective-friend resolution that honors the /// toggle. /// /// When the toggle is ON, every account on the server is treated as a /// friend of every other account WITHOUT writing any relationship rows — /// the friend graph is synthesized at read time. This keeps a small private /// server frictionless (no searching + manual friend requests) and reverts /// instantly when the toggle flips off, since nothing was persisted. /// /// Blocked relationships still suppress the pairing, and the system/coach /// account () is never offered as a friend. /// /// Live propagation: flipping the toggle broadcasts /// PushNotificationId.RelationshipsInvalid, which the 2020 watch /// handles by calling Relationships.RefreshList — a full re-fetch of /// api/relationships/v2/get — so connected players see the change /// without relogging (verified against the readable March decompile: /// RecNet/Relationships.txt → OnRelationshipsInvalid → RefreshList). /// public static class RelationshipQueries { /// Coach/system account seeded at startup (Player.Id = 1). /// Excluded from the global-friends set so it never shows up as a /// friend in anyone's list. public const long SystemAccountId = 1; /// The effective friend ids for . With the /// global-friends toggle off this is the real Friend graph; with it on /// it's every other (non-system, non-blocked) account. public static async Task> EffectiveFriendIdsAsync( DorkNetDbContext db, ServerSettingsService settings, long me) { if (!await settings.IsGlobalFriendsEnabledAsync()) { return await db.Relationships .Where(r => r.Status == RelationshipStatus.Friend && (r.RequesterId == me || r.TargetId == me)) .Select(r => r.RequesterId == me ? r.TargetId : r.RequesterId) .ToListAsync(); } // Global friends: everyone except myself, the system account, and // anyone in a Blocked relationship with me (either direction). var blocked = await db.Relationships .Where(r => r.Status == RelationshipStatus.Blocked && (r.RequesterId == me || r.TargetId == me)) .Select(r => r.RequesterId == me ? r.TargetId : r.RequesterId) .ToListAsync(); return await db.Players .Where(p => p.Id != me && p.Id != SystemAccountId && !blocked.Contains(p.Id)) .Select(p => p.Id) .ToListAsync(); } }