├── Extension ├── Pages │ └── .gitkeep ├── icons │ ├── 128x128.png │ ├── 16x16.png │ ├── 48x48.png │ └── 540x540.png ├── vendor │ ├── get_app-black-18dp.svg │ └── delete-black-18dp.svg ├── logReader.js ├── manifest.json ├── Iframe.js ├── popup.html ├── Presence.js └── background.js ├── babel.config.js ├── src ├── main.js └── App.vue ├── .gitignore ├── .editorconfig ├── package ├── pack.js └── updateVersion.js ├── README.md ├── icon.svg ├── overwrite └── compileChanged.ts ├── locale.js ├── .github └── workflows │ └── deploy.yml ├── webpack.config.js ├── package.json ├── presenceUpdater.ts └── LICENSE /Extension/Pages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Extension/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lolamtisch/PreWrap/HEAD/Extension/icons/128x128.png -------------------------------------------------------------------------------- /Extension/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lolamtisch/PreWrap/HEAD/Extension/icons/16x16.png -------------------------------------------------------------------------------- /Extension/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lolamtisch/PreWrap/HEAD/Extension/icons/48x48.png -------------------------------------------------------------------------------- /Extension/icons/540x540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lolamtisch/PreWrap/HEAD/Extension/icons/540x540.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | new Vue({ 5 | el: "#app", 6 | render: (h) => h(App), 7 | }); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | presenceUpdater.js 2 | Presences/ 3 | Localization/ 4 | node_modules/ 5 | Extension/Pages/ 6 | Extension/webpack/ 7 | webextension.zip 8 | -------------------------------------------------------------------------------- /Extension/vendor/get_app-black-18dp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | charset = utf-8 3 | 4 | trim_trailing_whitespace = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 2 11 | 12 | [*.js] 13 | end_of_line = lf 14 | insert_final_newline = true 15 | indent_style = space 16 | indent_size = 4 17 | -------------------------------------------------------------------------------- /Extension/vendor/delete-black-18dp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package/pack.js: -------------------------------------------------------------------------------- 1 | const archiver = require("archiver"); 2 | const fs = require("fs"); 3 | const path = require("path"); 4 | 5 | const dist = path.join(__dirname, ".."); 6 | 7 | const output = fs.createWriteStream(path.join(dist, "/webextension.zip")); 8 | const archive = archiver("zip", { 9 | zlib: { level: 9 }, 10 | }); 11 | archive.pipe(output); 12 | archive.directory(path.join(dist, "Extension"), false); 13 | archive.finalize(); 14 | -------------------------------------------------------------------------------- /package/updateVersion.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | 5 | var manifest = path.join(__dirname, "..", "Extension", "manifest.json"); 6 | fs.readFile(manifest, "utf8", function (err, data) { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | 11 | const ver = new Date().toISOString().replace(/T.*/, "").replace(/-0*/g, "."); 12 | 13 | const result = data.replace( 14 | /"version": "[\d|\.]+",/g, 15 | `"version": "${ver}",` 16 | ); 17 | 18 | fs.writeFile(manifest, result, "utf8", function (err) { 19 | if (err) return console.log(err); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /Extension/logReader.js: -------------------------------------------------------------------------------- 1 | const PreWrap_consoleLogger = document.createElement("script"); 2 | PreWrap_consoleLogger.type = "text/javascript"; 3 | PreWrap_consoleLogger.id = "PreWrap_consoleLogger"; 4 | PreWrap_consoleLogger.innerText = ` 5 | console.stdlog = console.log.bind(console); 6 | console.logs = []; 7 | console.log = function() { 8 | let inc = Array.from(arguments); 9 | inc.forEach(arg => { 10 | console.logs.push(arg); 11 | }); 12 | while (console.logs.length > 100) { 13 | console.logs.shift(); 14 | } 15 | console.stdlog.apply(console, arguments); 16 | }; 17 | `; 18 | document.head.appendChild(PreWrap_consoleLogger); 19 | -------------------------------------------------------------------------------- /Extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "PreWrap", 4 | "version": "0.0.1", 5 | "icons": { 6 | "16": "icons/16x16.png", 7 | "48": "icons/48x48.png", 8 | "128": "icons/128x128.png" 9 | }, 10 | "permissions": [ 11 | "storage", 12 | "activeTab", 13 | "webNavigation" 14 | ], 15 | "optional_permissions": [ 16 | "http://*/*", 17 | "https://*/*" 18 | ], 19 | "background": { 20 | "scripts": [ 21 | "Pages/pages.js", 22 | "Pages/locale.js", 23 | "background.js" 24 | ], 25 | "persistent": false 26 | }, 27 | "browser_action": { 28 | "default_popup": "popup.html" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PreWrap 2 | [PreMiD Presences](https://github.com/PreMiD/Presences) wrapper for the [Discord-RPC-Extension](https://github.com/lolamtisch/Discord-RPC-Extension) with focus on security and performance. 3 | The included presences are not created nor maintained by me. All credit goes to the [PreMiD](https://premid.app/) team and their [contributors](https://premid.app/contributors). 4 | 5 | ### Download 6 | Chrome 7 | Firefox 8 | 9 | ### What is the difference to PreMiD 10 | * No remote javascript execution or remote dependencies 11 | * Permission requested only for the active Presences 12 | * minimal content script and it only gets injected for the active Presence pages. 13 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /overwrite/compileChanged.ts: -------------------------------------------------------------------------------- 1 | import actions from "@actions/core"; 2 | import chalk from "chalk"; 3 | 4 | import PresenceCompiler from "../classes/PresenceCompiler.js"; 5 | 6 | import { basename, dirname } from "node:path"; 7 | import glob from "glob"; 8 | 9 | const compiler = new PresenceCompiler(), 10 | changedFolders = getDiff(); 11 | 12 | if (!changedFolders.length) 13 | actions.info(chalk.green("No Presences changed, exiting...")); 14 | else { 15 | const errors = await compiler.compilePresence(changedFolders); 16 | 17 | for (const error of errors.filter(error => !error.name.includes("TS"))) 18 | actions.error(error); 19 | 20 | //if (errors.length) 21 | //actions.setFailed("Some Presences failed to compile, exiting..."); 22 | } 23 | 24 | export function getDiff(): string[] { 25 | const changedPresenceFolders = glob.sync("websites/*/*/metadata.json", { absolute: true }) 26 | 27 | if (!changedPresenceFolders.length) return []; 28 | 29 | return [...new Set(changedPresenceFolders.map(f => basename(dirname(f))))]; 30 | } 31 | -------------------------------------------------------------------------------- /Extension/Iframe.js: -------------------------------------------------------------------------------- 1 | if (typeof oldLog !== 'undefined' && oldLog) { 2 | console.error('Content and Iframe executed at the same time'); 3 | console.log = oldLog; 4 | } 5 | 6 | console.log = (function () { 7 | return Function.prototype.bind.call( 8 | console.log, 9 | console, 10 | "%cIframe", 11 | "background-color: #312f40; color: white; padding: 2px 10px; border-radius: 3px;" 12 | ); 13 | })(); 14 | 15 | var activeIframePresence = null; 16 | 17 | class iFrame { 18 | constructor() { 19 | this._events = []; 20 | console.log('loaded', this.getUrl()) 21 | activeIframePresence = this; 22 | } 23 | 24 | getUrl() { 25 | return window.location.href; 26 | } 27 | 28 | on(eventName, callback) { 29 | this._events[eventName] = callback; 30 | } 31 | 32 | send(data) { 33 | console.log("send", data); 34 | chrome.runtime.sendMessage({ type: "iframeData", data: data }); 35 | } 36 | 37 | callEvent() { 38 | this._events["UpdateData"](); 39 | } 40 | } 41 | 42 | chrome.runtime.onMessage.addListener(function (info, sender, sendResponse) { 43 | if (info.type === 'presence') { 44 | console.log('Iframe data requested', info); 45 | activeIframePresence.callEvent(); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /locale.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | const fs = require('fs') 3 | 4 | console.log('Generate locale'); 5 | 6 | main(); 7 | 8 | function main() { 9 | let = langRes = {}; 10 | 11 | getFolder('./Localization/src/Extension').forEach(el => { 12 | const tLang = readFile('./Localization/src/Extension/'+el); 13 | langRes = {...langRes, ...tLang}; 14 | }); 15 | 16 | getFolder('./Localization/src/Presence').forEach(el => { 17 | const tLang = readFile('./Localization/src/Presence/'+el); 18 | langRes = {...langRes, ...tLang}; 19 | }); 20 | 21 | writeObj(langRes); 22 | } 23 | 24 | function getFolder(path) { 25 | return fs.readdirSync(path); 26 | } 27 | 28 | function readFile(path) { 29 | const data = fs.readFileSync(path, 'utf8'); 30 | const json = JSON.parse(data); 31 | const res = {}; 32 | for (const el in json) { 33 | res[el] = json[el].message; 34 | } 35 | 36 | return res; 37 | } 38 | 39 | function writeObj(obj) { 40 | console.log(obj); 41 | const content = ` 42 | var language = ${JSON.stringify(obj)}; 43 | `; 44 | fs.writeFileSync('./Extension/Pages/locale.js', content); 45 | } 46 | 47 | async function getJson(url) { 48 | return new Promise((resolve, reject) => { 49 | request({url: url}, function (error, response, body) { 50 | if(error) { 51 | console.error('error:', error); 52 | reject(error); 53 | return; 54 | } 55 | if(response && response.statusCode === 200) { 56 | resolve(JSON.parse(body)); 57 | } 58 | }); 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deployment 2 | on: 3 | schedule: 4 | - cron: '0 0 * * 0' 5 | workflow_dispatch: 6 | push: 7 | branches: 8 | - master 9 | 10 | jobs: 11 | Firefox: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v1 16 | with: 17 | node-version: '16.x' 18 | - name: Build 19 | run: | 20 | npm ci 21 | npm run build 22 | env: 23 | APP_TARGET: firefox 24 | - name: Pack 25 | run: | 26 | npm run pack:webextension 27 | - uses: trmcnvn/firefox-addon@v1 28 | with: 29 | uuid: '{9474c3da-698d-46ca-a50f-e8ff1ebdfff1}' 30 | xpi: webextension.zip 31 | manifest: Extension/manifest.json 32 | api-key: ${{ secrets.FIREFOX_API_KEY }} 33 | api-secret: ${{ secrets.FIREFOX_API_SECRET }} 34 | 35 | Chrome: 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v2 39 | - uses: actions/setup-node@v1 40 | with: 41 | node-version: '16.x' 42 | - name: Build 43 | run: | 44 | npm ci 45 | npm run build 46 | env: 47 | APP_TARGET: chrome 48 | - name: Pack 49 | run: | 50 | npm run pack:webextension 51 | - name: Deploy 52 | uses: trmcnvn/chrome-addon@v2 53 | with: 54 | extension: calpcokkjmookodfpbmdbknfcjhekgaj 55 | zip: webextension.zip 56 | client-id: ${{ secrets.DEV_CHROME_CLIENT_ID }} 57 | client-secret: ${{ secrets.DEV_CHROME_CLIENT_SECRET }} 58 | refresh-token: ${{ secrets.DEV_CHROME_REFRESH_TOKEN }} 59 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); 4 | const TerserPlugin = require("terser-webpack-plugin"); 5 | 6 | module.exports = { 7 | entry: "./src/main.js", 8 | output: { 9 | path: path.resolve(__dirname, "./Extension/webpack"), 10 | publicPath: "/dist/", 11 | filename: "popup.js", 12 | }, 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.js$/, 17 | loader: "babel-loader", 18 | exclude: /node_modules/, 19 | }, 20 | { 21 | test: /\.less$/, 22 | exclude: /node_modules/, 23 | use: [ 24 | "vue-style-loader", 25 | { loader: "to-string-loader" }, 26 | { loader: "css-loader" }, 27 | { loader: "less-loader" }, 28 | ], 29 | }, 30 | { 31 | test: /\.vue$/, 32 | exclude: /node_modules/, 33 | loader: "vue-loader", 34 | options: { 35 | shadowMode: true, 36 | }, 37 | }, 38 | ], 39 | }, 40 | resolve: { 41 | alias: { 42 | vue$: "vue/dist/vue.esm.js", 43 | }, 44 | extensions: ["*", ".js", ".vue", ".json"], 45 | }, 46 | devServer: { 47 | historyApiFallback: true, 48 | noInfo: true, 49 | overlay: true, 50 | }, 51 | performance: { 52 | hints: false, 53 | }, 54 | devtool: "source-map", 55 | plugins: [ 56 | new VueLoaderPlugin(), 57 | new webpack.optimize.LimitChunkCountPlugin({ 58 | maxChunks: 1, 59 | }), 60 | new TerserPlugin({ 61 | terserOptions: { 62 | output: { 63 | beautify: true, 64 | comments: false, 65 | }, 66 | mangle: false, 67 | compress: true, 68 | }, 69 | }), 70 | ], 71 | optimization: { 72 | minimize: false, 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "presences", 3 | "version": "3.0.0", 4 | "author": "Timeraa", 5 | "license": "MPL-2.0", 6 | "scripts": { 7 | "cleanup": "rm -rf Localization && rm -rf Presences && rm -rf Extension/Pages/* && touch Extension/Pages/.gitkeep", 8 | "cleanup:win": "(if exist .\\Localization ( rmdir /s/q .\\Localization ) || true) && (if exist .\\Presences ( rmdir /s/q .\\Presences ) || true) && (if exist .\\Extension\\Pages ( rmdir /s/q .\\Extension\\Pages ) || true) && mkdir .\\Extension\\Pages && type nul > .\\Extension\\Pages\\.gitkeep", 9 | "clone": "git clone https://github.com/PreMiD/Presences.git ./Presences && git clone https://github.com/PreMiD/Localization.git ./Localization", 10 | "pu": "node ./presenceUpdater.js", 11 | "pu:compile": "node ./node_modules/typescript/bin/tsc --module CommonJS --target ES2020 --esModuleInterop --removeComments --noUnusedParameters --noUnusedLocals --noFallthroughCasesInSwitch --newLine lf --inlineSourceMap ./presenceUpdater.ts", 12 | "pack:webextension": "node package/updateVersion.js && node package/pack.js", 13 | "pack": "npm run build && npm run pack:webextension", 14 | "build": "npm run cleanup && npm run build:build", 15 | "build:build": "npm run clone && npm run pu:compile && npm run pu && npm run build:webpack && npm run build:localisation", 16 | "build:webpack": "webpack", 17 | "build:localisation": "node locale.js", 18 | "build:win": "npm run cleanup:win && npm run build:build" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.15.5", 22 | "@babel/preset-env": "^7.15.6", 23 | "@types/babel__core": "^7.1.16", 24 | "@types/chrome": "^0.0.158", 25 | "@types/glob": "^7.1.4", 26 | "@types/mongodb": "4.0.7", 27 | "@types/node": "^16.10.2", 28 | "@types/prettier": "^2.4.1", 29 | "@types/semver": "^7.3.8", 30 | "@typescript-eslint/eslint-plugin": "^4.33.0", 31 | "@typescript-eslint/parser": "^4.33.0", 32 | "@vue/cli-plugin-babel": "^4.5.6", 33 | "archiver": "^5.0.2", 34 | "axios": "^0.22.0", 35 | "babel-loader": "^8.1.0", 36 | "chalk": "^4.1.2", 37 | "eslint": "^7.32.0", 38 | "execa": "^4.0.3", 39 | "glob": "^7.2.0", 40 | "jsonschema": "^1.4.0", 41 | "mongodb": "^3.6.9", 42 | "prettier": "^2.4.1", 43 | "semver": "^7.3.5", 44 | "source-map-support": "^0.5.19", 45 | "terser": "^5.9.0", 46 | "terser-webpack-plugin": "^4.2.2", 47 | "typescript": "^4.4.3", 48 | "vue": "^2.6.12", 49 | "vue-loader": "^15.9.3", 50 | "vue-template-compiler": "^2.6.12", 51 | "webpack": "^4.44.2", 52 | "webpack-cli": "^3.3.12" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Extension/popup.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 192 | 193 | 194 |