Skip to content

Commit

Permalink
Implement rate change command
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebola3461 committed Dec 27, 2023
1 parent 207fb22 commit 817214c
Show file tree
Hide file tree
Showing 7 changed files with 625 additions and 68 deletions.
3 changes: 2 additions & 1 deletion modules/bancho/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import help from "./help";
import ratechange from "./ratechange";
import spectro from "./spectro";
import verify from "./verify";
import _with from "./with";

export const BanchoCommands = [help, verify, spectro, _with];
export const BanchoCommands = [help, verify, spectro, _with, ratechange];
115 changes: 115 additions & 0 deletions modules/bancho/commands/ratechange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { PrivateMessage } from "bancho.js";
import { ExecException } from "child_process";

import getOrCreateBanchoUser from "../../../database/utils/getOrCreateBanchoUser";
import { bufferToStream } from "../../../helpers/transform/bufferToStream";
import { LegacyBeatmapsetImporter } from "../../osu/fetcher/beatmap/LegacyBeatmapImporter";
import osuApi from "../../osu/fetcher/osuApi";
import { AudioSpectrogram } from "../../osu/spectrogram/AudioSpectrogram";
import { AxerBancho } from "../client";
import { BeatmapRateChanger } from "../../osu/ratechanger/BeatmapRateChanger";

export default {
settings: {
name: "ratechange",
description: "Generate a spectrogram image from the latest /np beatmap",
},
run: async function (pm: PrivateMessage, bancho: AxerBancho, args: string[]) {
const userApi = await pm.user.fetchFromAPI();
if (!userApi) return pm.user.sendMessage("Can't fetch api user");

const user = await getOrCreateBanchoUser(userApi.id);
if (!user) return pm.user.sendMessage("User not found! Try again.");

if (!user.last_beatmapset) return pm.user.sendMessage("Use /np before use this command!");

const rateInput = args[0];

if (!rateInput || isNaN(Number(rateInput.replace("x", ""))))
return pm.user.sendMessage("You should include output rate: !ratechange 1.2x");

const sanitizedRate = Number(rateInput.replace("x", ""));

if (sanitizedRate < 0.1 || sanitizedRate > 5)
return pm.user.sendMessage("Rate should be 0.1x - 5.0x");

pm.user.sendMessage("Downloading beatmap... This can take a while.");
const beatmapInfo = await osuApi.fetch.beatmapset(user.last_beatmapset);

if (beatmapInfo.status != 200) return pm.user.sendMessage("Can't find this beatmap!");

if (
(beatmapInfo.data.beatmaps?.sort((b, a) => a.total_length - b.total_length)[0]
.total_length || 0) > 600
)
return pm.user.sendMessage("This beatmap is too big! Max duration is 10 minutes");

const beatmap = await osuApi.download.beatmapset(user.last_beatmapset);

if (!beatmap.data || beatmap.status != 200 || !beatmap.data.buffer)
return pm.user.sendMessage("Error during beatmap download");

const importer = new LegacyBeatmapsetImporter(beatmap.data.buffer, user.last_beatmapset);
importer.import();

importer.on("end", () => {
pm.user.sendMessage("Beatmap download finished! Working on rate change...");

importer.loadBeatmaps();

const beatmaps = importer.getBeatmaps();
const targetDifficulty = beatmaps.find(
(b) => String(b.metadata.beatmapId) == user.last_beatmap
);

if (!targetDifficulty) {
importer.deleteBeatmap();

return pm.user.sendMessage("This beatmapset doesn't has the requested beatmap id!");
}

const audioFile = importer.getAudioFileFrom(targetDifficulty.metadata.beatmapId);

if (!audioFile) {
importer.deleteBeatmap();

return pm.user.sendMessage("This difficulty doesn't have an audio file!");
}

function parseOptions() {
const validOptions = ["-noscaleod", "-noscalear"];

let scaleAr = true;
let scaleOd = true;

const options = args.filter(
(option) =>
option.startsWith("-") && validOptions.includes(option.toLowerCase())
);

if (options.includes("-noscalear")) scaleAr = false;
if (options.includes("-noscaleod")) scaleOd = false;

return {
scaleAr,
scaleOd,
};
}

const rateChanger = new BeatmapRateChanger(
targetDifficulty,
audioFile,
sanitizedRate,
parseOptions()
);

rateChanger.generate().then((fileId) => {
rateChanger.packToOSZ().then(() => {
pm.user.sendMessage(
`Beatmap rate changed to ${sanitizedRate}x! [https://${process.env.RATECHANGER_URL}/ratechange/download/${fileId} Download]`
);
});
});
});
},
};
53 changes: 12 additions & 41 deletions modules/osu/fetcher/beatmap/LegacyBeatmapImporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ export class LegacyBeatmapsetImporter extends EventEmitter {

this.validateTempFolders();

writeFileSync(
path.join(this.ImportFolder, beatmapsetId).concat(".zip"),
osz
);
writeFileSync(path.join(this.ImportFolder, beatmapsetId).concat(".zip"), osz);
}

