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
18 changes: 10 additions & 8 deletions popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ $('#authenticate').on('click', () => {
});

/* Get URL for welcome page */
$('#welcome_URL').attr(
'href',
chrome.runtime.getURL('welcome.html')
);
$('#hook_URL').attr(
'href',
chrome.runtime.getURL('welcome.html')
);
$('#welcome_URL').attr('href', chrome.runtime.getURL('welcome.html'));
$('#hook_URL').attr('href', chrome.runtime.getURL('welcome.html'));

chrome.storage.local.get('leethub_token', (data) => {
const token = data.leethub_token;
Expand Down Expand Up @@ -69,9 +63,17 @@ chrome.storage.local.get('leethub_token', (data) => {
action = true;
$('#auth_mode').show();
});
} else {
console.error(
`LeetHub: unexpected GitHub API status ${xhr.status}`,
xhr.responseText,
);
}
}
});
xhr.addEventListener('error', function () {
console.error('LeetHub: network error validating GitHub token');
});
xhr.open('GET', AUTHENTICATION_URL, true);
xhr.setRequestHeader('Authorization', `token ${token}`);
xhr.send();
Expand Down
81 changes: 77 additions & 4 deletions scripts/authorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,28 @@ const localAuth = {
*/
parseAccessCode(url) {
if (url.match(/\?error=(.+)/)) {
const errorMatch = url.match(/\?error=([^&]+)/);
console.error(
'LeetHub: GitHub OAuth error:',
errorMatch ? decodeURIComponent(errorMatch[1]) : 'unknown',
);
alert(
'GitHub authorization was denied or failed. Please try again.',
);
chrome.tabs.getCurrent(function (tab) {
chrome.tabs.remove(tab.id, function () {});
});
} else {
const codeMatch = url.match(/\?code=([\w\/\-]+)/);
if (!codeMatch) {
console.error(
'LeetHub: could not extract access code from URL:',
url,
);
return;
}
// eslint-disable-next-line
this.requestToken(url.match(/\?code=([\w\/\-]+)/)[1]);
this.requestToken(codeMatch[1]);
}
},

Expand All @@ -51,17 +67,42 @@ const localAuth = {
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
that.finish(
xhr.responseText.match(/access_token=([^&]*)/)[1],
const tokenMatch = xhr.responseText.match(
/access_token=([^&]*)/,
);
if (!tokenMatch) {
console.error(
'LeetHub: access_token not found in OAuth response',
);
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: 'access_token not found in response',
});
return;
}
that.finish(tokenMatch[1]);
} else {
console.error(
`LeetHub: token request failed with status ${xhr.status}:`,
xhr.responseText,
);
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: `Token request failed (HTTP ${xhr.status})`,
});
}
}
});
xhr.addEventListener('error', function () {
console.error('LeetHub: network error during token request');
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: 'Network error during token request',
});
});
xhr.open('POST', this.ACCESS_TOKEN_URL, true);
xhr.send(data);
},
Expand All @@ -80,17 +121,49 @@ const localAuth = {
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const username = JSON.parse(xhr.responseText).login;
let username;
try {
username = JSON.parse(xhr.responseText).login;
} catch (e) {
console.error(
'LeetHub: failed to parse GitHub user response:',
e,
);
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: 'Failed to parse user profile response',
});
return;
}
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: true,
token,
username,
KEY: this.KEY,
});
} else {
console.error(
`LeetHub: GitHub user validation failed (HTTP ${xhr.status}):`,
xhr.responseText,
);
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: `User validation failed (HTTP ${xhr.status})`,
});
}
}
});
xhr.addEventListener('error', function () {
console.error('LeetHub: network error validating GitHub user');
chrome.runtime.sendMessage({
closeWebPage: true,
isSuccess: false,
error: 'Network error validating user',
});
});
xhr.open('GET', AUTHENTICATION_URL, true);
xhr.setRequestHeader('Authorization', `token ${token}`);
xhr.send();
Expand Down
75 changes: 38 additions & 37 deletions scripts/background.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,46 @@
function handleMessage(request) {
if (
request &&
request.closeWebPage === true &&
request.isSuccess === true
) {
/* Set username */
chrome.storage.local.set(
{ leethub_username: request.username },
() => {
window.localStorage.leethub_username = request.username;
},
);
if (request && request.closeWebPage === true) {
if (request.isSuccess === true) {
/* Set username */
chrome.storage.local.set(
{ leethub_username: request.username },
() => {
window.localStorage.leethub_username = request.username;
},
);

/* Set token */
chrome.storage.local.set({ leethub_token: request.token }, () => {
window.localStorage[request.KEY] = request.token;
});
/* Set token */
chrome.storage.local.set(
{ leethub_token: request.token },
() => {
window.localStorage[request.KEY] = request.token;
},
);

/* Close pipe */
chrome.storage.local.set({ pipe_leethub: false }, () => {
console.log('Closed pipe.');
});
/* Close pipe */
chrome.storage.local.set({ pipe_leethub: false }, () => {
console.log('Closed pipe.');
});

chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
});
chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
});

