Compare commits

...

13 Commits

9 changed files with 213 additions and 39 deletions

View File

@ -0,0 +1,7 @@
export const writeText = (text) => { // Write text to clipboard
return DiscordNative.clipboard.copy(text);
};
export const readText = () => { // Read text from clipboard
return DiscordNative.clipboard.read();
};

View File

@ -0,0 +1 @@
export * as clipboard from './clipboard';

View File

@ -8,6 +8,8 @@ export const registerSettings = (id, { label, render, category }) => {
const FormTitle = goosemodScope.webpackModules.findByDisplayName('FormTitle');
const FormSection = goosemodScope.webpackModules.findByDisplayName('FormSection');
if (!Settings.settingStores[category]) Settings.makeStore(category);
goosemodScope.patcher.inject(id, SettingsView.prototype, 'getPredicateSections', (_, sections) => {
const logout = sections.find((c) => c.section === 'logout');
if (!logout) return sections;
@ -22,7 +24,7 @@ export const registerSettings = (id, { label, render, category }) => {
element: () => React.createElement(FormSection, { },
React.createElement(FormTitle, { tag: 'h2' }, finalLabel),
render({
React.createElement(render, {
...Settings.settingStores[category]
})
)

View File

@ -2,26 +2,34 @@
"name": "ms2builder",
"version": "1.0.0",
"description": "Builder for Module Store v2.",
"main": "src/index.js",
"scripts": {
"theme": "node ./scripts/add.js theme"
"theme": "node ./scripts/add.js theme",
"pccompatcheck": "node ./scripts/pccompatCheck.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/GooseMod/MS2Builder.git"
},
"author": "GooseMod",
"license": "MIT",
"bugs": {
"url": "https://github.com/GooseMod/MS2Builder/issues"
},
"homepage": "https://github.com/GooseMod/MS2Builder#readme",
"dependencies": {
"axios": "^0.21.1",
"glob": "^7.1.6",
"parcel-bundler": "^1.12.4",
"sass": "^1.32.8"
},
"alias": {
"@goosemod/patcher": "./moduleWrappers/goosemod/patcher.js",
"@goosemod/webpack": "./moduleWrappers/goosemod/webpack.js",
@ -29,13 +37,17 @@
"@goosemod/reactUtils": "./moduleWrappers/goosemod/reactUtils.js",
"@goosemod/toast": "./moduleWrappers/goosemod/toast.js",
"@goosemod/settings": "./moduleWrappers/goosemod/settings.js",
"powercord/entities": "./moduleWrappers/powercord/entities.js",
"powercord/injector": "./moduleWrappers/powercord/injector.js",
"powercord/webpack": "./moduleWrappers/powercord/webpack.js",
"powercord/util": "./moduleWrappers/powercord/util.js",
"powercord/components/settings": "./moduleWrappers/powercord/components/settings/index.js",
"_powercord/global": "./moduleWrappers/powercord/global/index.js"
"_powercord/global": "./moduleWrappers/powercord/global/index.js",
"electron": "./moduleWrappers/electron/index.js"
},
"type": "module"
}

View File

@ -1,30 +1,36 @@
import { createInterface } from 'readline';
import { readFileSync, writeFileSync } from 'fs';
import { exec as _exec } from 'child_process';
import { promisify } from 'util';
const exec = promisify(_exec);
const rl = createInterface({
input: process.stdin,
output: process.stdout
});
const [ type1, type2, repo ] = process.argv.slice(2);
console.log(type1, type2, repo);
const [ type1, type2, repo, subpath ] = process.argv.slice(2);
console.log(type1, type2, repo, subpath);
const ask = async (prompt) => {
return await new Promise((resp) => {
rl.question(prompt, (ans) => {
resp(ans);
});
});
};
const repeatAsk = async (prompt) => {
const answers = [];
const ask = async () => {
return await new Promise((resp) => {
rl.question(prompt, (ans) => {
resp(ans);
});
});
};
let ans;
while (ans !== '') {
ans = await ask();
ans = await ask(prompt);
if (ans === '') break;
answers.push(ans);
@ -57,6 +63,16 @@ switch (type1) {
break;
}
case 'bd': {
file = `src/modules/ports/themes/bdThemes.js`;
js = ` ['${repo}', '', '${subpath}', 'bdTheme', {
authors: ${JSON.stringify(authors)},
images: ${JSON.stringify(images)}
}],`;
break;
}
}
break;
@ -73,4 +89,26 @@ contents = contents.join('\n');
writeFileSync(file, contents);
const shouldCommit = await new Promise((resp) => {
rl.question(`Continue with automated Git (Y/N) > `, (ans) => {
resp(ans);
});
}) === 'Y';
if (shouldCommit) {
console.log('Building...');
await exec(`node src/index.js`);
console.log('Committing...');
await exec(`git add dist ${file}`);
await exec(`git commit -m "[(Auto) Add Theme (${type2.toUpperCase()}Theme)] ${repo}"`);
console.log('Pushing...');
await exec(`git push`);
}
rl.close();

82
scripts/pccompatCheck.js Normal file
View File

@ -0,0 +1,82 @@
import { exec } from 'child_process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { existsSync, readFileSync } from 'fs';
import glob from 'glob';
function underline(text) {
return `\x1b[4m${text}\x1b[0m`;
}
const __dirname = dirname(fileURLToPath(import.meta.url));
const { alias } = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
const clonesDir = join(__dirname, '..', 'clones');
const [ repo ] = process.argv.slice(2);
const cloneDir = join(clonesDir, repo);
const url = `https://github.com/${repo}.git`;
console.log(cloneDir, url);
if (!existsSync(cloneDir)) {
await new Promise((res) => exec(`git clone ${url} ${cloneDir}`, res));
}
console.log();
for (const jsFile of glob.sync(`${cloneDir}/**/*.js`).concat(glob.sync(`${cloneDir}/**/*.jsx`))) {
console.log(underline(jsFile.replace(cloneDir, '')));
const js = readFileSync(jsFile, 'utf8');
let match;
const importRegex = /{ *(.*,*) *} *= *require\(('|"|`)(.*)('|"|`)\)/g;
while ((match = importRegex.exec(js)) !== null) {
let [ _1, imports, _2, requirePath, _3 ] = match;
imports = imports.trim();
if (requirePath.includes('.')) continue;
const aliasPath = alias[requirePath];
if (!aliasPath) {
console.log('No alias', requirePath);
continue;
}
const aliasJS = readFileSync(join(__dirname, '..', aliasPath), 'utf8');
for (let imp of imports.split(',')) {
imp = imp.trim().split(':')[0];
const searchRegex = new RegExp(`^export.*${imp}.*$`, 'gm');
const searchMatch = aliasJS.match(searchRegex);
if (!searchMatch) {
if (requirePath === 'powercord/webpack') {
const webpackJS = readFileSync(join(__dirname, '..', '..', 'GooseMod', 'src', 'util', 'discord', 'webpackModules.js'), 'utf8');
if (imp.startsWith('getModule') || webpackJS.includes(`obj.common.${imp}`)) {
continue;
}
}
if (requirePath === 'powercord/injector') {
continue;
}
console.log('No export', requirePath, imp);
}
}
}
console.log();
}

View File

@ -48,7 +48,7 @@ if (existsSync(clonesDir)) {
process.chdir(cloneDir);
const currentHash = await new Promise((res) => exec(`git rev-parse HEAD`, (err, stdout) => res(stdout.trim())));
const moduleInRepos = ModuleRepos.map(
(x) => x.modules.filter(
(y) => y[0] === cloneDir.replace(`${clonesDir}/`, '') && (y[1] === currentHash || !y[1])
@ -103,25 +103,29 @@ for (const parentRepo of ModuleRepos) {
const name = repo[0];
const cloneDir = `${clonesDir}/${name}`;
const moduleDir = repo[2] || '';
let moduleDir = repo[2] || '';
if (previous.includes(repo)) {
let currentModule = currentRepoJson.modules.filter((x) => x.github.repo === repo[0]);
if (currentModule.length > 1) {
const manifest = JSON.parse(readFileSync(`${cloneDir}${moduleDir}/goosemodModule.json`));
try {
if (previous.includes(repo)) {
let currentModule = currentRepoJson.modules.filter((x) => x.github.repo === repo[0]);
if (currentModule.length > 1) {
const manifest = JSON.parse(readFileSync(`${cloneDir}${moduleDir}/goosemodModule.json`));
currentModule = currentModule.find((x) => x.name === manifest.name);
} else {
currentModule = currentModule[0];
}
currentModule = currentModule.find((x) => x.name === manifest.name);
} else {
currentModule = currentModule[0];
}
moduleJson.modules.push(currentModule);
moduleJson.modules.push(currentModule);
process.stdout.write('[SKIP] ');
process.stdout.write('[SKIP] ');
console.timeEnd(repo.slice(0, 2).join(' @ ')+`${repo[2] ? ` ${repo[2]}` : ''}`);
console.timeEnd(repo.slice(0, 2).join(' @ ')+`${repo[2] ? ` ${repo[2]}` : ''}`);
continue;
continue;
}
} catch (e) {
console.log('Cache fail', repo[0], e);
}
let githubInfo = getGithubInfo(repo[0]);
@ -155,7 +159,11 @@ for (const parentRepo of ModuleRepos) {
await new Promise((res) => exec(`git checkout ${commitHash}`, res));
if (preprocessor) {
(await import(`./preprocessors/${preprocessor}.js`)).default(`${cloneDir}${moduleDir}`, repo);
const preOut = (await import(`./preprocessors/${preprocessor}.js`)).default(`${cloneDir}${moduleDir}`, repo);
if (preOut !== undefined) {
moduleDir = preOut;
}
}
const manifest = JSON.parse(readFileSync(`${cloneDir}${moduleDir}/goosemodModule.json`));
@ -163,7 +171,7 @@ for (const parentRepo of ModuleRepos) {
// console.log(manifest);
const outFile = `${manifest.name}.js`;
const bundler = new Parcel(`${cloneDir}${moduleDir}/${manifest.main}`, Object.assign(parcelOptions, {
outFile
}));

View File

@ -12,9 +12,11 @@ export default (themePath, repo) => {
let match;
while ((match = metaReg.exec(content)) !== null) {
const [_, key, value] = match;
let [_, key, value] = match;
if (key === 'import') break;
value = value.trim();
// console.log(key, value);
switch (key) {

View File

@ -1,11 +1,16 @@
import { join } from 'path';
import { readFileSync, writeFileSync, mkdirSync, rmSync } from 'fs';
import sass from 'sass';
import glob from 'glob';
export default (manifestPath, repo) => {
const baseDir = join(manifestPath, '..');
const pcManifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
let manifest = {
main: '../index.js',
main: 'index.js',
tags: ['port'],
name: pcManifest.name,
@ -15,9 +20,6 @@ export default (manifestPath, repo) => {
authors: [ pcManifest.author ]
};
rmSync(manifestPath);
mkdirSync(manifestPath);
let content = readFileSync(pcManifest.main || 'index.js', 'utf8');//.replace(/\\/g, '\\\\').replace(/`/g, '\\`');
content = content.replace(`module.exports = `, `export default new `);
@ -29,7 +31,7 @@ export default (manifestPath, repo) => {
if (path.split('.').pop() === 'scss') {
css = (sass.renderSync({ file: path })).css.toString('utf8');
} else {
css = readFileSync(sync);
css = readFileSync(path, 'utf8');
}
css = css.replace(/\\/g, '\\\\').replace(/\`/g, '\`'); // Escape backticks
@ -37,8 +39,28 @@ export default (manifestPath, repo) => {
return `this.loadStylesheet(\`${css}\`)`;
});
const jsCode = `import powercord from '_powercord/global';\n` + content;
writeFileSync(join(baseDir, `index.js`), content);
writeFileSync(`${manifestPath}/goosemodModule.json`, JSON.stringify(manifest));
writeFileSync(`${manifestPath}/../index.js`, jsCode);
for (const jsFile of glob.sync(`${baseDir}/**/*.js`)) {
console.log(jsFile);
let content = readFileSync(jsFile, 'utf8');
/* Here we preappend some JS to each file to match context and fix some weird bundler bugs:
- Import our own Powercord global
- Fix dynamic imports (like using require("powercord/" + someVariable)) causing errors (due to no static analyse). Do this because some plugins use it for PC + VZ compat with the same JS
*/
content = `import powercord from '_powercord/global';
require.cache['powercord/entities'] = require('powercord/entities');
require.cache['powercord/components/settings'] = require('powercord/components/settings');
require.cache['powercord/webpack'] = require('powercord/webpack');
${content}`;
writeFileSync(jsFile, content);
}
writeFileSync(join(baseDir, `goosemodModule.json`), JSON.stringify(manifest));
return '';
};