2022-10-16 13:54:29 +00:00
|
|
|
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
|
|
|
|
const { setupTitlebar, attachTitlebarToWindow } = require('custom-electron-titlebar/main');
|
|
|
|
const windowManager = require('./ui/windowManager');
|
2022-10-16 14:47:31 +00:00
|
|
|
const osuUtil = require('./osuUtil');
|
2022-10-17 23:46:04 +00:00
|
|
|
const ezppUtil = require('./ezppUtil');
|
2022-10-16 16:41:53 +00:00
|
|
|
const config = require('./config');
|
|
|
|
const fs = require('fs');
|
2022-10-20 22:57:42 +00:00
|
|
|
const rpc = require('./discordPresence');
|
|
|
|
const windowName = require('get-window-by-name');
|
2022-10-24 04:36:03 +00:00
|
|
|
const terminalUtil = require('./terminalUtil');
|
2022-12-23 20:41:39 +00:00
|
|
|
const osUtil = require('./osUtil');
|
2022-10-16 16:41:53 +00:00
|
|
|
|
|
|
|
let tempOsuPath;
|
2022-10-20 22:57:42 +00:00
|
|
|
let osuWindowInfo;
|
2022-10-22 23:08:58 +00:00
|
|
|
let isIngame;
|
|
|
|
const platform = process.platform;
|
2022-10-24 04:36:03 +00:00
|
|
|
let linuxWMCtrlFound = false;
|
2022-10-27 11:58:15 +00:00
|
|
|
let osuLoaded = false;
|
2022-10-16 13:54:29 +00:00
|
|
|
|
|
|
|
const run = () => {
|
|
|
|
const gotTheLock = app.requestSingleInstanceLock()
|
|
|
|
if (!gotTheLock) {
|
|
|
|
app.quit();
|
|
|
|
return;
|
|
|
|
}
|
2022-10-16 16:41:53 +00:00
|
|
|
|
2022-10-22 23:08:58 +00:00
|
|
|
setInterval(async () => {
|
|
|
|
if (platform == "win32") {
|
|
|
|
osuWindowInfo = windowName.getWindowText("osu!.exe");
|
|
|
|
const firstInstance = osuWindowInfo[0];
|
|
|
|
if (firstInstance) {
|
|
|
|
if (firstInstance.processTitle && firstInstance.processTitle.length > 0) {
|
2022-10-27 11:58:15 +00:00
|
|
|
if (!osuLoaded) {
|
|
|
|
osuLoaded = true;
|
|
|
|
//TODO: do patch
|
|
|
|
}
|
2022-10-22 23:08:58 +00:00
|
|
|
const windowTitle = firstInstance.processTitle;
|
|
|
|
let rpcOsuVersion = "";
|
|
|
|
let currentMap = undefined;
|
|
|
|
if (!windowTitle.includes("-")) {
|
|
|
|
rpcOsuVersion = windowTitle;
|
|
|
|
rpc.updateState("Idle...");
|
|
|
|
} else {
|
|
|
|
var string = windowTitle;
|
|
|
|
var components = string.split(' - ');
|
|
|
|
const splitArray = [components.shift(), components.join(' - ')];
|
|
|
|
rpcOsuVersion = splitArray[0];
|
|
|
|
currentMap = splitArray[1];
|
2022-12-23 20:41:39 +00:00
|
|
|
if (currentMap.endsWith(".osu")) {
|
2022-10-27 04:38:58 +00:00
|
|
|
rpc.updateState("Editing...");
|
|
|
|
currentMap = currentMap.substring(0, currentMap.length - 4);
|
|
|
|
} else rpc.updateState("Playing...");
|
2022-10-22 23:08:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rpc.updateStatus(currentMap, rpcOsuVersion);
|
2022-10-20 22:57:42 +00:00
|
|
|
} else {
|
2022-10-27 11:58:15 +00:00
|
|
|
if (osuLoaded) osuLoaded = false;
|
2022-10-22 23:08:58 +00:00
|
|
|
rpc.updateState("Idle in Launcher...");
|
|
|
|
rpc.updateStatus(undefined, undefined);
|
2022-10-20 22:57:42 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-10-27 11:58:15 +00:00
|
|
|
if (osuLoaded) osuLoaded = false;
|
2022-10-20 22:57:42 +00:00
|
|
|
rpc.updateState("Idle in Launcher...");
|
|
|
|
rpc.updateStatus(undefined, undefined);
|
|
|
|
}
|
2022-10-24 04:36:03 +00:00
|
|
|
} else if (platform == "linux") {
|
|
|
|
if (!linuxWMCtrlFound) {
|
|
|
|
if (isIngame) {
|
|
|
|
rpc.updateState("Playing...");
|
|
|
|
rpc.updateStatus("Clicking circles!", "runningunderwine");
|
|
|
|
} else {
|
|
|
|
rpc.updateState("Idle in Launcher...");
|
|
|
|
rpc.updateStatus(undefined, undefined);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const processesOutput = await terminalUtil.execCommand(`wmctrl -l|awk '{$3=""; $2=""; $1=""; print $0}'`);
|
|
|
|
const allLines = processesOutput.split("\n");
|
|
|
|
const filteredProcesses = allLines.filter((line) => line.trim().startsWith("osu!"));
|
|
|
|
if (filteredProcesses.length > 0) {
|
|
|
|
const windowTitle = filteredProcesses[0].trim();
|
|
|
|
let rpcOsuVersion = "";
|
|
|
|
let currentMap = undefined;
|
|
|
|
if (!windowTitle.includes("-")) {
|
|
|
|
rpcOsuVersion = windowTitle;
|
|
|
|
rpc.updateState("Idle...");
|
|
|
|
} else {
|
|
|
|
var string = windowTitle;
|
|
|
|
var components = string.split(' - ');
|
|
|
|
const splitArray = [components.shift(), components.join(' - ')];
|
|
|
|
rpcOsuVersion = splitArray[0];
|
|
|
|
currentMap = splitArray[1];
|
2022-12-23 20:41:39 +00:00
|
|
|
if (currentMap.endsWith(".osu")) {
|
2023-05-04 19:22:32 +00:00
|
|
|
rpc.updateState("Editing/Modding...");
|
2022-10-27 04:38:58 +00:00
|
|
|
currentMap = currentMap.substring(0, currentMap.length - 4);
|
2022-12-23 20:41:39 +00:00
|
|
|
}
|
2022-10-27 04:38:58 +00:00
|
|
|
else rpc.updateState("Playing...");
|
2022-10-24 04:36:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rpc.updateStatus(currentMap, rpcOsuVersion);
|
|
|
|
} else {
|
|
|
|
rpc.updateState("Idle in Launcher...");
|
|
|
|
rpc.updateStatus(undefined, undefined);
|
|
|
|
}
|
2022-10-20 22:57:42 +00:00
|
|
|
} else {
|
2022-10-23 15:07:20 +00:00
|
|
|
if (isIngame) {
|
2022-10-22 23:08:58 +00:00
|
|
|
rpc.updateState("Playing...");
|
|
|
|
rpc.updateStatus("Clicking circles!", "runningunderwine");
|
2022-10-23 15:07:20 +00:00
|
|
|
} else {
|
2022-10-22 23:08:58 +00:00
|
|
|
rpc.updateState("Idle in Launcher...");
|
|
|
|
rpc.updateStatus(undefined, undefined);
|
|
|
|
}
|
2022-10-20 22:57:42 +00:00
|
|
|
}
|
|
|
|
}, 2000);
|
|
|
|
|
2022-10-16 13:54:29 +00:00
|
|
|
setupTitlebar();
|
|
|
|
|
2022-10-20 22:57:42 +00:00
|
|
|
rpc.connect();
|
|
|
|
|
|
|
|
|
2022-10-16 13:54:29 +00:00
|
|
|
let mainWindow;
|
|
|
|
app.whenReady().then(() => {
|
|
|
|
|
2022-10-16 16:41:53 +00:00
|
|
|
mainWindow = createWindow();
|
|
|
|
mainWindow.on('show', async () => {
|
2022-10-17 14:37:12 +00:00
|
|
|
await updateConfigVars(mainWindow);
|
|
|
|
await tryLogin(mainWindow);
|
2022-10-17 23:46:04 +00:00
|
|
|
await doUpdateCheck(mainWindow);
|
2022-10-23 15:07:20 +00:00
|
|
|
if (platform === "linux") {
|
2022-12-23 20:41:39 +00:00
|
|
|
const linuxDistroInfo = await osUtil.getLinuxDistroInfo();
|
|
|
|
if (linuxDistroInfo?.id != "arch") {
|
|
|
|
if (linuxDistroInfo?.id_like != "arch") {
|
|
|
|
mainWindow.webContents.send('status_update', {
|
|
|
|
type: "info",
|
|
|
|
message: "We detected that you are running the Launcher under Linux. It's currently just compatible with Arch like distributions!"
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
await terminalUtil.execCommand(`osu-stable -h`);
|
|
|
|
} catch (err) {
|
2022-10-27 04:38:58 +00:00
|
|
|
mainWindow.webContents.send('status_update', {
|
|
|
|
type: "package-issue",
|
|
|
|
message: "Seems like you dont have the osu AUR Package installed, please install it."
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2022-10-24 04:36:03 +00:00
|
|
|
/* mainWindow.webContents.send('status_update', {
|
2022-10-23 15:07:20 +00:00
|
|
|
type: "info",
|
|
|
|
message: "We detected that you are running the Launcher under Linux. It's currently just compatible with Arch and the osu AUR package!"
|
2022-10-24 04:36:03 +00:00
|
|
|
}); */
|
|
|
|
const terminalTest = await terminalUtil.execCommand(`wmctrl -l|awk '{$3=""; $2=""; $1=""; print $0}'`);
|
|
|
|
const isFailed = terminalTest.trim() == "";
|
|
|
|
if (isFailed) {
|
|
|
|
mainWindow.webContents.send('status_update', {
|
|
|
|
type: "info",
|
|
|
|
message: "Seems like you are missing the wmctrl package, please install it for the RPC to work!"
|
|
|
|
});
|
|
|
|
} else linuxWMCtrlFound = true;
|
2022-10-27 14:28:22 +00:00
|
|
|
} else {
|
|
|
|
const osuFolder = await config.get("osuPath");
|
|
|
|
if (!osuFolder || osuFolder == "") {
|
|
|
|
const foundFolder = await osuUtil.findOsuInstallation();
|
|
|
|
console.log("osu! Installation located at: ",foundFolder);
|
|
|
|
}
|
2022-10-23 15:07:20 +00:00
|
|
|
}
|
2022-10-16 20:44:56 +00:00
|
|
|
})
|
|
|
|
app.on('activate', function () {
|
|
|
|
if (BrowserWindow.getAllWindows().length === 0) mainWindow = createWindow();
|
|
|
|
})
|
|
|
|
app.on('window-all-closed', () => {
|
|
|
|
app.quit()
|
|
|
|
})
|
2022-10-16 21:10:07 +00:00
|
|
|
ipcMain.handle('launch', async () => {
|
2022-10-17 23:46:04 +00:00
|
|
|
const osuConfig = await osuUtil.getLatestConfig(tempOsuPath);
|
|
|
|
const username = await config.get('username');
|
|
|
|
const password = await config.get('password');
|
|
|
|
if (password && username) {
|
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "SaveUsername", "1");
|
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "SavePassword", "1");
|
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "Username", username);
|
2022-10-22 23:08:58 +00:00
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "Password", password);
|
2022-10-17 23:46:04 +00:00
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "CredentialEndpoint", "ez-pp.farm");
|
|
|
|
} else {
|
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "Username", "");
|
|
|
|
await osuUtil.setConfigValue(osuConfig.path, "Password", "");
|
|
|
|
}
|
2022-10-20 22:57:42 +00:00
|
|
|
rpc.updateState("Launching osu!...");
|
2022-10-22 23:08:58 +00:00
|
|
|
isIngame = true;
|
2022-10-27 14:28:22 +00:00
|
|
|
mainWindow.hide();
|
2022-10-16 21:10:07 +00:00
|
|
|
const result = await osuUtil.startOsuWithDevServer(tempOsuPath, "ez-pp.farm", async () => {
|
2022-10-22 23:08:58 +00:00
|
|
|
isIngame = false;
|
2022-10-27 14:28:22 +00:00
|
|
|
mainWindow.show();
|
2022-10-16 21:10:07 +00:00
|
|
|
await doUpdateCheck(mainWindow);
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
})
|
2022-10-16 20:44:56 +00:00
|
|
|
ipcMain.on('do-update-check', async () => {
|
|
|
|
await doUpdateCheck(mainWindow);
|
|
|
|
})
|
|
|
|
ipcMain.on('do-update', async () => {
|
2022-10-16 16:41:53 +00:00
|
|
|
const osuPath = await config.get("osuPath", "");
|
2022-10-16 20:20:50 +00:00
|
|
|
const isValid = await osuUtil.isValidOsuFolder(osuPath);
|
|
|
|
if (osuPath.trim == "" || !isValid) {
|
|
|
|
mainWindow.webContents.send('status_update', {
|
2022-10-16 20:44:56 +00:00
|
|
|
type: "error",
|
|
|
|
message: "Invalid osu! folder"
|
|
|
|
});
|
2022-10-16 20:20:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-10-16 16:52:34 +00:00
|
|
|
if (fs.existsSync(osuPath)) {
|
2022-10-16 16:41:53 +00:00
|
|
|
tempOsuPath = osuPath;
|
|
|
|
const osuConfig = await osuUtil.getLatestConfig(tempOsuPath);
|
|
|
|
const lastVersion = await osuConfig.get("LastVersion");
|
2022-10-16 16:52:34 +00:00
|
|
|
let releaseStream = "stable40";
|
|
|
|
if (lastVersion.endsWith("cuttingedge"))
|
|
|
|
releaseStream = "cuttingedge"
|
|
|
|
else if (lastVersion.endsWith("beta"))
|
|
|
|
releaseStream = "beta";
|
2022-10-16 19:13:30 +00:00
|
|
|
|
2022-10-16 16:52:34 +00:00
|
|
|
const releaseFiles = await osuUtil.getUpdateFiles(releaseStream);
|
2022-10-16 19:13:30 +00:00
|
|
|
const filesToDownload = await osuUtil.filesThatNeedUpdate(tempOsuPath, releaseFiles);
|
2022-10-16 20:44:56 +00:00
|
|
|
const downloadTask = await osuUtil.downloadUpdateFiles(osuPath, filesToDownload);
|
|
|
|
downloadTask.on('completed', () => {
|
|
|
|
mainWindow.webContents.send('status_update', {
|
|
|
|
type: "update-complete"
|
|
|
|
})
|
|
|
|
});
|
2022-10-20 17:08:48 +00:00
|
|
|
downloadTask.on('error', () => {
|
|
|
|
mainWindow.webContents.send('status_update', {
|
|
|
|
type: "error",
|
|
|
|
message: "An error occured while updating."
|
|
|
|
});
|
|
|
|
});
|
2022-10-16 20:44:56 +00:00
|
|
|
|
2022-10-16 20:20:50 +00:00
|
|
|
} else
|
|
|
|
mainWindow.webContents.send('status_update', {
|
2022-10-16 20:44:56 +00:00
|
|
|
type: "error",
|
|
|
|
message: "Invalid osu! folder"
|
|
|
|
});
|
2022-10-16 13:54:29 +00:00
|
|
|
})
|
2022-10-16 14:47:31 +00:00
|
|
|
ipcMain.handle('set-osu-dir', async (event) => {
|
2022-10-16 13:54:29 +00:00
|
|
|
const yes = await dialog.showOpenDialog({
|
|
|
|
properties: ['openDirectory']
|
|
|
|
})
|
2022-10-16 14:47:31 +00:00
|
|
|
if (yes.filePaths.length <= 0)
|
|
|
|
return undefined;
|
|
|
|
const folderPath = yes.filePaths[0];
|
2022-10-16 20:20:50 +00:00
|
|
|
const validOsuDir = await osuUtil.isValidOsuFolder(folderPath);
|
2022-10-16 16:41:53 +00:00
|
|
|
|
|
|
|
if (validOsuDir) await config.set("osuPath", folderPath);
|
|
|
|
|
2022-10-17 23:46:04 +00:00
|
|
|
return { validOsuDir, folderPath };
|
|
|
|
})
|
|
|
|
ipcMain.handle('perform-login', async (event, data) => {
|
|
|
|
const { username, password } = data;
|
|
|
|
const loginData = await ezppUtil.performLogin(username, password);
|
|
|
|
if (loginData && loginData.code === 200) {
|
|
|
|
await config.set("username", username);
|
2022-10-22 23:08:58 +00:00
|
|
|
await config.set("password", password);
|
2022-10-17 23:46:04 +00:00
|
|
|
}
|
|
|
|
return loginData;
|
|
|
|
})
|
|
|
|
ipcMain.on('perform-logout', async (event) => {
|
|
|
|
await config.remove("username");
|
|
|
|
await config.remove("password");
|
2022-10-16 13:54:29 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-10-17 14:37:12 +00:00
|
|
|
async function updateConfigVars(window) {
|
2022-10-17 23:46:04 +00:00
|
|
|
const osuPath = await config.get("osuPath", "");
|
2022-10-17 14:37:12 +00:00
|
|
|
window.webContents.send('config_update', {
|
|
|
|
osuPath: osuPath
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function tryLogin(window) {
|
2022-10-17 23:46:04 +00:00
|
|
|
const username = await config.get("username", "");
|
|
|
|
const password = await config.get("password", "");
|
2022-10-17 14:37:12 +00:00
|
|
|
if ((username && username.length > 0) && (password && password.length > 0)) {
|
2022-10-22 23:08:58 +00:00
|
|
|
const passwordPlain = password;
|
2022-10-17 23:46:04 +00:00
|
|
|
const loginResponse = await ezppUtil.performLogin(username, passwordPlain);
|
|
|
|
if (loginResponse && loginResponse.code === 200) {
|
|
|
|
window.webContents.send('account_update', {
|
|
|
|
type: "loggedin",
|
|
|
|
user: loginResponse.user
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
window.webContents.send('account_update', {
|
|
|
|
type: "login-failed"
|
|
|
|
})
|
|
|
|
}
|
2022-10-17 14:37:12 +00:00
|
|
|
} else {
|
|
|
|
window.webContents.send('account_update', {
|
|
|
|
type: "not-loggedin"
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-16 20:44:56 +00:00
|
|
|
async function doUpdateCheck(window) {
|
2022-10-17 23:46:04 +00:00
|
|
|
const osuPath = await config.get("osuPath");
|
|
|
|
if (!osuPath || osuPath.trim == "") {
|
|
|
|
window.webContents.send('status_update', {
|
|
|
|
type: "missing-folder"
|
|
|
|
})
|
|
|
|
return;
|
|
|
|
}
|
2022-10-16 20:44:56 +00:00
|
|
|
const isValid = await osuUtil.isValidOsuFolder(osuPath);
|
2022-10-17 23:46:04 +00:00
|
|
|
if (!isValid) {
|
2022-10-16 20:44:56 +00:00
|
|
|
window.webContents.send('status_update', {
|
|
|
|
type: "missing-folder"
|
|
|
|
})
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fs.existsSync(osuPath)) {
|
|
|
|
tempOsuPath = osuPath;
|
|
|
|
const osuConfig = await osuUtil.getLatestConfig(tempOsuPath);
|
|
|
|
const lastVersion = await osuConfig.get("LastVersion");
|
|
|
|
let releaseStream = "stable40";
|
|
|
|
if (lastVersion.endsWith("cuttingedge"))
|
|
|
|
releaseStream = "cuttingedge"
|
|
|
|
else if (lastVersion.endsWith("beta"))
|
|
|
|
releaseStream = "beta";
|
|
|
|
|
|
|
|
const releaseFiles = await osuUtil.getUpdateFiles(releaseStream);
|
|
|
|
const filesToDownload = await osuUtil.filesThatNeedUpdate(tempOsuPath, releaseFiles);
|
|
|
|
window.webContents.send('status_update', {
|
|
|
|
type: filesToDownload.length > 0 ? "update-available" : "up-to-date"
|
|
|
|
})
|
|
|
|
} else
|
|
|
|
window.webContents.send('status_update', {
|
|
|
|
type: "missing-folder"
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-10-16 13:54:29 +00:00
|
|
|
function createWindow() {
|
|
|
|
// Create the browser window.
|
2022-10-27 13:42:29 +00:00
|
|
|
const win = windowManager.createWindow(700, 460);
|
2022-10-16 13:54:29 +00:00
|
|
|
|
|
|
|
win.loadFile('./html/index.html');
|
|
|
|
|
|
|
|
attachTitlebarToWindow(win);
|
2022-10-16 14:06:06 +00:00
|
|
|
win.webContents.setWindowOpenHandler(() => "deny");
|
2022-10-16 13:54:29 +00:00
|
|
|
win.webContents.on('did-finish-load', function () {
|
|
|
|
if (win.webContents.getZoomFactor() != 0.9)
|
|
|
|
win.webContents.setZoomFactor(0.9)
|
|
|
|
});
|
|
|
|
|
|
|
|
return win;
|
|
|
|
}
|
|
|
|
|
|
|
|
run();
|