Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GitHub OAuth Secrets for LeetHub-3.0
GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
5 changes: 3 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import reactHooks from 'eslint-plugin-react-hooks';
import globals from 'globals';

export default [
{
ignores: ['node_modules/**', 'dist/**', 'build/**', 'src/js/static/**', 'Original/**'],
},
js.configs.recommended,
prettierConfig,
{
Expand All @@ -22,7 +25,6 @@ export default [
...globals.browser,
...globals.node,
...globals.webextensions,
...globals.jquery,
},
},
rules: {
Expand All @@ -39,6 +41,5 @@ export default [
version: 'detect',
},
},
ignores: ['node_modules/', 'dist/', 'build/'],
},
];
6 changes: 6 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
"unlimitedStorage",
"storage"
],
"host_permissions": [
"https://api.github.com/*",
"https://github.com/*",
"https://leetcode.com/*",
"https://leetcode.cn/*"
],
"content_scripts": [
{
"matches": [
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
"private": true,
"description": "Automatically integrate your code with LeetCode and GitHub",
"scripts": {
"setup": "npm i",
"setup": "npm i && node setup-env.js",
"config": "node setup-env.js",
"format": "prettier --write **/*.{js,jsx,ts,tsx,css,html}",
"format-test": "prettier --check **/*.{js,jsx,ts,tsx,css,html}",
"lint": "eslint . --fix --ignore-pattern 'src/js/static/jquery-3.3.1.min.js' --ignore-pattern 'src/js/static/semantic-2.4.1.min.js'",
"lint-test": "eslint . --color --ignore-pattern 'src/js/static/jquery-3.3.1.min.js' --ignore-pattern 'src/js/static/semantic-2.4.1.min.js'"
"lint": "eslint . --fix",
"lint-test": "eslint . --color"
},
"devDependencies": {
"@eslint/js": "^9.23.0",
Expand Down
102 changes: 102 additions & 0 deletions setup-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const ENV_PATH = path.join(__dirname, '.env');
const ENV_EXAMPLE_PATH = path.join(__dirname, '.env.example');
const AUTHORIZE_JS_PATH = path.join(__dirname, 'src', 'js', 'authorize.js');
const OAUTH2_JS_PATH = path.join(__dirname, 'src', 'js', 'oauth2.js');

// Parse a .env file content
function parseEnv(content) {
const env = {};
const lines = content.split('\n');
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const index = trimmed.indexOf('=');
if (index === -1) continue;
const key = trimmed.substring(0, index).trim();
let value = trimmed.substring(index + 1).trim();
// Remove surrounding quotes if present
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.substring(1, value.length - 1);
}
env[key] = value;
}
return env;
}

// Extract current secrets from authorize.js
function extractSecrets() {
if (!fs.existsSync(AUTHORIZE_JS_PATH)) {
return { clientId: '', clientSecret: '' };
}
const content = fs.readFileSync(AUTHORIZE_JS_PATH, 'utf8');
const clientIdMatch = content.match(/this\.CLIENT_ID\s*=\s*['"]([^'"]*)['"]/);
const clientSecretMatch = content.match(/this\.CLIENT_SECRET\s*=\s*['"]([^'"]*)['"]/);
return {
clientId: clientIdMatch ? clientIdMatch[1] : '',
clientSecret: clientSecretMatch ? clientSecretMatch[1] : '',
};
}

// Update authorize.js and oauth2.js with secrets from env
function updateSecrets(clientId, clientSecret) {
if (fs.existsSync(AUTHORIZE_JS_PATH)) {
let content = fs.readFileSync(AUTHORIZE_JS_PATH, 'utf8');
content = content.replace(/(this\.CLIENT_ID\s*=\s*['"])[^'"]*(['"])/, `$1${clientId}$2`);
content = content.replace(
/(this\.CLIENT_SECRET\s*=\s*['"])[^'"]*(['"])/,
`$1${clientSecret}$2`,
);
fs.writeFileSync(AUTHORIZE_JS_PATH, content, 'utf8');
console.log('Updated src/js/authorize.js');
}

if (fs.existsSync(OAUTH2_JS_PATH)) {
let content = fs.readFileSync(OAUTH2_JS_PATH, 'utf8');
content = content.replace(/(const\s+CLIENT_ID\s*=\s*['"])[^'"]*(['"])/, `$1${clientId}$2`);
fs.writeFileSync(OAUTH2_JS_PATH, content, 'utf8');
console.log('Updated src/js/oauth2.js');
}
}

function main() {
const current = extractSecrets();

// Create .env.example if it doesn't exist
if (!fs.existsSync(ENV_EXAMPLE_PATH)) {
const exampleContent = `# GitHub OAuth Secrets for LeetHub-3.0
GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
`;
fs.writeFileSync(ENV_EXAMPLE_PATH, exampleContent, 'utf8');
console.log('Created .env.example');
}

// Create .env with current values if it doesn't exist
if (!fs.existsSync(ENV_PATH)) {
const envContent = `# GitHub OAuth Secrets for LeetHub-3.0
GITHUB_CLIENT_ID=${current.clientId || 'your_client_id_here'}
GITHUB_CLIENT_SECRET=${current.clientSecret || 'your_client_secret_here'}
`;
fs.writeFileSync(ENV_PATH, envContent, 'utf8');
console.log('Created .env with existing credentials');
} else {
// If it exists, read it and update files
const envContent = fs.readFileSync(ENV_PATH, 'utf8');
const env = parseEnv(envContent);
const clientId = env.GITHUB_CLIENT_ID || current.clientId;
const clientSecret = env.GITHUB_CLIENT_SECRET || current.clientSecret;
updateSecrets(clientId, clientSecret);
}
}

main();
Loading