using System; using System.Collections.Generic; using System.Linq; using IPA; using IPALogger = IPA.Logging.Logger; namespace Setlist { [Plugin(RuntimeOptions.SingleStartInit)] public class Plugin { internal static Plugin Instance { get; private set; } /// /// BSIPA logger (shows in BSIPA console / game logs when verbose). /// internal static IPALogger Log { get; private set; } [Init] public Plugin(IPALogger logger) { Instance = this; Log = logger; } [OnStart] public void OnApplicationStart() { try { var playlists = BeatSaberPlaylistsLib.PlaylistManager.DefaultManager.GetAllPlaylists( includeChildren: true, out AggregateException loadErrors); if (loadErrors != null) { Log.Error(loadErrors.Message); foreach (var inner in loadErrors.InnerExceptions) { Log.Error(inner.ToString()); } } if (playlists == null || playlists.Length == 0) { Log.Info("No playlists loaded (or playlist library not initialized yet)."); return; } var entries = new List<(string Title, bool HasSyncUrl, string BeatLeaderGuid, string OwnerId)>(); foreach (var playlist in playlists) { var hasSyncUrl = false; string syncUrl = null; if (playlist.TryGetCustomData("syncURL", out var syncObj) && syncObj is string url) { syncUrl = url; hasSyncUrl = !string.IsNullOrWhiteSpace(url); } string ownerId = null; if (playlist.TryGetCustomData("owner", out var ownerObj) && ownerObj is string o) { ownerId = string.IsNullOrWhiteSpace(o) ? null : o.Trim(); } string blGuid = null; if (hasSyncUrl && BeatLeaderPlaylistOwnership.TryExtractBeatLeaderPlaylistGuid(syncUrl, out var g)) { blGuid = g; } entries.Add((playlist.Title, hasSyncUrl, blGuid, ownerId)); } BeatLeaderPlaylistOwnership.ScheduleVerifyAndLog(entries, Log); } catch (Exception ex) { Log.Error(ex.ToString()); } } [OnExit] public void OnApplicationQuit() { } internal static string FormatPlaylistLogLine( string title, bool hasSyncUrl, string beatLeaderGuid, string ownerId, string platformUserId, HashSet ownedGuids) { var ownerToken = string.IsNullOrEmpty(ownerId) ? "owner=n/a" : $"owner={ownerId}"; string confirmPart; if (!hasSyncUrl) { confirmPart = "beatLeaderOwnerConfirmed=n/a (no sync URL)"; } else if (string.IsNullOrEmpty(beatLeaderGuid)) { confirmPart = "beatLeaderOwnerConfirmed=n/a (sync URL is not a BeatLeader playlist)"; } else if (!string.IsNullOrEmpty(ownerId) && !string.IsNullOrEmpty(platformUserId) && string.Equals(ownerId, platformUserId, StringComparison.Ordinal)) { confirmPart = "beatLeaderOwnerConfirmed=true (owner matches platform user id)"; } else if (ownedGuids == null) { confirmPart = "beatLeaderOwnerConfirmed=unknown (BeatLeader /user/playlists did not succeed; see prior log line)"; } else if (ownedGuids.Contains(beatLeaderGuid)) { confirmPart = "beatLeaderOwnerConfirmed=true"; } else { confirmPart = "beatLeaderOwnerConfirmed=false"; } return $"Playlist \"{title}\": hasSyncUrl={hasSyncUrl}, {ownerToken}, {confirmPart}"; } } }