Updated return data for public endpoint & added bulk admin endpoint
Some checks failed
Build & Lint / build-lint (push) Failing after 1m14s
Deploy / setup (push) Failing after 1m6s

This commit is contained in:
pfych 2024-10-20 10:11:06 +11:00
parent 5ef33a9f49
commit 6a0dcce2bd
3 changed files with 129 additions and 8 deletions

View File

@ -0,0 +1,87 @@
# Process for Uploading Charts
1. Find a bms bundle/zip ie. `p_stands_for_party_newbga_ogg.zip`
2. Upload zip to BackBlaze B2 storage bucket
3. Open the admin dashboard for bms-repository
4. Unzip the bms bundle/zip on your local machine
5. For each bms file in the unzipped folder:
1. Copy the zip friendly url from BackBlaze B2
2. Create a new chart in the admin dashboard
3. Paste the zip friendly url into the `resourceUri` field
4. Set the `md5` and `sha256` fields to the md5 and sha256 of the bms file
5. Set the `name` field to the name of the chart + difficulty
- ie. `"P" stands for "Party!" [Another]`
## Script for generating chart JSON
Run in the freshly unzipped folder
```shell
#!/bin/bash
FILES=($(find . -name "*.bm*"));
JSON="["
for CHART in "${FILES[@]}"
do
MD5=$(md5sum "$CHART" | cut -d ' ' -f 1)
SHA256=$(sha256sum "$CHART" | cut -d ' ' -f 1)
TITLE=$(cat "$CHART" | grep "#TITLE" | sed -e s/^.*\#TITLE// | xargs | tr -d '\r')
UUID=$(uuidgen)
JSON+=$(jq -n \
--arg chartId "$UUID" \
--arg md5 "$MD5" \
--arg sha256 "$SHA256" \
--arg name "$TITLE" \
--arg resourceUri "$1" \
'. += $ARGS.named')
done
echo "$JSON]" | sed -e s/\}\{/},{/g | jq # Lazy, couldn't get JQ append working lol
```
First argument is the upload url
```shell
./export.sh https://example.com/zips/myzip.zip
```
While authenticated as an admin user, hit the `bulk` endpoint with the generated JSON after confirming that it is valid.
```shell
curl --request POST \
--url https://<API_URL>/chart/admin/bulk \
--header 'Authorization: Bearer Token' \
--header 'Content-Type: application/json' \
--data '[
{
"chartId": "9923c511-355c-4ed8-9551-4b31fec45560",
"md5": "8d80d1732fa4c81dcbd4ddfd1673d949",
"sha256": "b796cdef4fa8865035d282be275cbda878203359c8ba630ac9ba619b52322346",
"name": "P stands for Party! [Hyper]",
"resourceUri": "https://f002.backblazeb2.com/file/bms-chart-storage-staging/p_stands_for_party_newbga_ogg.zip"
},
{
"chartId": "4684b205-d1d9-4bcc-ace3-47e044988ff0",
"md5": "b81eea46f8600fabab3e3f6bce2a2cc7",
"sha256": "806c56cbb413d390c84a8d49b9888fecaac4571d5a2337b450ec23f28b10c725",
"name": "P stands for Party! [Another]",
"resourceUri": "https://f002.backblazeb2.com/file/bms-chart-storage-staging/p_stands_for_party_newbga_ogg.zip"
},
{
"chartId": "ce9af400-4726-49ed-9ee2-13652bd98410",
"md5": "b963e1f212e3783cfd566b59b5cb472d",
"sha256": "17588424eea6479ed90dec7d7ffa1991bc049fd4c2ea218a1408f8febed64121",
"name": "P stands for Party! [Beginner]",
"resourceUri": "https://f002.backblazeb2.com/file/bms-chart-storage-staging/p_stands_for_party_newbga_ogg.zip"
},
{
"chartId": "9834898f-c0ba-4a4f-a0b9-ac701e8a6f3a",
"md5": "c6c5e5e20b53983ba59252ddcc205b5b",
"sha256": "a60bdb0e6d2cd9d54c53decc33932b2eee7cd15966e0dd0666c368ff58070a3a",
"name": "P stands for Party! [Normal]",
"resourceUri": "https://f002.backblazeb2.com/file/bms-chart-storage-staging/p_stands_for_party_newbga_ogg.zip"
}
]'
```

View File

@ -35,6 +35,32 @@ app.post('/chart/admin', [
},
]);
app.post('/chart/admin/bulk', [
isAdmin,
async (req: RequestContext, res: Response) => {
try {
const chartData = (req.body as Chart[]).map((chart) => ({
md5: chart.md5,
sha256: chart.sha256,
resourceUri: chart.resourceUri,
parentChart: chart.parentChart,
name: chart.name,
comment: chart.comment,
}));
const charts = await Promise.all(
chartData.map((chart) => chartService.create(chart)),
);
res.json(charts.map(chartMapper));
} catch (error) {
const message = getErrorMessage(error);
console.error(`Failed to create chart ${message}`);
res.status(400).json({ error: 'Failed to create chart' });
}
},
]);
app.patch('/chart/admin', [
isAdmin,
async (req: RequestContext, res: Response) => {

View File

@ -4,7 +4,7 @@ import { RequestContext } from '../../util/request-context.type';
import { Response } from 'express';
import { getErrorMessage } from '../../util/error-message';
import { getChartsByMd5, getChartsBySha256 } from './chart.service';
import { flatten, keyBy } from 'lodash-es';
import { flatten, uniqBy } from 'lodash-es';
const app = createApp();
export const handler = createAuthenticatedHandler(app);
@ -17,22 +17,30 @@ app.post('/chart/public', [
sha256: string[];
};
/** @TODO Ask herman how to batch query */
const md5Charts = flatten(
await Promise.all(md5.map((md5) => getChartsByMd5(md5))),
);
const md5ChartsKeyedByMd5 = keyBy(md5Charts, 'md5');
console.log(md5Charts);
const md5ChartsFound = md5Charts.map((chart) => chart.md5);
const md5ChartsNotFound = md5.filter(
(md5) => !md5ChartsFound.includes(md5),
);
const sha256Charts = flatten(
await Promise.all(sha256.map((sha256) => getChartsBySha256(sha256))),
);
const sha256ChartsKeyedBySha256 = keyBy(sha256Charts, 'sha256');
const sha256ChartsFound = sha256Charts.map((chart) => chart.sha256);
const sha256ChartsNotFound = sha256.filter(
(sha256) => !sha256ChartsFound.includes(sha256),
);
res.json({
md5: md5ChartsKeyedByMd5,
sha256: sha256ChartsKeyedBySha256,
resources: uniqBy([...md5Charts, ...sha256Charts], 'resourceUri').map(
(chart) => chart.resourceUri,
),
metadata: {
success: [...md5ChartsFound, ...sha256ChartsFound],
failure: [...md5ChartsNotFound, ...sha256ChartsNotFound],
},
});
} catch (error) {
const message = getErrorMessage(error);