private getBeatmapsetId() {
Expand All @@ -52,11 +49,7 @@ export class LegacyBeatmapsetImporter extends EventEmitter {

for (const beatmapFile of beatmapFiles) {
const fileContent = readFileSync(
path.join(
this.getImportFolder(),
this.getBeatmapsetId(),
beatmapFile
),
path.join(this.getImportFolder(), this.getBeatmapsetId(), beatmapFile),
"utf8"
);

Expand All @@ -76,9 +69,7 @@ export class LegacyBeatmapsetImporter extends EventEmitter {

public getAudioFileFrom(beatmapId: number) {
try {
const mapData = this.Beatmaps.find(
(b) => b.metadata.beatmapId == beatmapId
);
const mapData = this.Beatmaps.find((b) => b.metadata.beatmapId == beatmapId);

if (!mapData) return null;

Expand Down Expand Up @@ -106,18 +97,18 @@ export class LegacyBeatmapsetImporter extends EventEmitter {

try {
yauzl.open(
path
.join(this.getImportFolder(), this.getBeatmapsetId())
.concat(".zip"),
path.join(this.getImportFolder(), this.getBeatmapsetId()).concat(".zip"),
{ lazyEntries: true },
(err, zipfile) => {
if (err) throw err;

zipfile.readEntry();

zipfile.on("entry", (entry) => {
entry.fileName = entry.fileName.replace(/\\/g, "_");

/// * Check if the entry is a folder
if (entry.fileName.split("/").length != 1) {
if (entry.fileName.replace(/\\/g, "_").split("/").length != 1) {
this.createFolders(
entry.fileName
.split("/")
Expand Down Expand Up @@ -160,11 +151,7 @@ export class LegacyBeatmapsetImporter extends EventEmitter {
}

public deleteOsz() {
unlinkSync(
path
.join(this.getImportFolder(), this.getBeatmapsetId())
.concat(".zip")
);
unlinkSync(path.join(this.getImportFolder(), this.getBeatmapsetId()).concat(".zip"));
}

private createFolders(paths: string[]) {
Expand All @@ -175,22 +162,8 @@ export class LegacyBeatmapsetImporter extends EventEmitter {
for (const _path of paths) {
target.push(_path);

if (
!existsSync(
path.join(
this.ImportFolder,
this.BeatmapsetId,
target.join("/")
)
)
)
mkdirSync(
path.join(
this.ImportFolder,
this.BeatmapsetId,
target.join("/")
)
);
if (!existsSync(path.join(this.ImportFolder, this.BeatmapsetId, target.join("/"))))
mkdirSync(path.join(this.ImportFolder, this.BeatmapsetId, target.join("/")));
}
}

Expand All @@ -201,11 +174,9 @@ export class LegacyBeatmapsetImporter extends EventEmitter {
}

private validateTempFolders() {
if (!existsSync(path.resolve(this.ImportFolder)))
mkdirSync(this.ImportFolder);
if (!existsSync(path.resolve(this.ImportFolder))) mkdirSync(this.ImportFolder);

if (existsSync(path.join(this.ImportFolder, this.BeatmapsetId)))
this.deleteBeatmap();
if (existsSync(path.join(this.ImportFolder, this.BeatmapsetId))) this.deleteBeatmap();

mkdirSync(path.join(this.ImportFolder, this.BeatmapsetId));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
import OsuBeatmapsetDownloader, {
BeatmapsetDownloadOptions,
BeatmapsetDownloadOptions,
} from "../struct/OsuBeatmapsetDownloader";
import DownloadClient from "../struct/DownloadClient";
import Downloader from "../struct/Downloader";

export default class OsuOfficialDownloader extends OsuBeatmapsetDownloader {
#osu_session: string;
#osu_session: string;

constructor(client: DownloadClient, osu_session: string) {
super(client);
this.#osu_session = osu_session;
}
constructor(client: DownloadClient, osu_session: string) {
super(client);
this.#osu_session = osu_session;
}

getSession(): string {
return this.#osu_session;
}
getSession(): string {
return this.#osu_session;
}

setSession(osu_session: string) {
this.#osu_session = osu_session;
}
setSession(osu_session: string) {
this.#osu_session = osu_session;
}

download(options: BeatmapsetDownloadOptions): Downloader {
const url = new URL(
`https://osu.ppy.sh/beatmapsets/${options.beatmapsetId}/download?noVideo=1`
);
download(options: BeatmapsetDownloadOptions): Downloader {
const url = new URL(
`https://osu.ppy.sh/beatmapsets/${options.beatmapsetId}/download?noVideo=1`
);

const headers = {
cookie: `osu_session=${this.#osu_session}`,
referer: url.href,
};
return this.client.download(url, { headers });
}
const headers = {
cookie: `osu_session=${this.#osu_session}`,
referer: url.href,
};

return this.client.download(url, { headers });
}
}
Loading

0 comments on commit 817214c

Please sign in to comment.