Skip to content

Commit a3f13f3

Browse files
authored
Merge pull request #20 from Syriiin/add-download-missing-beatmap-envvar
Add DOWNLOAD_MISSING_BEATMAPS env var
2 parents de076f1 + ce58a78 commit a3f13f3

17 files changed

+186
-121
lines changed

.config/dotnet-tools.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"swashbuckle.aspnetcore.cli": {
6+
"version": "6.6.1",
7+
"commands": [
8+
"swagger"
9+
]
10+
}
11+
}
12+
}

.github/workflows/test-on-push.yml

+6
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ jobs:
1212
steps:
1313
- uses: actions/checkout@v3
1414
- run: make test-e2e
15+
16+
check-api-reference:
17+
runs-on: ubuntu-22.04
18+
steps:
19+
- uses: actions/checkout@v3
20+
- run: make check-api-reference

Difficalcy/Controllers/CalculatorController.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ public ActionResult<CalculatorInfo> GetInfo()
3333
[HttpGet("calculation")]
3434
public async Task<ActionResult<TCalculation>> GetCalculation([FromQuery] TScore score)
3535
{
36-
return Ok(await calculatorService.GetCalculation(score));
36+
try
37+
{
38+
return Ok(await calculatorService.GetCalculation(score));
39+
}
40+
catch (BeatmapNotFoundException e)
41+
{
42+
return BadRequest(new { error = e.Message });
43+
}
3744
}
3845

3946
/// <summary>
@@ -43,7 +50,14 @@ public async Task<ActionResult<TCalculation>> GetCalculation([FromQuery] TScore
4350
[Consumes("application/json")]
4451
public async Task<ActionResult<TCalculation[]>> GetCalculationBatch([FromBody] TScore[] scores)
4552
{
46-
return Ok(await Task.WhenAll(scores.Select(score => calculatorService.GetCalculation(score))));
53+
try
54+
{
55+
return Ok(await Task.WhenAll(scores.Select(calculatorService.GetCalculation)));
56+
}
57+
catch (BeatmapNotFoundException e)
58+
{
59+
return BadRequest(new { error = e.Message });
60+
}
4761
}
4862
}
4963
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System;
2+
3+
namespace Difficalcy.Services
4+
{
5+
public class BeatmapNotFoundException(string beatmapId) : Exception($"Beatmap {beatmapId} not found")
6+
{
7+
}
8+
}

Difficalcy/Services/TestBeatmapProvider.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
using System;
21
using System.IO;
32
using System.Reflection;
43
using System.Threading.Tasks;
5-
using Microsoft.AspNetCore.Http;
64

