mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2025-02-13 01:11:20 +01:00
Revert "temp Revert "cleanup, js classes""
This reverts commit 37ca5e22f6
.
This commit is contained in:
parent
37ca5e22f6
commit
85f08be29b
@ -169,13 +169,6 @@ script-src 'self' https://*.cloudflare.com/ https://alcdn.msauth.net/ https://*.
|
||||
<script src="https://alcdn.msauth.net/browser/2.15.0/js/msal-browser.min.js" integrity="sha384-/weuqUPkC0P9JxnstihEV1GHdWrheU9Qo3MbdTuxxKJM8l/cSTE5zGP5VBIM4TZN"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="js/account_manager.js"></script>
|
||||
<script src="js/auth_ms.js"></script>
|
||||
<script src="js/cors_proxy.js"></script>
|
||||
<script src="js/minecraft_id.js"></script>
|
||||
<script src="js/notification.js"></script>
|
||||
<script src="js/page.js"></script>
|
||||
<script src="js/util.js"></script>
|
||||
<script src="js/websocket.js"></script>
|
||||
<script type="module" src="js/page.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,35 +1,226 @@
|
||||
// Account storage
|
||||
function storeMcAccount(accessToken, clientToken, name, id, msUser = null) {
|
||||
let accounts = JSON.parse(localStorage.getItem("viaaas_mc_accounts")) || [];
|
||||
let account = {accessToken: accessToken, clientToken: clientToken, name: name, id: id, msUser: msUser};
|
||||
accounts.push(account);
|
||||
localStorage.setItem("viaaas_mc_accounts", JSON.stringify(accounts));
|
||||
refreshAccountList();
|
||||
return account;
|
||||
import {getCorsProxy} from "./cors_proxy.js";
|
||||
import {checkFetchSuccess, filterNot, isSuccess} from "./util.js";
|
||||
import {addToast, refreshAccountList} from "./page.js";
|
||||
|
||||
let activeAccounts = [];
|
||||
|
||||
function loadAccounts() {
|
||||
(JSON.parse(localStorage.getItem("viaaas_mc_accounts")) || []).forEach(it => {
|
||||
if (it.clientToken) {
|
||||
addActiveAccount(new MojangAccount(it.id, it.name, it.accessToken, it.clientToken))
|
||||
} else if (it.msUser) {
|
||||
addActiveAccount(new MicrosoftAccount(it.id, it.name, it.accessToken, it.msUser))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function removeMcAccount(id) {
|
||||
let accounts = getMcAccounts();
|
||||
accounts = accounts.filter(it => it.id != id);
|
||||
localStorage.setItem("viaaas_mc_accounts", JSON.stringify(accounts));
|
||||
refreshAccountList();
|
||||
$(() => loadAccounts());
|
||||
|
||||
function saveRefreshAccounts() {
|
||||
localStorage.setItem("viaaas_mc_accounts", JSON.stringify(getActiveAccounts()))
|
||||
refreshAccountList()
|
||||
}
|
||||
|
||||
function getMcAccounts() {
|
||||
return JSON.parse(localStorage.getItem("viaaas_mc_accounts")) || [];
|
||||
export function getActiveAccounts() {
|
||||
return activeAccounts;
|
||||
}
|
||||
|
||||
function findAccountByMcName(name) {
|
||||
return getMcAccounts().reverse().find(it => it.name.toLowerCase() == name.toLowerCase());
|
||||
|
||||
}
|
||||
function findAccountByMs(username) {
|
||||
return getMcAccounts().filter(isNotMojang).find(it => it.msUser == username);
|
||||
export function getMicrosoftUsers() {
|
||||
return (myMSALObj.getAllAccounts() || []).map(it => it.username);
|
||||
}
|
||||
|
||||
// Mojang account
|
||||
function loginMc(user, pass) {
|
||||
var clientToken = uuid.v4();
|
||||
export class McAccount {
|
||||
id;
|
||||
name;
|
||||
accessToken;
|
||||
loggedOut = false;
|
||||
|
||||
constructor(id, username, accessToken) {
|
||||
this.id = id;
|
||||
this.name = username;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
logout() {
|
||||
activeAccounts = filterNot(activeAccounts, this);
|
||||
saveRefreshAccounts();
|
||||
this.loggedOut = true;
|
||||
}
|
||||
|
||||
checkActive() {
|
||||
return fetch(getCorsProxy() + "https://authserver.mojang.com/validate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({accessToken: this.accessToken}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(data => isSuccess(data.status));
|
||||
}
|
||||
|
||||
joinGame(hash) {
|
||||
return this.acquireActiveToken()
|
||||
.then(() => fetch(getCorsProxy() + "https://sessionserver.mojang.com/session/minecraft/join", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: this.accessToken,
|
||||
selectedProfile: this.id,
|
||||
serverId: hash
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
})).then(checkFetchSuccess("Failed to join session"));
|
||||
}
|
||||
|
||||
refresh() {
|
||||
}
|
||||
|
||||
acquireActiveToken() {
|
||||
return this.checkActive().then(success => {
|
||||
if (!success) {
|
||||
return this.refresh();
|
||||
}
|
||||
return this;
|
||||
}).catch(e => addToast("Failed to refresh token!", e));
|
||||
}
|
||||
}
|
||||
|
||||
export class MojangAccount extends McAccount {
|
||||
clientToken;
|
||||
|
||||
constructor(id, username, accessToken, clientToken) {
|
||||
super(id, username, accessToken);
|
||||
this.clientToken = clientToken;
|
||||
}
|
||||
|
||||
logout() {
|
||||
super.logout();
|
||||
fetch(getCorsProxy() + "https://authserver.mojang.com/invalidate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: this.accessToken,
|
||||
clientToken: this.clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(checkFetchSuccess("not success logout"));
|
||||
}
|
||||
|
||||
checkActive() {
|
||||
return fetch(getCorsProxy() + "https://authserver.mojang.com/validate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: this.accessToken,
|
||||
clientToken: this.clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(data => isSuccess(data.status));
|
||||
}
|
||||
|
||||
refresh() {
|
||||
super.refresh();
|
||||
|
||||
console.log("refreshing " + this.id);
|
||||
return fetch(getCorsProxy() + "https://authserver.mojang.com/refresh", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: this.accessToken,
|
||||
clientToken: this.clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"},
|
||||
})
|
||||
.then(checkFetchSuccess("code"))
|
||||
.then(r => r.json())
|
||||
.then(json => {
|
||||
console.log("refreshed " + json.selectedProfile.id);
|
||||
this.accessToken = json.accessToken;
|
||||
this.clientToken = json.clientToken;
|
||||
this.name = json.selectedProfile.name;
|
||||
this.id = json.id;
|
||||
saveRefreshAccounts();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class MicrosoftAccount extends McAccount {
|
||||
msUser;
|
||||
|
||||
constructor(id, username, accessToken, msUser) {
|
||||
super(id, username, accessToken);
|
||||
this.msUser = msUser;
|
||||
}
|
||||
|
||||
logout() {
|
||||
super.logout();
|
||||
|
||||
let msAccount = myMSALObj.getAccountByUsername(this.msUser);
|
||||
if (!msAccount) return;
|
||||
|
||||
const logoutRequest = {account: msAccount};
|
||||
myMSALObj.logout(logoutRequest);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
super.refresh();
|
||||
return getTokenPopup(this.msUser, loginRequest)
|
||||
.then(response => {
|
||||
// this supports CORS
|
||||
return fetch("https://user.auth.xboxlive.com/user/authenticate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
Properties: {
|
||||
AuthMethod: "RPS", SiteName: "user.auth.xboxlive.com",
|
||||
RpsTicket: "d=" + response.accessToken
|
||||
}, RelyingParty: "http://auth.xboxlive.com", TokenType: "JWT"
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(checkFetchSuccess("xbox response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch("https://xsts.auth.xboxlive.com/xsts/authorize", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
Properties: {SandboxId: "RETAIL", UserTokens: [json.Token]},
|
||||
RelyingParty: "rp://api.minecraftservices.com/", TokenType: "JWT"
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(checkFetchSuccess("xsts response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch(getCorsProxy() + "https://api.minecraftservices.com/authentication/login_with_xbox", {
|
||||
method: "post",
|
||||
body: JSON.stringify({identityToken: "XBL3.0 x=" + json.DisplayClaims.xui[0].uhs + ";" + json.Token}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(checkFetchSuccess("mc response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch(getCorsProxy() + "https://api.minecraftservices.com/minecraft/profile", {
|
||||
method: "get",
|
||||
headers: {"content-type": "application/json", "authorization": "Bearer " + json.access_token}
|
||||
}).then(profile => {
|
||||
if (profile.status === 404) return {id: "MHF_Exclamation", name: "[DEMO]", access_token: ""};
|
||||
if (!isSuccess(profile.status)) throw "profile response not success";
|
||||
return profile.json();
|
||||
}).then(jsonProfile => {
|
||||
this.accessToken = json.access_token;
|
||||
this.name = jsonProfile.name;
|
||||
this.id = jsonProfile.id;
|
||||
saveRefreshAccounts();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function findAccountByMcName(name) {
|
||||
return activeAccounts.find(it => it.name.toLowerCase() === name.toLowerCase());
|
||||
}
|
||||
|
||||
export function findAccountByMs(username) {
|
||||
return getActiveAccounts().find(it => it.msUser === username);
|
||||
}
|
||||
|
||||
function addActiveAccount(acc) {
|
||||
activeAccounts.push(acc)
|
||||
saveRefreshAccounts()
|
||||
}
|
||||
|
||||
export function loginMc(user, pass) {
|
||||
const clientToken = uuid.v4();
|
||||
fetch(getCorsProxy() + "https://authserver.mojang.com/authenticate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
@ -40,123 +231,74 @@ function loginMc(user, pass) {
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
}).then(checkFetchSuccess("code"))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
storeMcAccount(data.accessToken, data.clientToken, data.selectedProfile.name, data.selectedProfile.id);
|
||||
}).catch(e => addToast("Failed to login", e));
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
let acc = new MojangAccount(data.selectedProfile.id, data.selectedProfile.name, data.accessToken, data.clientToken);
|
||||
addActiveAccount(acc);
|
||||
return acc;
|
||||
}).catch(e => addToast("Failed to login", e));
|
||||
$("#form_add_mc input").val("");
|
||||
}
|
||||
|
||||
function logoutMojang(id) {
|
||||
getMcAccounts().filter(isMojang).filter(it => it.id == id).forEach(it => {
|
||||
fetch(getCorsProxy() + "https://authserver.mojang.com/invalidate", {method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: it.accessToken,
|
||||
clientToken: it.clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
})
|
||||
.then(checkFetchSuccess("not success logout"))
|
||||
.finally(() => removeMcAccount(id));
|
||||
});
|
||||
// https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-javascript-auth-code
|
||||
const azureClientId = "a370fff9-7648-4dbf-b96e-2b4f8d539ac2";
|
||||
const whitelistedOrigin = [
|
||||
"https://via-login.geyserconnect.net",
|
||||
"https://via.re.yt.nom.br",
|
||||
"https://viaaas.noxt.cf"
|
||||
];
|
||||
const loginRequest = {scopes: ["XboxLive.signin"]};
|
||||
let redirectUrl = "https://viaversion.github.io/VIAaaS/src/main/resources/web/";
|
||||
if (location.hostname === "localhost" || whitelistedOrigin.includes(location.origin)) {
|
||||
redirectUrl = location.origin + location.pathname;
|
||||
}
|
||||
|
||||
function refreshMojangAccount(it) {
|
||||
console.log("refreshing " + it.id);
|
||||
return fetch(getCorsProxy() + "https://authserver.mojang.com/refresh", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: it.accessToken,
|
||||
clientToken: it.clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"},
|
||||
}).then(checkFetchSuccess("code"))
|
||||
.then(r => r.json())
|
||||
.then(json => {
|
||||
console.log("refreshed " + json.selectedProfile.id);
|
||||
removeMcAccount(json.selectedProfile.id);
|
||||
return storeMcAccount(json.accessToken, json.clientToken, json.selectedProfile.name, json.selectedProfile.id);
|
||||
});
|
||||
const msalConfig = {
|
||||
auth: {
|
||||
clientId: azureClientId,
|
||||
authority: "https://login.microsoftonline.com/consumers/",
|
||||
redirectUri: redirectUrl,
|
||||
},
|
||||
cache: {
|
||||
cacheLocation: "sessionStorage",
|
||||
storeAuthStateInCookie: false,
|
||||
}
|
||||
};
|
||||
|
||||
const myMSALObj = new msal.PublicClientApplication(msalConfig);
|
||||
|
||||
export function loginMs() {
|
||||
myMSALObj.loginRedirect(loginRequest);
|
||||
}
|
||||
|
||||
// Generic
|
||||
function getMcUserToken(account) {
|
||||
return validateToken(account.accessToken, account.clientToken || undefined).then(data => {
|
||||
if (!isSuccess(data.status)) {
|
||||
if (isMojang(account)) {
|
||||
return refreshMojangAccount(account);
|
||||
} else {
|
||||
return refreshTokenMs(account.msUser);
|
||||
}
|
||||
$(() => myMSALObj.handleRedirectPromise().then((resp) => {
|
||||
if (resp) {
|
||||
let found = findAccountByMs(resp.account.username)
|
||||
if (!found) {
|
||||
let accNew = new MicrosoftAccount("", "", "", resp.account.username);
|
||||
accNew.refresh()
|
||||
.then(() => addActiveAccount(accNew))
|
||||
.catch(e => addToast("Failed to get token", e));
|
||||
} else {
|
||||
found.refresh()
|
||||
.catch(e => addToast("Failed to refresh token", e));
|
||||
}
|
||||
return account;
|
||||
}).catch(e => addToast("Failed to refresh token!", e));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
function validateToken(accessToken, clientToken) {
|
||||
return fetch(getCorsProxy() + "https://authserver.mojang.com/validate", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: accessToken,
|
||||
clientToken: clientToken
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
function getTokenPopup(username, request) {
|
||||
/**
|
||||
* See here for more info on account retrieval:
|
||||
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
|
||||
*/
|
||||
request.account = myMSALObj.getAccountByUsername(username);
|
||||
return myMSALObj.acquireTokenSilent(request).catch(error => {
|
||||
console.warn("silent token acquisition fails.");
|
||||
if (error instanceof msal.InteractionRequiredAuthError) {
|
||||
// fallback to interaction when silent call fails
|
||||
return myMSALObj.acquireTokenPopup(request).catch(error => console.error(error));
|
||||
} else {
|
||||
console.warn(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function joinGame(token, id, hash) {
|
||||
return fetch(getCorsProxy() + "https://sessionserver.mojang.com/session/minecraft/join", {
|
||||
method: "post",
|
||||
body: JSON.stringify({
|
||||
accessToken: token,
|
||||
selectedProfile: id,
|
||||
serverId: hash
|
||||
}),
|
||||
headers: {"content-type": "application/json"}
|
||||
});
|
||||
}
|
||||
|
||||
// Microsoft auth
|
||||
function refreshTokenMs(username) {
|
||||
return getTokenPopup(username, loginRequest)
|
||||
.then(response => {
|
||||
// this supports CORS
|
||||
return fetch("https://user.auth.xboxlive.com/user/authenticate", {method: "post",
|
||||
body: JSON.stringify({Properties: {AuthMethod: "RPS", SiteName: "user.auth.xboxlive.com",
|
||||
RpsTicket: "d=" + response.accessToken}, RelyingParty: "http://auth.xboxlive.com", TokenType: "JWT"}),
|
||||
headers: {"content-type": "application/json"}})
|
||||
.then(checkFetchSuccess("xbox response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch("https://xsts.auth.xboxlive.com/xsts/authorize", {method: "post",
|
||||
body: JSON.stringify({Properties: {SandboxId: "RETAIL", UserTokens: [json.Token]},
|
||||
RelyingParty: "rp://api.minecraftservices.com/", TokenType: "JWT"}),
|
||||
headers: {"content-type": "application/json"}})
|
||||
.then(checkFetchSuccess("xsts response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch(getCorsProxy() + "https://api.minecraftservices.com/authentication/login_with_xbox", {method: "post",
|
||||
body: JSON.stringify({identityToken: "XBL3.0 x=" + json.DisplayClaims.xui[0].uhs + ";" + json.Token}),
|
||||
headers: {"content-type": "application/json"}})
|
||||
.then(checkFetchSuccess("mc response not success"))
|
||||
.then(r => r.json());
|
||||
}).then(json => {
|
||||
return fetch(getCorsProxy() + "https://api.minecraftservices.com/minecraft/profile", {
|
||||
method: "get", headers: {"content-type": "application/json", "authorization": "Bearer " + json.access_token}}).then(profile => {
|
||||
if (profile.status == 404) return {id: "MHF_Exclamation", name: "[DEMO]"};
|
||||
if (!isSuccess(profile.status)) throw "profile response not success";
|
||||
return profile.json();
|
||||
}).then(jsonProfile => {
|
||||
removeMcAccount(jsonProfile.id);
|
||||
return storeMcAccount(json.access_token, null, jsonProfile.name, jsonProfile.id, username);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function isMojang(it) {
|
||||
return !!it.clientToken;
|
||||
}
|
||||
|
||||
function isNotMojang(it) {
|
||||
return !isMojang(it);
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
// https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-javascript-auth-code
|
||||
|
||||
const azureClientId = "a370fff9-7648-4dbf-b96e-2b4f8d539ac2";
|
||||
const whitelistedOrigin = ["https://localhost:25543", "https://via-login.geyserconnect.net", "https://via.re.yt.nom.br", "https://viaaas.noxt.cf"];
|
||||
let redirectUrl = "https://viaversion.github.io/VIAaaS/src/main/resources/web/";
|
||||
if (whitelistedOrigin.includes(location.origin)) {
|
||||
redirectUrl = location.origin + location.pathname;
|
||||
}
|
||||
|
||||
const msalConfig = {
|
||||
auth: {
|
||||
clientId: azureClientId,
|
||||
authority: "https://login.microsoftonline.com/consumers/",
|
||||
redirectUri: redirectUrl,
|
||||
},
|
||||
cache: {
|
||||
cacheLocation: "sessionStorage",
|
||||
storeAuthStateInCookie: false,
|
||||
}
|
||||
};
|
||||
|
||||
const myMSALObj = new msal.PublicClientApplication(msalConfig);
|
||||
|
||||
const loginRequest = {
|
||||
scopes: ["XboxLive.signin"]
|
||||
};
|
||||
|
||||
function loginMs() {
|
||||
myMSALObj.loginRedirect(loginRequest);
|
||||
}
|
||||
|
||||
$(() => myMSALObj.handleRedirectPromise().then((resp) => {
|
||||
if (resp) {
|
||||
refreshTokenMs(resp.account.username).catch(e => addToast("Failed to get token", e));
|
||||
refreshAccountList();
|
||||
}
|
||||
}));
|
||||
|
||||
function getTokenPopup(username, request) {
|
||||
/**
|
||||
* See here for more info on account retrieval:
|
||||
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
|
||||
*/
|
||||
request.account = myMSALObj.getAccountByUsername(username);
|
||||
return myMSALObj.acquireTokenSilent(request).catch(error => {
|
||||
console.warn("silent token acquisition fails.");
|
||||
if (error instanceof msal.InteractionRequiredAuthError) {
|
||||
// fallback to interaction when silent call fails
|
||||
return myMSALObj.acquireTokenPopup(request).catch(error => console.error(error));
|
||||
} else {
|
||||
console.warn(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logoutMs(username) {
|
||||
let mcAcc = findAccountByMs(username) || {};
|
||||
removeMcAccount(mcAcc.id);
|
||||
|
||||
const logoutRequest = {
|
||||
account: myMSALObj.getAccountByUsername(username)
|
||||
};
|
||||
|
||||
myMSALObj.logout(logoutRequest);
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
import {refreshCorsStatus} from "./page.js";
|
||||
|
||||
function defaultCors() {
|
||||
return "https://crp123-cors.herokuapp.com/";
|
||||
}
|
||||
function getCorsProxy() {
|
||||
|
||||
export function getCorsProxy() {
|
||||
return localStorage.getItem("viaaas_cors_proxy") || defaultCors();
|
||||
}
|
||||
function setCorsProxy(url) {
|
||||
|
||||
export function setCorsProxy(url) {
|
||||
localStorage.setItem("viaaas_cors_proxy", url);
|
||||
refreshCorsStatus();
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
// Minecraft.id
|
||||
var mcIdUsername = null;
|
||||
var mcauth_code = null;
|
||||
var mcauth_success = null;
|
||||
|
||||
$(() => {
|
||||
let urlParams = new URLSearchParams();
|
||||
window.location.hash.substr(1).split("?").map(it => new URLSearchParams(it).forEach((a, b) => urlParams.append(b, a)));
|
||||
mcIdUsername = urlParams.get("username");
|
||||
mcauth_code = urlParams.get("mcauth_code");
|
||||
mcauth_success = urlParams.get("mcauth_success");
|
||||
if (mcauth_success == "false") {
|
||||
addToast("Couldn't authenticate with Minecraft.ID", urlParams.get("mcauth_msg"));
|
||||
}
|
||||
if (mcauth_code != null) {
|
||||
history.replaceState(null, null, "#");
|
||||
renderActions();
|
||||
}
|
||||
});
|
@ -1,7 +1,8 @@
|
||||
// Notification
|
||||
var notificationCallbacks = {};
|
||||
let notificationCallbacks = {};
|
||||
$(() => {
|
||||
new BroadcastChannel("viaaas-notification").addEventListener("message", handleSWMsg);
|
||||
new BroadcastChannel("viaaas-notification")
|
||||
.addEventListener("message", handleSWMsg);
|
||||
})
|
||||
|
||||
function handleSWMsg(event) {
|
||||
@ -13,8 +14,8 @@ function handleSWMsg(event) {
|
||||
callback(data.action);
|
||||
}
|
||||
|
||||
function authNotification(msg, yes, no) {
|
||||
if (!navigator.serviceWorker || Notification.permission != "granted") {
|
||||
export function authNotification(msg, yes, no) {
|
||||
if (!navigator.serviceWorker || Notification.permission !== "granted") {
|
||||
if (confirm(msg)) yes(); else no();
|
||||
return;
|
||||
}
|
||||
@ -23,21 +24,21 @@ function authNotification(msg, yes, no) {
|
||||
r.showNotification("Click to allow auth impersionation", {
|
||||
body: msg,
|
||||
tag: tag,
|
||||
vibrate: [200,10,100,200,100,10,100,10,200],
|
||||
vibrate: [200, 10, 100, 200, 100, 10, 100, 10, 200],
|
||||
actions: [
|
||||
{action: "reject", title: "Reject"},
|
||||
{action: "confirm", title: "Confirm"}
|
||||
]
|
||||
});
|
||||
notificationCallbacks[tag] = action => {
|
||||
if (action == "reject") {
|
||||
if (action === "reject") {
|
||||
no();
|
||||
} else if (!action || action == "confirm") {
|
||||
} else if (!action || action === "confirm") {
|
||||
yes();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
setTimeout(() => { delete notificationCallbacks[tag] }, 30 * 1000);
|
||||
setTimeout(() => {
|
||||
delete notificationCallbacks[tag]
|
||||
}, 30 * 1000);
|
||||
});
|
||||
}
|
||||
|
@ -1,35 +1,67 @@
|
||||
var connectionStatus = document.getElementById("connection_status");
|
||||
var corsStatus = document.getElementById("cors_status");
|
||||
var listening = document.getElementById("listening");
|
||||
var actions = document.getElementById("actions");
|
||||
var accounts = document.getElementById("accounts-list");
|
||||
var listenVisible = false;
|
||||
var workers = [];
|
||||
// Minecraft.id
|
||||
import {icanhazepoch, icanhazip} from "./util.js";
|
||||
import {getCorsProxy, setCorsProxy} from "./cors_proxy.js";
|
||||
import {
|
||||
findAccountByMs,
|
||||
getActiveAccounts,
|
||||
getMicrosoftUsers,
|
||||
loginMc,
|
||||
loginMs, MicrosoftAccount,
|
||||
MojangAccount
|
||||
} from "./account_manager.js";
|
||||
import {connect, getWsUrl, removeToken, sendSocket, setWsUrl, unlisten} from "./websocket.js";
|
||||
|
||||
let mcIdUsername = null;
|
||||
let mcauth_code = null;
|
||||
let mcauth_success = null;
|
||||
|
||||
$(() => {
|
||||
let urlParams = new URLSearchParams();
|
||||
window.location.hash.substr(1).split("?")
|
||||
.map(it => new URLSearchParams(it)
|
||||
.forEach((a, b) => urlParams.append(b, a)));
|
||||
mcIdUsername = urlParams.get("username");
|
||||
mcauth_code = urlParams.get("mcauth_code");
|
||||
mcauth_success = urlParams.get("mcauth_success");
|
||||
if (mcauth_success === "false") {
|
||||
addToast("Couldn't authenticate with Minecraft.ID", urlParams.get("mcauth_msg"));
|
||||
}
|
||||
if (mcauth_code != null) {
|
||||
history.replaceState(null, null, "#");
|
||||
renderActions();
|
||||
}
|
||||
});
|
||||
|
||||
let connectionStatus = document.getElementById("connection_status");
|
||||
let corsStatus = document.getElementById("cors_status");
|
||||
let listening = document.getElementById("listening");
|
||||
let actions = document.getElementById("actions");
|
||||
let accounts = document.getElementById("accounts-list");
|
||||
let cors_proxy_txt = document.getElementById("cors-proxy");
|
||||
let ws_url_txt = document.getElementById("ws-url");
|
||||
let listenVisible = false;
|
||||
let workers = [];
|
||||
$(() => workers = new Array(navigator.hardwareConcurrency).fill(null).map(() => new Worker("js/worker.js")));
|
||||
window.addEventListener('beforeinstallprompt', e => {
|
||||
e.preventDefault();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// On load
|
||||
$(() => {
|
||||
if (navigator.serviceWorker) {
|
||||
navigator.serviceWorker.register("sw.js");
|
||||
navigator.serviceWorker.ready.then(ready => ready.active.postMessage({
|
||||
action: "cache",
|
||||
urls: performance.getEntriesByType("resource")
|
||||
.map(it => it.name)
|
||||
.filter(it => it.endsWith(".js") || it.endsWith(".css") || it.endsWith(".png"))
|
||||
})); // https://stackoverflow.com/questions/46830493/is-there-any-way-to-cache-all-files-of-defined-folder-path-in-service-worker
|
||||
navigator.serviceWorker.register("sw.js").then(() => {
|
||||
swCacheFiles();
|
||||
});
|
||||
}
|
||||
|
||||
ohNo();
|
||||
$("#cors-proxy").val(getCorsProxy());
|
||||
$("#ws-url").val(getWsUrl());
|
||||
cors_proxy_txt.value = getCorsProxy();
|
||||
ws_url_txt.value = getWsUrl();
|
||||
$("form").on("submit", e => e.preventDefault());
|
||||
$("#form_add_mc").on("submit", e => loginMc($("#email").val(), $("#password").val()));
|
||||
$("#form_add_ms").on("submit", e => loginMs());
|
||||
$("#form_ws_url").on("submit", e => setWsUrl($("#ws-url").val()));
|
||||
$("#form_cors_proxy").on("submit", e => setCorsProxy($("#cors-proxy").val()));
|
||||
$("#form_add_mc").on("submit", () => loginMc($("#email").val(), $("#password").val()));
|
||||
$("#form_add_ms").on("submit", () => loginMs());
|
||||
$("#form_ws_url").on("submit", () => setWsUrl($("#ws-url").val()));
|
||||
$("#form_cors_proxy").on("submit", () => setCorsProxy($("#cors-proxy").val()));
|
||||
$(".css_async").attr("disabled", null);
|
||||
|
||||
workers.forEach(it => it.onmessage = onWorkerMsg);
|
||||
@ -41,14 +73,31 @@ $(() => {
|
||||
connect();
|
||||
});
|
||||
|
||||
function refreshCorsStatus() {
|
||||
corsStatus.innerText = "...";
|
||||
icanhazip(true).then(ip => {
|
||||
return icanhazip(false).then(ip2 => corsStatus.innerText = "OK " + ip + (ip != ip2 ? " (different IP)" : ""));
|
||||
}).catch(e => corsStatus.innerText = "error: " + e);
|
||||
function swCacheFiles() {
|
||||
navigator.serviceWorker.ready.then(ready => ready.active.postMessage({
|
||||
action: "cache",
|
||||
urls: performance.getEntriesByType("resource")
|
||||
.map(it => it.name)
|
||||
.filter(it => it.endsWith(".js") || it.endsWith(".css") || it.endsWith(".png"))
|
||||
})); // https://stackoverflow.com/questions/46830493/is-there-any-way-to-cache-all-files-of-defined-folder-path-in-service-worker
|
||||
}
|
||||
|
||||
function addMcAccountToList(id, name, msUser = null) {
|
||||
export function setWsStatus(txt) {
|
||||
connectionStatus.innerText = txt;
|
||||
}
|
||||
|
||||
export function setListenVisible(visible) {
|
||||
listenVisible = visible;
|
||||
}
|
||||
|
||||
export function refreshCorsStatus() {
|
||||
corsStatus.innerText = "...";
|
||||
icanhazip(true).then(ip => {
|
||||
return icanhazip(false).then(ip2 => corsStatus.innerText = "OK " + ip + (ip !== ip2 ? " (different IP)" : ""));
|
||||
}).catch(e => corsStatus.innerText = "error: " + e);
|
||||
}
|
||||
|
||||
function addMcAccountToList(account) {
|
||||
let p = document.createElement("li");
|
||||
p.className = "input-group d-flex";
|
||||
let shead = document.createElement("span");
|
||||
@ -59,19 +108,15 @@ function addMcAccountToList(id, name, msUser = null) {
|
||||
n.className = "form-control";
|
||||
let remove = document.createElement("a");
|
||||
remove.className = "btn btn-danger";
|
||||
n.innerText = " " + name + " " + (msUser == null ? "" : "(" + msUser + ") ");
|
||||
n.innerText = " " + account.name + " " + (account instanceof MicrosoftAccount ? "(" + account.msUser + ") " : "");
|
||||
remove.innerText = "Logout";
|
||||
remove.href = "javascript:";
|
||||
remove.onclick = () => {
|
||||
if (msUser == null) {
|
||||
logoutMojang(id);
|
||||
} else {
|
||||
logoutMs(msUser);
|
||||
}
|
||||
account.logout();
|
||||
};
|
||||
head.width = "24";
|
||||
head.alt = name + "'s head";
|
||||
head.src = "https://crafthead.net/helm/" + id;
|
||||
head.width = 24;
|
||||
head.alt = account.name + "'s head";
|
||||
head.src = "https://crafthead.net/helm/" + account.id;
|
||||
//(id.length == 36 || id.length == 32) ? "https://crafatar.com/avatars/" + id + "?overlay" : "https://crafthead.net/helm/" + id;
|
||||
p.append(shead);
|
||||
p.append(n);
|
||||
@ -79,28 +124,35 @@ function addMcAccountToList(id, name, msUser = null) {
|
||||
accounts.appendChild(p);
|
||||
}
|
||||
|
||||
function refreshAccountList() {
|
||||
export function refreshAccountList() {
|
||||
accounts.innerHTML = "";
|
||||
getMcAccounts().filter(isMojang).sort((a, b) => a.name.localeCompare(b.name)).forEach(it => addMcAccountToList(it.id, it.name));
|
||||
(myMSALObj.getAllAccounts() || []).sort((a, b) => a.username.localeCompare(b.username)).forEach(msAccount => {
|
||||
let mcAcc = findAccountByMs(msAccount.username) || {id: "MHF_Question", name: "..."};
|
||||
addMcAccountToList(mcAcc.id, mcAcc.name, msAccount.username);
|
||||
});
|
||||
getActiveAccounts()
|
||||
.filter(it => it instanceof MojangAccount)
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.forEach(it => addMcAccountToList(it));
|
||||
getMicrosoftUsers()
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.forEach(username => {
|
||||
let mcAcc = findAccountByMs(username);
|
||||
if (!mcAcc) return;
|
||||
addMcAccountToList(mcAcc);
|
||||
});
|
||||
}
|
||||
|
||||
function renderActions() {
|
||||
export function renderActions() {
|
||||
actions.innerHTML = "";
|
||||
if (Notification.permission == "default") {
|
||||
if (Notification.permission === "default") {
|
||||
actions.innerHTML += '<p><a href="javascript:" id="notificate">Enable notifications</a></p>';
|
||||
$("#notificate").on("click", e => Notification.requestPermission().then(renderActions)); // i'm lazy
|
||||
$("#notificate").on("click", () => Notification.requestPermission().then(renderActions)); // i'm lazy
|
||||
}
|
||||
if (listenVisible) {
|
||||
if (mcIdUsername != null && mcauth_code != null) {
|
||||
addAction("Listen to " + mcIdUsername, () => {
|
||||
socket.send(JSON.stringify({
|
||||
sendSocket(JSON.stringify({
|
||||
"action": "minecraft_id_login",
|
||||
"username": mcIdUsername,
|
||||
"code": mcauth_code}));
|
||||
"code": mcauth_code
|
||||
}));
|
||||
mcauth_code = null;
|
||||
renderActions();
|
||||
});
|
||||
@ -111,7 +163,7 @@ function renderActions() {
|
||||
let callbackUrl = new URL(location);
|
||||
callbackUrl.search = "";
|
||||
callbackUrl.hash = "#username=" + encodeURIComponent(user);
|
||||
location = "https://api.minecraft.id/gateway/start/" + encodeURIComponent(user)
|
||||
location.href = "https://api.minecraft.id/gateway/start/" + encodeURIComponent(user)
|
||||
+ "?callback=" + encodeURIComponent(callbackUrl);
|
||||
});
|
||||
addAction("Listen to frontend offline login in VIAaaS instance", () => {
|
||||
@ -126,13 +178,13 @@ function renderActions() {
|
||||
|
||||
function onWorkerMsg(e) {
|
||||
console.log(e);
|
||||
if (e.data.action == "completed_pow") onCompletedPoW(e);
|
||||
if (e.data.action === "completed_pow") onCompletedPoW(e);
|
||||
}
|
||||
|
||||
function onCompletedPoW(e) {
|
||||
addToast("Offline username", "Completed proof of work");
|
||||
workers.forEach(it => it.postMessage({action: "cancel", id: e.data.id}));
|
||||
socket.send(e.data.msg);
|
||||
sendSocket(e.data.msg);
|
||||
}
|
||||
|
||||
function addAction(text, onClick) {
|
||||
@ -145,7 +197,7 @@ function addAction(text, onClick) {
|
||||
actions.appendChild(p);
|
||||
}
|
||||
|
||||
function addListeningList(user, token) {
|
||||
export function addListeningList(user, token) {
|
||||
let p = document.createElement("p");
|
||||
let head = document.createElement("img");
|
||||
let n = document.createElement("span");
|
||||
@ -158,7 +210,7 @@ function addListeningList(user, token) {
|
||||
listening.removeChild(p);
|
||||
unlisten(user);
|
||||
};
|
||||
head.width = "24";
|
||||
head.width = 24;
|
||||
head.alt = user + "'s head";
|
||||
head.src = "https://crafthead.net/helm/" + user;
|
||||
p.append(head);
|
||||
@ -167,7 +219,7 @@ function addListeningList(user, token) {
|
||||
listening.appendChild(p);
|
||||
}
|
||||
|
||||
function addToast(title, msg) {
|
||||
export function addToast(title, msg) {
|
||||
let toast = document.createElement("div");
|
||||
document.getElementById("toasts").prepend(toast);
|
||||
$(toast)
|
||||
@ -188,7 +240,7 @@ function addToast(title, msg) {
|
||||
new bootstrap.Toast(toast).show();
|
||||
}
|
||||
|
||||
function resetHtml() {
|
||||
export function resetHtml() {
|
||||
listening.innerHTML = "";
|
||||
listenVisible = false;
|
||||
renderActions();
|
||||
@ -196,13 +248,16 @@ function resetHtml() {
|
||||
|
||||
function ohNo() {
|
||||
try {
|
||||
icanhazepoch().then(sec => {
|
||||
if (Math.abs(Date.now() / 1000 - sec) > 15) {
|
||||
addToast("Time isn't synchronized", "Please synchronize your computer time to NTP servers");
|
||||
} else {
|
||||
console.log("time seems synchronized");
|
||||
}
|
||||
})
|
||||
new Date().getDay() == 3 && console.log("it's snapshot day 🐸 my dudes"); new Date().getDate() == 1 && new Date().getMonth() == 3 && addToast("WARNING", "Your ViaVersion has expired, please renew it at https://viaversion.com/ for $99");
|
||||
} catch (e) { console.log(e); }
|
||||
icanhazepoch().then(sec => {
|
||||
if (Math.abs(Date.now() / 1000 - sec) > 15) {
|
||||
addToast("Time isn't synchronized", "Please synchronize your computer time to NTP servers");
|
||||
} else {
|
||||
console.log("time seems synchronized");
|
||||
}
|
||||
})
|
||||
new Date().getDay() === 3 && console.log("it's snapshot day 🐸 my dudes");
|
||||
new Date().getDate() === 1 && new Date().getMonth() === 3 && addToast("WARNING", "Your ViaVersion has expired, please renew it at https://viaversion.com/ for $99");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,30 @@
|
||||
function isSuccess(status) {
|
||||
import {getCorsProxy} from "./cors_proxy.js";
|
||||
|
||||
export function isSuccess(status) {
|
||||
return status >= 200 && status < 300;
|
||||
}
|
||||
|
||||
function checkFetchSuccess(msg) {
|
||||
export function checkFetchSuccess(msg) {
|
||||
return r => {
|
||||
if (!isSuccess(r.status)) throw r.status + " " + msg;
|
||||
return r;
|
||||
};
|
||||
}
|
||||
|
||||
function icanhazip(cors) {
|
||||
export function icanhazip(cors) {
|
||||
return fetch((cors ? getCorsProxy() : "") + "https://ipv4.icanhazip.com")
|
||||
.then(checkFetchSuccess("code"))
|
||||
.then(r => r.text())
|
||||
.then(it => it.trim());
|
||||
}
|
||||
|
||||
function icanhazepoch() {
|
||||
export function icanhazepoch() {
|
||||
return fetch("https://icanhazepoch.com")
|
||||
.then(checkFetchSuccess("code"))
|
||||
.then(r => r.text())
|
||||
.then(it => parseInt(it.trim()))
|
||||
}
|
||||
|
||||
export function filterNot(array, item) {
|
||||
return array.filter(it => it !== item);
|
||||
}
|
@ -1,23 +1,30 @@
|
||||
var wsUrl = getWsUrl();
|
||||
var socket = null;
|
||||
import {authNotification} from "./notification.js";
|
||||
import {checkFetchSuccess} from "./util.js";
|
||||
import {findAccountByMcName} from "./account_manager.js";
|
||||
import {addListeningList, addToast, renderActions, resetHtml, setListenVisible, setWsStatus} from "./page.js";
|
||||
|
||||
let wsUrl = getWsUrl();
|
||||
let socket = null;
|
||||
|
||||
// WS url
|
||||
function defaultWs() {
|
||||
let url = new URL("ws", new URL(location));
|
||||
url.protocol = "wss";
|
||||
return window.location.host == "viaversion.github.io" || !window.location.host ? "wss://localhost:25543/ws" : url.toString();
|
||||
return window.location.host.endsWith("github.io") || !window.location.protocol.startsWith("http")
|
||||
? "wss://localhost:25543/ws" : url.toString();
|
||||
}
|
||||
|
||||
function getWsUrl() {
|
||||
export function getWsUrl() {
|
||||
return localStorage.getItem("viaaas_ws_url") || defaultWs();
|
||||
}
|
||||
function setWsUrl(url) {
|
||||
|
||||
export function setWsUrl(url) {
|
||||
localStorage.setItem("viaaas_ws_url", url);
|
||||
location.reload();
|
||||
}
|
||||
|
||||
// Tokens
|
||||
function saveToken(token) {
|
||||
export function saveToken(token) {
|
||||
let hTokens = JSON.parse(localStorage.getItem("viaaas_tokens")) || {};
|
||||
let tokens = getTokens();
|
||||
tokens.push(token);
|
||||
@ -25,28 +32,28 @@ function saveToken(token) {
|
||||
localStorage.setItem("viaaas_tokens", JSON.stringify(hTokens));
|
||||
}
|
||||
|
||||
function removeToken(token) {
|
||||
export function removeToken(token) {
|
||||
let hTokens = JSON.parse(localStorage.getItem("viaaas_tokens")) || {};
|
||||
let tokens = getTokens();
|
||||
tokens = tokens.filter(it => it != token);
|
||||
tokens = tokens.filter(it => it !== token);
|
||||
hTokens[wsUrl] = tokens;
|
||||
localStorage.setItem("viaaas_tokens", JSON.stringify(hTokens));
|
||||
}
|
||||
|
||||
function getTokens() {
|
||||
export function getTokens() {
|
||||
return (JSON.parse(localStorage.getItem("viaaas_tokens")) || {})[wsUrl] || [];
|
||||
}
|
||||
|
||||
// Websocket
|
||||
function listen(token) {
|
||||
export function listen(token) {
|
||||
socket.send(JSON.stringify({"action": "listen_login_requests", "token": token}));
|
||||
}
|
||||
|
||||
function unlisten(id) {
|
||||
export function unlisten(id) {
|
||||
socket.send(JSON.stringify({"action": "unlisten_login_requests", "uuid": id}));
|
||||
}
|
||||
|
||||
function confirmJoin(hash) {
|
||||
export function confirmJoin(hash) {
|
||||
socket.send(JSON.stringify({action: "session_hash_response", session_hash: hash}));
|
||||
}
|
||||
|
||||
@ -56,12 +63,10 @@ function handleJoinRequest(parsed) {
|
||||
+ parsed.message.split(/[\r\n]+/).map(it => "> " + it).join('\n'), () => {
|
||||
let account = findAccountByMcName(parsed.user);
|
||||
if (account) {
|
||||
getMcUserToken(account).then(data => {
|
||||
return joinGame(data.accessToken, data.id, parsed.session_hash);
|
||||
})
|
||||
.then(checkFetchSuccess("code"))
|
||||
.finally(() => confirmJoin(parsed.session_hash))
|
||||
.catch((e) => addToast("Couldn't contact session server", "Error: " + e));
|
||||
account.joinGame(parsed.session_hash)
|
||||
.then(checkFetchSuccess("code"))
|
||||
.finally(() => confirmJoin(parsed.session_hash))
|
||||
.catch((e) => addToast("Couldn't contact session server", "Error: " + e));
|
||||
} else {
|
||||
confirmJoin(parsed.session_hash);
|
||||
addToast("Couldn't find account", "Couldn't find " + parsed.user + ", check Accounts tab");
|
||||
@ -71,51 +76,51 @@ function handleJoinRequest(parsed) {
|
||||
|
||||
function onSocketMsg(event) {
|
||||
let parsed = JSON.parse(event.data);
|
||||
if (parsed.action == "ad_minecraft_id_login") {
|
||||
listenVisible = true;
|
||||
if (parsed.action === "ad_minecraft_id_login") {
|
||||
setListenVisible(true);
|
||||
renderActions();
|
||||
} else if (parsed.action == "login_result") {
|
||||
} else if (parsed.action === "login_result") {
|
||||
if (!parsed.success) {
|
||||
addToast("Couldn't verify Minecraft account", "VIAaaS returned failed response");
|
||||
} else {
|
||||
listen(parsed.token);
|
||||
saveToken(parsed.token);
|
||||
}
|
||||
} else if (parsed.action == "listen_login_requests_result") {
|
||||
} else if (parsed.action === "listen_login_requests_result") {
|
||||
if (parsed.success) {
|
||||
addListeningList(parsed.user, parsed.token);
|
||||
} else {
|
||||
removeToken(parsed.token);
|
||||
}
|
||||
} else if (parsed.action == "session_hash_request") {
|
||||
} else if (parsed.action === "session_hash_request") {
|
||||
handleJoinRequest(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
function listenStoredTokens() {
|
||||
export function listenStoredTokens() {
|
||||
getTokens().forEach(listen);
|
||||
}
|
||||
|
||||
function onConnect() {
|
||||
connectionStatus.innerText = "connected";
|
||||
setWsStatus("connected");
|
||||
resetHtml();
|
||||
listenStoredTokens();
|
||||
}
|
||||
|
||||
function onWsError(e) {
|
||||
console.log(e);
|
||||
connectionStatus.innerText = "socket error";
|
||||
setWsStatus("socket error");
|
||||
resetHtml();
|
||||
}
|
||||
|
||||
function onDisconnect(evt) {
|
||||
connectionStatus.innerText = "disconnected with close code " + evt.code + " and reason: " + evt.reason;
|
||||
setWsStatus("disconnected with close code " + evt.code + " and reason: " + evt.reason);
|
||||
resetHtml();
|
||||
setTimeout(connect, 5000);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
connectionStatus.innerText = "connecting...";
|
||||
export function connect() {
|
||||
setWsStatus("connecting...");
|
||||
socket = new WebSocket(wsUrl);
|
||||
|
||||
socket.onerror = onWsError;
|
||||
@ -123,3 +128,11 @@ function connect() {
|
||||
socket.onclose = onDisconnect
|
||||
socket.onmessage = onSocketMsg;
|
||||
}
|
||||
|
||||
export function sendSocket(msg) {
|
||||
if (!socket) {
|
||||
console.error("couldn't send msg, socket isn't set");
|
||||
return
|
||||
}
|
||||
socket.send(msg);
|
||||
}
|
@ -1,43 +1,43 @@
|
||||
importScripts("https://cdnjs.cloudflare.com/ajax/libs/js-sha512/0.8.0/sha512.min.js");
|
||||
|
||||
var pending = [];
|
||||
let pending = [];
|
||||
|
||||
onmessage = function(e) {
|
||||
if (e.data.action == "listen_pow") startPoW(e);
|
||||
if (e.data.action == "cancel") removePending(e.data.id);
|
||||
onmessage = function (e) {
|
||||
if (e.data.action === "listen_pow") startPoW(e);
|
||||
if (e.data.action === "cancel") removePending(e.data.id);
|
||||
}
|
||||
|
||||
function removePending(id) {
|
||||
console.log("removing task" + id);
|
||||
pending = pending.filter(it => it != id);
|
||||
console.log("removing task" + id);
|
||||
pending = pending.filter(it => it !== id);
|
||||
}
|
||||
|
||||
function startPoW(e) {
|
||||
pending.push(e.data.id);
|
||||
listenPoW(e);
|
||||
pending.push(e.data.id);
|
||||
listenPoW(e);
|
||||
}
|
||||
|
||||
function listenPoW(e) {
|
||||
var user = e.data.user;
|
||||
let msg = null;
|
||||
var endTime = Date.now() + 1000;
|
||||
do {
|
||||
if (!pending.includes(e.data.id)) return; // cancelled
|
||||
let user = e.data.user;
|
||||
let msg = null;
|
||||
let endTime = Date.now() + 1000;
|
||||
do {
|
||||
if (!pending.includes(e.data.id)) return; // cancelled
|
||||
|
||||
msg = JSON.stringify({
|
||||
action: "offline_login",
|
||||
username: user,
|
||||
date: Date.now(),
|
||||
rand: Math.random()
|
||||
});
|
||||
msg = JSON.stringify({
|
||||
action: "offline_login",
|
||||
username: user,
|
||||
date: Date.now(),
|
||||
rand: Math.random()
|
||||
});
|
||||
|
||||
if (Date.now() >= endTime) {
|
||||
setTimeout(() => listenPoW(e), 0);
|
||||
return;
|
||||
}
|
||||
} while (!sha512(msg).startsWith("00000"));
|
||||
if (Date.now() >= endTime) {
|
||||
setTimeout(() => listenPoW(e), 0);
|
||||
return;
|
||||
}
|
||||
} while (!sha512(msg).startsWith("00000"));
|
||||
|
||||
postMessage({id: e.data.id, action: "completed_pow", msg: msg});
|
||||
postMessage({id: e.data.id, action: "completed_pow", msg: msg});
|
||||
}
|
||||
|
||||
/* function sha512(s) {
|
||||
|
Loading…
Reference in New Issue
Block a user