diff --git a/.github/release.md b/.github/release.md deleted file mode 100644 index 639ec3e..0000000 --- a/.github/release.md +++ /dev/null @@ -1,2 +0,0 @@ -# Thanks for checking out ArmCord dev build! -Make sure to join our [Discord server](https://discord.gg/uaW5vMY3V6) to share opinions, or to chat with ArmCord developers! \ No newline at end of file diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml deleted file mode 100644 index 0c6640e..0000000 --- a/.github/workflows/dev.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Dev build -on: [push] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '18' - - run: npm install - - run: npm run CIbuild - - id: vars - shell: bash - run: | - echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ steps.vars.outputs.sha_short }} - release_name: Release ${{ steps.vars.outputs.sha_short }} - draft: true - prerelease: true - body_path: ./.github/release.md - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: /home/runner/work/ArmCord/ArmCord/dist/ArmCord-3.1.0.zip - asset_name: ArmCordLinux.zip - asset_content_type: application/octet-stream - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: /home/runner/work/ArmCord/ArmCord/dist/ArmCord-3.1.0-win.zip - asset_name: ArmCordWindows.zip - asset_content_type: application/octet-stream - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: /home/runner/work/ArmCord/ArmCord/dist/ArmCord-3.1.0-mac.zip - asset_name: ArmCordWindows.zip - asset_content_type: application/octet-stream - - run: | - curl --request PATCH \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - -H "Content-Type: application/json" \ - https://api.github.com/repos/${{ github.repository }}/releases/${{steps.create_release.outputs.id}} \ - -d '{"draft":false}' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a9967c5..0f7ad6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,12 @@ "license": "OSL-3.0", "dependencies": { "electron-context-menu": "^3.1.2", - "v8-compile-cache": "^2.3.0", - "ws": "^8.5.0" + "electron-tabs": "^0.17.0", + "v8-compile-cache": "^2.3.0" }, "devDependencies": { "@types/electron-json-storage": "^4.5.0", "@types/node": "^17.0.24", - "@types/ws": "^8.5.3", "copyfiles": "^2.4.1", "electron": "^18.0.4", "electron-builder": "^23.0.3", @@ -294,15 +293,6 @@ "dev": true, "optional": true }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/yargs": { "version": "17.0.10", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", @@ -1564,6 +1554,11 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-tabs": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/electron-tabs/-/electron-tabs-0.17.0.tgz", + "integrity": "sha512-jFv6WOeumSR5q2Cf6WOghE7CTdxPB0mSuPw8dGwz1OAG8MJMQn/kd/ghmvRPwoOYK77v4d9YligqjXIQc2oPcg==" + }, "node_modules/electron/node_modules/@types/node": { "version": "16.11.26", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", @@ -3442,26 +3437,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", @@ -3760,15 +3735,6 @@ "dev": true, "optional": true }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/yargs": { "version": "17.0.10", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", @@ -4761,6 +4727,11 @@ } } }, + "electron-tabs": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/electron-tabs/-/electron-tabs-0.17.0.tgz", + "integrity": "sha512-jFv6WOeumSR5q2Cf6WOghE7CTdxPB0mSuPw8dGwz1OAG8MJMQn/kd/ghmvRPwoOYK77v4d9YligqjXIQc2oPcg==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -6214,12 +6185,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} - }, "xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", diff --git a/package.json b/package.json index f3f91ce..ddcd94d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "start": "npm run build && electron ./ts-out/main.js", "package": "npm run build && electron-builder", "format": "prettier --write src/**/*", - "CIbuild": "npm run build && electron-builder --linux zip && electron-builder --windows zip && electron-builder --macos zip", "postinstall": "husky install" }, "repository": { @@ -25,7 +24,6 @@ "devDependencies": { "@types/electron-json-storage": "^4.5.0", "@types/node": "^17.0.24", - "@types/ws": "^8.5.3", "copyfiles": "^2.4.1", "electron": "^18.0.4", "electron-builder": "^23.0.3", @@ -35,8 +33,8 @@ }, "dependencies": { "electron-context-menu": "^3.1.2", - "v8-compile-cache": "^2.3.0", - "ws": "^8.5.0" + "electron-tabs": "^0.17.0", + "v8-compile-cache": "^2.3.0" }, "build": { "appId": "com.smartfridge.armcord", diff --git a/src/content/setup.html b/src/content/setup.html index 22f3f98..cdca768 100644 --- a/src/content/setup.html +++ b/src/content/setup.html @@ -46,9 +46,7 @@ minimizeToTray: true, automaticPatches: false, mods: "cumcord", - blurType: "acrylic", - inviteWebsocket: true, - doneSetup: true + blurType: "acrylic" }); fade(document.getElementById("setup")); setTimeout(function () { @@ -100,9 +98,7 @@ minimizeToTray: true, automaticPatches: false, mods: mod, - blurType: "acrylic", - inviteWebsocket: true, - doneSetup: true + blurType: "acrylic" }); fade(document.getElementById("setup")); setTimeout(function () { @@ -117,9 +113,7 @@ minimizeToTray: true, automaticPatches: false, mods: "none", - blurType: "acrylic", - inviteWebsocket: true, - doneSetup: true + blurType: "acrylic" }); fade(document.getElementById("setup")); setTimeout(function () { diff --git a/src/settings/settings.html b/src/settings/settings.html index b74d94f..2b8151f 100644 --- a/src/settings/settings.html +++ b/src/settings/settings.html @@ -74,9 +74,7 @@ minimizeToTray: document.getElementById("tray").checked, automaticPatches: document.getElementById("patches").checked, mods: document.getElementById("mod").value, - blurType: "acrylic", - inviteWebsocket: true, - doneSetup: true + blurType: "acrylic" }); }); diff --git a/src/socket.ts b/src/socket.ts deleted file mode 100644 index 0c2e0a9..0000000 --- a/src/socket.ts +++ /dev/null @@ -1,182 +0,0 @@ -// MIT License - -// Copyright (c) 2020-2022 Dawid Papiewski "SpacingBat3" - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -import type {Server, WebSocket} from "ws"; -import {inviteWindow, createInviteWindow} from "./window"; - -async function wsLog(message: string, ...args: unknown[]) { - console.log("[WebSocket]" + message, ...args); -} - -/** Generates an inclusive range (as `Array`) from `start` to `end`. */ -function range(start: number, end: number) { - return Array.from({length: end - start + 1}, (_v, k) => start + k); -} - -interface InviteResponse { - /** Response type/command. */ - cmd: "INVITE_BROWSER"; - /** Response arguments. */ - args: { - /** An invitation code. */ - code: string; - }; - /** Nonce indentifying the communication. */ - nonce: string; -} - -function isInviteResponse(data: unknown): data is InviteResponse { - if (!(data instanceof Object)) return false; - if ((data as Partial)?.cmd !== "INVITE_BROWSER") return false; - if (typeof (data as Partial)?.args?.code !== "string") return false; - if (typeof (data as Partial)?.nonce !== "string") return false; - return true; -} - -const messages = { - /** - * A fake, hard-coded Discord command to spoof the presence of - * official Discord client (which makes browser to actually start a - * communication with the ArmCord). - */ - handShake: { - /** Message command. */ - cmd: "DISPATCH", - /** Message data. */ - data: { - /** Message scheme version. */ - v: 1, - /** Client properties. */ - config: { - /** Discord CDN host (hard-coded for `dicscord.com` instance). */ - cdn_host: "cdn.discordapp.com", - /** API endpoint (hard-coded for `dicscord.com` instance). */ - api_endpoint: "//discord.com/api", - /** Client type. Can be (probably) `production` or `canary`. */ - environment: "production" - } - }, - evt: "READY", - nonce: null - } -}; - -/** - * Tries to reserve the server at given port. - * - * @returns `Promise`, which always resolves (either to `Server` on - * success or `null` on failure). - */ -async function getServer(port: number) { - const {WebSocketServer} = await import("ws"); - return new Promise | null>((resolve) => { - const wss = new WebSocketServer({host: "127.0.0.1", port}); - wss.once("listening", () => resolve(wss)); - wss.once("error", () => resolve(null)); - }); -} - -/** - * Tries to start a WebSocket server at given port range. If it suceed, it will - * listen to the browser requests which are meant to be sent to official - * Discord client. - * - * Currently it supports only the invitation link requests. - * - */ -export default async function startServer() { - function isJsonSyntaxCorrect(string: string) { - try { - JSON.parse(string); - } catch { - return false; - } - return true; - } - /** Known Discord instances, including the official ones. */ - const knownInstancesList = [ - ["Discord", new URL("https://discord.com/app")], - ["Discord Canary", new URL("https://canary.discord.com/app")], - ["Discord PTB", new URL("https://ptb.discord.com/app")], - ["Fosscord", new URL("https://dev.fosscord.com/app")] - ] as const; - - let wss = null, wsPort = 6463; - for(const port of range(6463, 6472)) { - wss = await getServer(port); - if(wss !== null) { - void wsLog("ArmCord is listening at " + (port.toString())); - wsPort = port; - break; - } - } - if(wss === null) return; - let lock = false; - wss.on('connection', (wss, request) => { - const origin = request.headers.origin??'https://discord.com'; - let known = false; - for(const instance of knownInstancesList) { - if(instance[1].origin === origin) - known = true; - } - if(!known) return; - wss.send(JSON.stringify(messages.handShake)); - wss.once('message', (data, isBinary) => { - if(lock) return; - lock = true; - let parsedData:unknown = data; - if(!isBinary) - parsedData = data.toString(); - if(isJsonSyntaxCorrect(parsedData as string)) - parsedData = JSON.parse(parsedData as string); - if(isInviteResponse(parsedData)) { - // Replies to browser, so it finds the communication successful. - wss.send(JSON.stringify({ - cmd: parsedData.cmd, - data: { - invite: null, - code: parsedData.args.code - }, - evt: null, - nonce: parsedData.nonce - })); - createInviteWindow() - const child = inviteWindow; - if(child === undefined) return; - void child.loadURL(origin+'/invite/'+parsedData.args.code); - child.webContents.once("did-finish-load", () => { - child.show(); - }); - child.webContents.once("will-navigate", () => { - lock = false; - child.close(); - }) - child.on("close", (e) => { - lock = false; - }) - // Blocks requests to ArmCord's WS, to prevent loops. - child.webContents.session.webRequest.onBeforeRequest({ - urls: ['ws://127.0.0.1:'+wsPort.toString()+'/*'] - }, (_details,callback) => callback({cancel: true})); - } - }) - }) -} diff --git a/src/utils.ts b/src/utils.ts index 6b12f38..7e48a87 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -41,7 +41,6 @@ export function setup() { automaticPatches: false, mods: "cumcord", blurType: "acrylic", - inviteWebsocket: true, doneSetup: false }; setConfigBulk({ @@ -73,7 +72,6 @@ export interface Settings { automaticPatches: boolean; mods: string; blurType: string; - inviteWebsocket: boolean; doneSetup: boolean; } export async function getConfig(object: string) { diff --git a/src/window.ts b/src/window.ts index c5e4b9c..bc00139 100644 --- a/src/window.ts +++ b/src/window.ts @@ -6,10 +6,9 @@ import {BrowserWindow, shell, app, ipcMain, dialog} from "electron"; import path from "path"; import {checkIfConfigIsBroken, firstRun, getConfig, contentPath} from "./utils"; import {registerIpc} from "./ipc"; -import startServer from "./socket" import contextMenu from "electron-context-menu"; export let mainWindow: BrowserWindow; -export let inviteWindow: BrowserWindow; + let guestWindows: BrowserWindow[] = []; contextMenu({ showSaveImageAs: true, @@ -17,7 +16,7 @@ contextMenu({ showSearchWithGoogle: true }); -async function doAfterDefiningTheWindow() { +function doAfterDefiningTheWindow() { checkIfConfigIsBroken(); registerIpc(); mainWindow.webContents.userAgent = @@ -40,9 +39,6 @@ async function doAfterDefiningTheWindow() { } }); console.log(contentPath); - if (await getConfig("inviteWebsocket") == true) { - startServer() - } try { mainWindow.loadFile(contentPath); } catch (e) { @@ -169,18 +165,3 @@ export function createTabsGuest(number: number) { guestWindows[number].loadURL("https://discord.com/app"); } } -export function createInviteWindow() { - inviteWindow = new BrowserWindow({ - width: 800, - height: 600, - title: "ArmCord Invite Manager", - darkTheme: true, - icon: path.join(__dirname, "/assets/icon_transparent.png"), - frame: true, - autoHideMenuBar: true, - webPreferences: { - spellcheck: true - } - }); - inviteWindow.hide() -} \ No newline at end of file