/* Go to onboarding for UX */
const urlOnboarding = chrome.runtime.getURL('welcome.html');
chrome.tabs.create({ url: urlOnboarding, active: true }); // creates new tab
} else if (
request &&
request.closeWebPage === true &&
request.isSuccess === true
) {
alert(
'Something went wrong while trying to authenticate your profile!',
);
chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
});
/* Go to onboarding for UX */
const urlOnboarding = chrome.runtime.getURL('welcome.html');
chrome.tabs.create({ url: urlOnboarding, active: true }); // creates new tab
} else {
console.error(
'LeetHub authentication failed:',
request.error || 'Unknown error',
);
alert(
'Something went wrong while trying to authenticate your profile!',
);
chrome.tabs.getSelected(null, function (tab) {
chrome.tabs.remove(tab.id);
});
}
}
}

Expand Down
74 changes: 60 additions & 14 deletions scripts/gfg.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ const toKebabCase = (string) => {
};

function findGfgLanguage() {
const ele = document.getElementsByClassName('divider text')[0]
.innerText;
const elements = document.getElementsByClassName('divider text');
if (!elements || elements.length === 0) {
console.error(
'LeetHub: could not find language element on GFG page',
);
return null;
}
const ele = elements[0].innerText;
const lang = ele.split('(')[0].trim();
if (lang.length > 0 && languages[lang]) {
return languages[lang];
Expand All @@ -30,19 +36,35 @@ function findGfgLanguage() {
}

function findTitle() {
const ele = document.querySelector('[class^="problems_header_content__title"] > h3')
.innerText;
if (ele != null) {
return ele;
const node = document.querySelector(
'[class^="problems_header_content__title"] > h3',
);
if (node && node.innerText) {
return node.innerText;
}
console.error('LeetHub: could not find problem title on GFG page');
return '';
}

function findDifficulty() {
const ele = document.querySelectorAll('[class^="problems_header_description"]')[0].children[0].innerText;
const elements = document.querySelectorAll(
'[class^="problems_header_description"]',
);
if (
!elements ||
elements.length === 0 ||
!elements[0].children ||
elements[0].children.length === 0
) {
console.error(
'LeetHub: could not find difficulty element on GFG page',
);
return '';
}
const ele = elements[0].children[0].innerText;

if (ele != null) {
if (ele.trim() == 'Basic' || ele.trim() === 'School') {
if (ele.trim() === 'Basic' || ele.trim() === 'School') {
return 'Easy';
}
return ele;
Expand All @@ -51,12 +73,19 @@ function findDifficulty() {
}

function getProblemStatement() {
const ele = document.querySelector('[class^="problems_problem_content"]');
const ele = document.querySelector(
'[class^="problems_problem_content"]',
);
if (!ele) {
console.error(
'LeetHub: could not find problem statement on GFG page',
);
return '';
}
return `${ele.outerHTML}`;
}

function getCode() {

const scriptContent = `
var editor = ace.edit("ace-editor");
var editorContent = editor.getValue();
Expand Down Expand Up @@ -103,14 +132,31 @@ const gfgLoader = setInterval(() => {
'practice.geeksforgeeks.org/problems',
)
) {

const submitBtn = document.evaluate(".//button[text()='Submit']", document.body, null, XPathResult.ANY_TYPE, null).iterateNext();
const submitBtn = document
.evaluate(
".//button[text()='Submit']",
document.body,
null,
XPathResult.ANY_TYPE,
null,
)
.iterateNext();

if (!submitBtn) {
console.error(
'LeetHub: could not find Submit button on GFG page',
);
return;
}

submitBtn.addEventListener('click', function () {
START_MONITOR = true;
const submission = setInterval(() => {
const output = document.querySelectorAll('[class^="problems_content"]')[0]
.innerText;
const outputElems = document.querySelectorAll(
'[class^="problems_content"]',
);
if (!outputElems || outputElems.length === 0) return;
const output = outputElems[0].innerText;
if (
output.includes('Problem Solved Successfully') &&
START_MONITOR
Expand Down
Loading