about summary refs log tree commit diff
diff options
context:
space:
mode:
m---------LibMatrix0
-rw-r--r--OsuFederatedBeatmapApi.sln.DotSettings.user2
-rw-r--r--OsuFederatedBeatmapApi/Controllers/BeatmapRepositoryController.cs7
-rw-r--r--OsuFederatedBeatmapApi/Events/State/BeatmapSetInfo.cs36
-rw-r--r--OsuFederatedBeatmapApi/OsuFederatedBeatmapApi.csproj1
-rw-r--r--OsuFederatedBeatmapApi/Program.cs3
-rw-r--r--OsuFederatedBeatmapApi/Services/BeatmapFetcherService.cs34
-rw-r--r--OsuFederatedBeatmapApi/Services/FederatedBeatmapApiBot.cs23
-rw-r--r--OsuFederatedBeatmapApi/UtilityClasses/OsuDirectApiResponses.cs107
9 files changed, 207 insertions, 6 deletions
diff --git a/LibMatrix b/LibMatrix
-Subproject 84e33226690beb65f747526714ac9aa4cc8ee15
+Subproject 4340b1899470c06f170817dbc1200040619fbf8
diff --git a/OsuFederatedBeatmapApi.sln.DotSettings.user b/OsuFederatedBeatmapApi.sln.DotSettings.user
index d5ce503..98ceabe 100644
--- a/OsuFederatedBeatmapApi.sln.DotSettings.user
+++ b/OsuFederatedBeatmapApi.sln.DotSettings.user
@@ -1,3 +1,3 @@
 <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
-	<s:Int64 x:Key="/Default/Dpa/Thresholds/=AllocationClosure/@EntryIndexedValue">52428800</s:Int64>
+	<s:Int64 x:Key="/Default/Dpa/Thresholds/=AllocationClosure/@EntryIndexedValue">53477376</s:Int64>
 	<s:Int64 x:Key="/Default/Dpa/Thresholds/=AllocationLoh/@EntryIndexedValue">52428800</s:Int64></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/OsuFederatedBeatmapApi/Controllers/BeatmapRepositoryController.cs b/OsuFederatedBeatmapApi/Controllers/BeatmapRepositoryController.cs
index 6a1149d..b1fa4f1 100644
--- a/OsuFederatedBeatmapApi/Controllers/BeatmapRepositoryController.cs
+++ b/OsuFederatedBeatmapApi/Controllers/BeatmapRepositoryController.cs
@@ -6,7 +6,7 @@ namespace OsuFederatedBeatmapApi.Controllers;
 
 [ApiController]
 [Route("/")]