75
namespace Difficalcy.Services
86
{
@@ -11,7 +9,7 @@ public class TestBeatmapProvider(string resourceAssemblyName) : IBeatmapProvider
119
public Task EnsureBeatmap(string beatmapId)
1210
{
1311
var resourceName = GetResourceName(beatmapId);
14-
_ = ResourceAssembly.GetManifestResourceInfo(resourceName) ?? throw new BadHttpRequestException($"Beatmap not found: {beatmapId}");
12+
_ = ResourceAssembly.GetManifestResourceInfo(resourceName) ?? throw new BeatmapNotFoundException(beatmapId);
1513
return Task.CompletedTask;
1614
}
1715

Difficalcy/Services/WebBeatmapProvider.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
11
using System.IO;
22
using System.Net.Http;
33
using System.Threading.Tasks;
4-
using Microsoft.AspNetCore.Http;
54
using Microsoft.Extensions.Configuration;
65

76
namespace Difficalcy.Services
87
{
98
public class WebBeatmapProvider(IConfiguration configuration) : IBeatmapProvider
109
{
1110
private readonly string _beatmapDirectory = configuration["BEATMAP_DIRECTORY"];
11+
private readonly string _downloadMissingBeatmaps = configuration["DOWNLOAD_MISSING_BEATMAPS"];
1212
private readonly HttpClient _httpClient = new();
1313

1414
public async Task EnsureBeatmap(string beatmapId)
1515
{
1616
var beatmapPath = GetBeatmapPath(beatmapId);
1717
if (!File.Exists(beatmapPath))
1818
{
19+
if (_downloadMissingBeatmaps != "true")
20+
throw new BeatmapNotFoundException(beatmapId);
21+
1922
using var response = await _httpClient.GetAsync($"https://osu.ppy.sh/osu/{beatmapId}");
20-
if (!response.IsSuccessStatusCode)
21-
throw new BadHttpRequestException("Beatmap not found");
23+
if (!response.IsSuccessStatusCode || response.Content.Headers.ContentLength == 0)
24+
throw new BeatmapNotFoundException(beatmapId);
2225

2326
using var fs = new FileStream(beatmapPath, FileMode.CreateNew);
24-
if (fs.Length == 0)
25-
throw new BadHttpRequestException("Beatmap not found");
26-
2727
await response.Content.CopyToAsync(fs);
28+
if (fs.Length == 0)
29+
{
30+
fs.Close();
31+
File.Delete(beatmapPath);
32+
throw new BeatmapNotFoundException(beatmapId);
33+
}
2834
}
2935
}
3036

Dockerfile

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ LABEL org.opencontainers.image.source https://github.com/Syriiin/difficalcy
44

55
WORKDIR /app
66
EXPOSE 80
7-
ENV ASPNETCORE_URLS=http://+:80
8-
ENV ASPNETCORE_ENVIRONMENT=Production
9-
ENV BEATMAP_DIRECTORY=/beatmaps
7+
ENV ASPNETCORE_URLS="http://+:80"
8+
ENV ASPNETCORE_ENVIRONMENT="Production"
9+
ENV BEATMAP_DIRECTORY="/beatmaps"
10+
ENV DOWNLOAD_MISSING_BEATMAPS="true"
1011

1112
VOLUME ${BEATMAP_DIRECTORY}
1213
# chmod 777 so that this volume can be read/written by other containers that might use different uids

Makefile

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ start-dev: build-dev ## Starts development environment
2727
clean-dev: ## Cleans development environment
2828
$(COMPOSE_APP_DEV) down --remove-orphans
2929

30-
update-openapi-schemas: ## Updates OpenAPI schemas in docs site
31-
curl localhost:5000/swagger/v1/swagger.json -o docs/docs/api-reference/difficalcy-osu.json
32-
curl localhost:5001/swagger/v1/swagger.json -o docs/docs/api-reference/difficalcy-taiko.json
33-
curl localhost:5002/swagger/v1/swagger.json -o docs/docs/api-reference/difficalcy-catch.json
34-
curl localhost:5003/swagger/v1/swagger.json -o docs/docs/api-reference/difficalcy-mania.json
30+
update-api-reference: ## Updates OpenAPI schemas in docs site
31+
$(COMPOSE_TOOLING_RUN) scripts/update-api-reference.sh
32+
33+
check-api-reference: ## Checks OpenAPI schemas are updated
34+
$(COMPOSE_TOOLING_RUN) scripts/check-api-reference.sh
3535

3636
build-docs: ## Builds documentation site
3737
$(COMPOSE_RUN_DOCS) build --strict --clean

compose.tooling.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ services:
33
build:
44
context: .
55
dockerfile: ./tooling.Dockerfile
6+
volumes:
7+
- .:/app

docs/docs/api-reference/difficalcy-catch.json

+23-26
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
],
1313
"responses": {
1414
"200": {
15-
"description": "Success",
15+
"description": "OK",
1616
"content": {
1717
"application/json": {
1818
"schema": {
@@ -37,8 +37,7 @@
3737
"maximum": 2147483647,
3838
"minimum": 0,
3939
"type": "integer",
40-
"format": "int32",
41-
"nullable": true
40+
"format": "int32"
4241
}
4342
},
4443
{
@@ -58,8 +57,7 @@
5857
"maximum": 2147483647,
5958
"minimum": 0,
6059
"type": "integer",
61-
"format": "int32",
62-
"nullable": true
60+
"format": "int32"
6361
}
6462
},
6563
{
@@ -69,8 +67,7 @@
6967
"maximum": 2147483647,
7068
"minimum": 0,
7169
"type": "integer",
72-
"format": "int32",
73-
"nullable": true
70+
"format": "int32"
7471
}
7572
},
7673
{
@@ -94,7 +91,7 @@
9491
],
9592
"responses": {
9693
"200": {
97-
"description": "Success",
94+
"description": "OK",
9895
"content": {
9996
"application/json": {
10097
"schema": {
@@ -118,15 +115,14 @@
118115
"type": "array",
119116
"items": {
120117
"$ref": "#/components/schemas/CatchScore"
121-
},
122-
"nullable": true
118+
}
123119
}
124120
}
125121
}
126122
},
127123
"responses": {
128124
"200": {
129-
"description": "Success",
125+
"description": "OK",
130126
"content": {
131127
"application/json": {
132128
"schema": {
@@ -170,17 +166,27 @@
170166
},
171167
"additionalProperties": false
172168
},
173-
"CatchDifficulty": {
169+
"CatchCalculation": {
174170
"type": "object",
175171
"properties": {
176-
"total": {
172+
"difficulty": {
173+
"$ref": "#/components/schemas/CatchDifficulty"
174+
},
175+
"performance": {
176+
"$ref": "#/components/schemas/CatchPerformance"
177+
},
178+
"accuracy": {
179+
"type": "number",
180+
"format": "double"
181+
},
182+
"combo": {
177183
"type": "number",
178184
"format": "double"
179185
}
180186
},
181187
"additionalProperties": false
182188
},
183-
"CatchPerformance": {
189+
"CatchDifficulty": {
184190
"type": "object",
185191
"properties": {
186192
"total": {
@@ -190,20 +196,10 @@
190196
},
191197
"additionalProperties": false
192198
},
193-
"CatchCalculation": {
199+
"CatchPerformance": {
194200
"type": "object",
195201
"properties": {
196-
"difficulty": {
197-
"$ref": "#/components/schemas/CatchDifficulty"
198-
},
199-
"performance": {
200-
"$ref": "#/components/schemas/CatchPerformance"
201-
},
202-
"accuracy": {
203-
"type": "number",
204-
"format": "double"
205-
},
206-
"combo": {
202+
"total": {
207203
"type": "number",
208204
"format": "double"
209205
}
@@ -217,6 +213,7 @@
217213
"type": "object",
218214
"properties": {
219215
"beatmapId": {
216+
"minLength": 1,
220217
"type": "string"
221218
},
222219
"mods": {

docs/docs/api-reference/difficalcy-mania.json

+19-19
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
],
1313
"responses": {
1414
"200": {
15-
"description": "Success",
15+
"description": "OK",
1616
"content": {
1717
"application/json": {
1818
"schema": {
@@ -101,7 +101,7 @@
101101
],
102102
"responses": {
103103
"200": {
104-
"description": "Success",
104+
"description": "OK",
105105
"content": {
106106
"application/json": {
107107
"schema": {
@@ -125,15 +125,14 @@
125125
"type": "array",
126126
"items": {
127127
"$ref": "#/components/schemas/ManiaScore"
128-
},
129-
"nullable": true
128+
}
130129
}
131130
}
132131
}
133132
},
134133
"responses": {
135134
"200": {
136-
"description": "Success",
135+
"description": "OK",
137136
"content": {
138137
"application/json": {
139138
"schema": {
@@ -177,40 +176,40 @@
177176
},
178177
"additionalProperties": false
179178
},
180-
"ManiaDifficulty": {
179+
"ManiaCalculation": {
181180
"type": "object",
182181
"properties": {
183-
"total": {
182+
"difficulty": {
183+
"$ref": "#/components/schemas/ManiaDifficulty"
184+
},
185+
"performance": {
186+
"$ref": "#/components/schemas/ManiaPerformance"
187+
},
188+
"accuracy": {
184189
"type": "number",
185190
"format": "double"
186191
}
187192
},
188193
"additionalProperties": false
189194
},
190-
"ManiaPerformance": {
195+
"ManiaDifficulty": {
191196
"type": "object",
192197
"properties": {
193198
"total": {
194199
"type": "number",
195200
"format": "double"
196-
},
197-
"difficulty": {
198-
"type": "number",
199-
"format": "double"
200201
}
201202
},
202203
"additionalProperties": false
203204
},
204-
"ManiaCalculation": {
205+
"ManiaPerformance": {
205206
"type": "object",
206207
"properties": {
207-
"difficulty": {
208-
"$ref": "#/components/schemas/ManiaDifficulty"
209-
},
210-
"performance": {
211-
"$ref": "#/components/schemas/ManiaPerformance"
208+
"total": {
209+
"type": "number",
210+
"format": "double"
212211
},
213-
"accuracy": {
212+
"difficulty": {
214213
"type": "number",
215214
"format": "double"
216215
}
@@ -224,6 +223,7 @@
224223
"type": "object",
225224
"properties": {
226225
"beatmapId": {
226+
"minLength": 1,
227227
"type": "string"
228228
},
229229
"mods": {

0 commit comments

Comments
 (0)