-public class BeatmapRepositoryController(ILogger<BeatmapRepositoryController> logger, FederatedBeatmapApiBotAccountDataService ads) : ControllerBase {
+public class BeatmapRepositoryController(ILogger<BeatmapRepositoryController> logger, FederatedBeatmapApiBotAccountDataService ads, BeatmapFetcherService bfs) : ControllerBase {
     [HttpGet("/beatmapset/all/info")]
     public async IAsyncEnumerable<BeatmapSetInfo> GetAllInfo() {
         await ads.LoadAccountDataAsync();
@@ -24,8 +24,9 @@ public class BeatmapRepositoryController(ILogger<BeatmapRepositoryController> lo
         await ads.LoadAccountDataAsync();
 
         foreach (var repo in ads.ListedRepositories) {
-            var states = await repo.GetStateAsync<BeatmapSetInfo>("gay.rory.beatmap_api.beatmap_set_info", id.ToString());
-            return states as BeatmapSetInfo;
+            var state = await repo.GetStateOrNullAsync<BeatmapSetInfo>("gay.rory.beatmap_api.beatmap_set_info", id.ToString());
+            if (state is not null) return state;
+            return await bfs.FetchBeatmapSetInfo(id);
         }
 
         return null;
diff --git a/OsuFederatedBeatmapApi/Events/State/BeatmapSetInfo.cs b/OsuFederatedBeatmapApi/Events/State/BeatmapSetInfo.cs
index 8cfcf0d..7d6b455 100644
--- a/OsuFederatedBeatmapApi/Events/State/BeatmapSetInfo.cs
+++ b/OsuFederatedBeatmapApi/Events/State/BeatmapSetInfo.cs
@@ -1,12 +1,46 @@
+using System.Text.Json.Serialization;
 using LibMatrix;
 using LibMatrix.EventTypes;
 using LibMatrix.Interfaces;
 
 namespace OsuFederatedBeatmapApi.Events.State;
 
-[MatrixEvent(EventName = "gay.rory.beatmap_api.beatmap_set_info")]
+[MatrixEvent(EventName = EventName)]
 public class BeatmapSetInfo : EventContent {
+    public const string EventName = "gay.rory.beatmap_api.beatmap_set_info";
 
+    [JsonPropertyName("title")]
+    public string? Title { get; set; }
 
+    [JsonPropertyName("artist")]
+    public string? Artist { get; set; }
 
+    [JsonPropertyName("creator")]
+    public string? Creator { get; set; }
+
+    [JsonPropertyName("beatmaps")]
+    public Dictionary<int, BeatmapInfo> Beatmaps { get; set; } = new();
+
+    public class BeatmapInfo {
+        [JsonPropertyName("difficulty")]
+        public string? Difficulty { get; set; }
+
+        [JsonPropertyName("mode")]
+        public int? Mode { get; set; }
+
+        [JsonPropertyName("difficulty_rating")]
+        public double? DifficultyRating { get; set; }
+
+        [JsonPropertyName("total_length")]
+        public int? TotalLength { get; set; }
+
+        [JsonPropertyName("bpm")]
+        public double? BPM { get; set; }
+
+        [JsonPropertyName("max_combo")]
+        public int? MaxCombo { get; set; }
+
+        // [JsonPropertyName("drain")]
+        // public double? Drain { get; set; }
+    }
 }
diff --git a/OsuFederatedBeatmapApi/OsuFederatedBeatmapApi.csproj b/OsuFederatedBeatmapApi/OsuFederatedBeatmapApi.csproj
index 387808f..bc2a324 100644
--- a/OsuFederatedBeatmapApi/OsuFederatedBeatmapApi.csproj
+++ b/OsuFederatedBeatmapApi/OsuFederatedBeatmapApi.csproj
@@ -14,6 +14,7 @@
 
     <ItemGroup>
       <ProjectReference Include="..\LibMatrix\Utilities\LibMatrix.Utilities.Bot\LibMatrix.Utilities.Bot.csproj" />
+
     </ItemGroup>
 
 
diff --git a/OsuFederatedBeatmapApi/Program.cs b/OsuFederatedBeatmapApi/Program.cs
index 15f9b12..8f54865 100644
--- a/OsuFederatedBeatmapApi/Program.cs
+++ b/OsuFederatedBeatmapApi/Program.cs
@@ -1,3 +1,4 @@
+using System.Text.Json;
 using LibMatrix.Services;
 using LibMatrix.Utilities.Bot;
 using OsuFederatedBeatmapApi.Services;
@@ -21,6 +22,8 @@ builder.Services.AddScoped<TieredStorageService>(x =>
 builder.Services.AddRoryLibMatrixServices();
 builder.Services.AddBot(withCommands: true);
 
+builder.Services.AddScoped<BeatmapFetcherService>();
+
 builder.Services.AddSingleton<FederatedBeatmapApiBotConfiguration>();
 builder.Services.AddScoped<FederatedBeatmapApiBotAccountDataService>();
 builder.Services.AddHostedService<FederatedBeatmapApiBot>();
diff --git a/OsuFederatedBeatmapApi/Services/BeatmapFetcherService.cs b/OsuFederatedBeatmapApi/Services/BeatmapFetcherService.cs
new file mode 100644
index 0000000..ae108fb
--- /dev/null
+++ b/OsuFederatedBeatmapApi/Services/BeatmapFetcherService.cs
@@ -0,0 +1,34 @@
+using System.Net.Http.Headers;
+using OsuFederatedBeatmapApi.Events.State;
+using OsuFederatedBeatmapApi.UtilityClasses;
+
+namespace OsuFederatedBeatmapApi.Services;
+
+public class BeatmapFetcherService(FederatedBeatmapApiBotAccountDataService ads) {
+
+    public async Task<BeatmapSetInfo> FetchBeatmapSetInfo(int id) {
+        var hc = new HttpClient();
+        hc.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("OsuFederatedBeatmapApi", "1.0"));
+        var res = await hc.GetFromJsonAsync<OsuDirectApiResponses.BeatmapSet>($"https://osu.direct/api/s/{id}");
+        var info = new BeatmapSetInfo {
+            Title = res.Title,
+            Artist = res.Artist,
+            Creator = res.Creator,
+            Beatmaps = res.ChildrenBeatmaps.ToDictionary(b => b.BeatmapID, b => new BeatmapSetInfo.BeatmapInfo {
+                Difficulty = b.DiffName,
+                Mode = b.Mode,
+                DifficultyRating = b.DifficultyRating,
+                TotalLength = b.TotalLength,
+                BPM = b.BPM,
+                MaxCombo = b.MaxCombo
+            })
+        };
+
+        await ads.LoadAccountDataAsync();
+
+        await ads.OwnBeatmapRepositoryRoom.SendStateEventAsync(BeatmapSetInfo.EventName, id.ToString(), info);
+
+        return info;
+    }
+
+}
diff --git a/OsuFederatedBeatmapApi/Services/FederatedBeatmapApiBot.cs b/OsuFederatedBeatmapApi/Services/FederatedBeatmapApiBot.cs
index b8cc635..2aaf45c 100644
--- a/OsuFederatedBeatmapApi/Services/FederatedBeatmapApiBot.cs
+++ b/OsuFederatedBeatmapApi/Services/FederatedBeatmapApiBot.cs
@@ -40,7 +40,28 @@ public class FederatedBeatmapApiBot(AuthenticatedHomeserverGeneric hs,
                 var controlRoomMembers = accountDataService.ControlRoom.GetMembersAsync();
                 await foreach (var member in controlRoomMembers) {
                     if ((member.TypedContent as RoomMemberEventContent)?
-                        .Membership == "join") admins.Add(member.UserId);
+                        .Membership == "join")
+                        admins.Add(member.StateKey);
+                }
+
+                var pls = await accountDataService.OwnBeatmapRepositoryRoom.GetPowerLevelsAsync();
+                var ownPl = pls.GetUserPowerLevel(hs.UserId);
+
+                if (!pls.UserHasPermission(hs.UserId, RoomPowerLevelEventContent.EventId)) {
+                    accountDataService.LogRoom.SendMessageEventAsync(
+                        MessageFormatter.FormatError(
+                            $"I don't have permission to send power level updates in " +
+                            $"{MessageFormatter.HtmlFormatMention(accountDataService.OwnBeatmapRepositoryRoom.RoomId, "my own beatmap repository")}!"));
+                }
+                else {
+                    foreach (var admin in admins) {
+                        if (pls.GetUserPowerLevel(admin) < ownPl - 1) {
+                            logger.LogInformation("Raising powerlevel of {} in {} to {}", admin, accountDataService.OwnBeatmapRepositoryRoom.RoomId, ownPl - 1);
+                            pls.SetUserPowerLevel(admin, ownPl - 1);
+                            await accountDataService.OwnBeatmapRepositoryRoom.SendStateEventAsync(
+                                RoomPowerLevelEventContent.EventId, pls);
+                        }
+                    }
                 }
 
                 await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
diff --git a/OsuFederatedBeatmapApi/UtilityClasses/OsuDirectApiResponses.cs b/OsuFederatedBeatmapApi/UtilityClasses/OsuDirectApiResponses.cs
new file mode 100644
index 0000000..b7b67b1
--- /dev/null
+++ b/OsuFederatedBeatmapApi/UtilityClasses/OsuDirectApiResponses.cs
@@ -0,0 +1,107 @@
+using System.Text.Json.Serialization;
+
+namespace OsuFederatedBeatmapApi.UtilityClasses;
+
+public class OsuDirectApiResponses {
+        public class ChildrenBeatmap
+    {
+        [JsonPropertyName("ParentSetID")]
+        public int ParentSetID { get; set; }
+
+        [JsonPropertyName("BeatmapID")]
+        public int BeatmapID { get; set; }
+
+        [JsonPropertyName("TotalLength")]
+        public int TotalLength { get; set; }
+
+        [JsonPropertyName("HitLength")]
+        public int HitLength { get; set; }
+
+        [JsonPropertyName("DiffName")]
+        public string DiffName { get; set; }
+
+        [JsonPropertyName("FileMD5")]
+        public string FileMD5 { get; set; }
+
+        [JsonPropertyName("CS")]
+        public int CS { get; set; }
+
+        [JsonPropertyName("AR")]
+        public int AR { get; set; }
+
+        [JsonPropertyName("HP")]
+        public int HP { get; set; }
+
+        [JsonPropertyName("OD")]
+        public int OD { get; set; }
+
+        [JsonPropertyName("Mode")]
+        public int Mode { get; set; }
+
+        [JsonPropertyName("BPM")]
+        public int BPM { get; set; }
+
+        [JsonPropertyName("Playcount")]
+        public int Playcount { get; set; }
+
+        [JsonPropertyName("Passcount")]
+        public int Passcount { get; set; }
+
+        [JsonPropertyName("MaxCombo")]
+        public int MaxCombo { get; set; }
+
+        [JsonPropertyName("DifficultyRating")]
+        public double DifficultyRating { get; set; }
+    }
+
+    public class BeatmapSet
+    {
+        [JsonPropertyName("SetID")]
+        public int SetID { get; set; }
+
+        [JsonPropertyName("Title")]
+        public string Title { get; set; }
+
+        [JsonPropertyName("Artist")]
+        public string Artist { get; set; }
+
+        [JsonPropertyName("Creator")]
+        public string Creator { get; set; }
+
+        [JsonPropertyName("Source")]
+        public string Source { get; set; }
+
+        [JsonPropertyName("Tags")]
+        public string Tags { get; set; }
+
+        [JsonPropertyName("RankedStatus")]
+        public int RankedStatus { get; set; }
+
+        [JsonPropertyName("Genre")]
+        public int Genre { get; set; }
+
+        [JsonPropertyName("Language")]
+        public int Language { get; set; }
+
+        [JsonPropertyName("Favourites")]
+        public int Favourites { get; set; }
+
+        [JsonPropertyName("HasVideo")]
+        public int HasVideo { get; set; }
+
+        [JsonPropertyName("SubmittedDate")]
+        public DateTime SubmittedDate { get; set; }
+
+        [JsonPropertyName("ApprovedDate")]
+        public DateTime ApprovedDate { get; set; }
+
+        [JsonPropertyName("LastUpdate")]
+        public DateTime LastUpdate { get; set; }
+
+        [JsonPropertyName("LastChecked")]
+        public DateTime LastChecked { get; set; }
+
+        [JsonPropertyName("ChildrenBeatmaps")]
+        public List<ChildrenBeatmap> ChildrenBeatmaps { get; set; }
+    }
+}