Skip to content

Commit

Permalink
3-price-tracking-and-monitoring (#12)
Browse files Browse the repository at this point in the history
* Add price tracking functionality and update manifest permissions

* Refactor normalizeContent function to handle numeric content with commas and dots

* Refactor element selection and data storage logic

* better design

* import logik

* remove all comments

* Add export and import buttons to popup.html and display current selector and selected content in popup.js

---------

Co-authored-by: KleinerCodeDrago <[email protected]>
  • Loading branch information
KleinerCodeDrago and KleinerCodeDrago authored Feb 21, 2024
1 parent 16ae503 commit 2ae4c9c
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 115 deletions.
124 changes: 107 additions & 17 deletions background.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ function storeSelector(url, selector, content) {
browser.storage.local.get(url).then(result => {
let existingData = result[url] || {};
if (content !== '') {
existingData.content = content;
existingData.content = normalizeContent(content);
}
existingData.selector = selector;
browser.storage.local.set({[url]: existingData});
});
}


browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "storeSelector") {
console.log("Received storeSelector message:", message);
storeSelector(message.url, message.selector, message.content);
} else if (message.action === "getSelectorForCurrentTab") {
getSelectorForCurrentTab(function(data) {
sendResponse(data);
});
return true;
}
});

Expand All @@ -28,11 +32,17 @@ function retrieveSelector(url) {

function getSelectorForCurrentTab(callback) {
browser.tabs.query({active: true, currentWindow: true}, function(tabs) {
const url = new URL(tabs[0].url);
browser.storage.local.get(url.href, function(result) {
const data = result[url.href];
if (tabs.length === 0 || !tabs[0].url) {
callback({selector: '', content: ''});
return;
}

const url = tabs[0].url;
browser.storage.local.get(url, function(result) {
const data = result[url];
console.log("Sending data to popup:", data);
if (data) {
callback({selector: data.selector, content: data.content});
callback(data);
} else {
callback({selector: '', content: ''});
}
Expand All @@ -41,21 +51,22 @@ function getSelectorForCurrentTab(callback) {
}


browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.action === "getSelectorForCurrentTab") {
getSelectorForCurrentTab(function(data) {
sendResponse(data);
});
return true;
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "initiateImport") {
browser.tabs.create({url: "import.html"});
}
});


function getSelectorForCurrentTab(callback) {
browser.tabs.query({active: true, currentWindow: true}, function(tabs) {
const url = new URL(tabs[0].url);
browser.storage.local.get(url.href, function(result) {
const data = result[url.href];
if (tabs.length === 0 || !tabs[0].url) {
callback({selector: '', content: ''});
return;
}

const url = tabs[0].url;
browser.storage.local.get(url, function(result) {
const data = result[url];
console.log("Sending data to popup:", data);
if (data) {
callback(data);
Expand All @@ -64,4 +75,83 @@ function getSelectorForCurrentTab(callback) {
}
});
});
}
}

function importData(data) {
console.log("Importing data:", data);
browser.storage.local.clear(() => {
for (let url in data) {
if (data.hasOwnProperty(url)) {
let item = data[url];

if (item.hasOwnProperty('selector') && item.hasOwnProperty('content')) {
let storageItem = {};
storageItem[url] = item;
browser.storage.local.set(storageItem).then(() => {
console.log("Data imported for URL:", url);
}).catch((error) => {
console.error("Error setting data for URL:", url, error);
});
} else {
console.error("Invalid data format for URL:", url, item);
}
}
}
});
}


browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "importData") {
importData(message.data);
}
});


function normalizeContent(content) {
let numericContent = content.replace(/[^\d,.-]/g, '');

let lastCommaIndex = numericContent.lastIndexOf(',');
let lastDotIndex = numericContent.lastIndexOf('.');

if (lastCommaIndex > lastDotIndex) {
numericContent = numericContent.substring(0, lastCommaIndex).replace(/,/g, '') + '.' + numericContent.substring(lastCommaIndex + 1);
} else {
numericContent = numericContent.replace(/,/g, '');
}

return numericContent;
}


function checkPrices() {
browser.storage.local.get(null, function(items) {
for (let url in items) {
if (!url.startsWith('http://') && !url.startsWith('https://')) {
console.error('Invalid URL:', url);
continue;
}

let storedData = items[url];
fetch(url)
.then(response => response.text())
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const element = doc.querySelector(storedData.selector);
const currentContent = element ? normalizeContent(element.innerText) : '';

})
.catch(error => console.error('Error fetching the page:', error));
}
});
}


browser.alarms.create("checkPricesAlarm", { delayInMinutes: 1, periodInMinutes: 1 });
browser.alarms.onAlarm.addListener(alarm => {
if (alarm.name === "checkPricesAlarm") {
checkPrices();
}
});

82 changes: 35 additions & 47 deletions content.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
let isSelectingElement = false;

function enableElementSelection() {
isSelectingElement = true;
document.addEventListener('click', elementSelectionHandler, {once: true});
}

function elementSelectionHandler(e) {
if (!isSelectingElement) {
return;
}

e.preventDefault();
e.stopPropagation();
isSelectingElement = false;

let path = getPathTo(e.target);
highlightElement(e.target);

browser.runtime.sendMessage({
action: "storeSelector",
url: window.location.href,
selector: path,
content: e.target.innerText
});
}

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "selectElement") {
enableElementSelection();
}
});


function getPathTo(element) {
if (element.id) {
return `#${element.id}`;
Expand Down Expand Up @@ -26,57 +60,11 @@ function getPathTo(element) {
return path;
}

document.addEventListener('click', function handler(e) {
e.preventDefault();
e.stopPropagation();

setTimeout(() => {
try {
let path = getPathTo(e.target);
let content = e.target.innerText;
console.log("Captured element:", e.target);
console.log("Captured content:", content);

browser.runtime.sendMessage({
action: "storeSelector",
url: window.location.href,
selector: path,
content: content
});
} catch (error) {
console.error("Error capturing content:", error);
}
}, 500);

document.removeEventListener('click', handler);
}, {once: true});

function highlightElement(element) {
const originalBorder = element.style.border;
element.style.border = '2px solid red';

setTimeout(() => {
element.style.border = originalBorder;
}, 2000);
}

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "selectElement") {
document.addEventListener('click', function handler(e) {
e.preventDefault();
e.stopPropagation();

let path = getPathTo(e.target);
highlightElement(e.target);
console.log("Selected Element CSS Path:", path);

browser.runtime.sendMessage({
action: "storeSelector",
url: window.location.href,
selector: path
});

document.removeEventListener('click', handler);
}, {once: true});
}
});
}
10 changes: 10 additions & 0 deletions import.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Import Data</title>
</head>
<body>
<input type="file" id="fileInput" accept="application/json">
<script src="import.js"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
document.getElementById('fileInput').addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;

const reader = new FileReader();
reader.onload = (e) => {
const data = JSON.parse(e.target.result);
browser.runtime.sendMessage({action: "importData", data: data});
};
reader.readAsText(file);
});
14 changes: 12 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"name": "Price Tracker",
"version": "0.1",
"description": "Track prices on various websites and get notified of changes.",
"permissions": ["activeTab", "storage", "<all_urls>"],
"browser_action": {
"default_popup": "popup.html",
"default_icon": {
Expand All @@ -12,9 +11,20 @@
"128": "icons/icon-128.png"
}
},
"permissions": [
"storage",
"alarms",
"notifications",
"<all_urls>"
],
"background": {
"scripts": ["background.js"]
"scripts": ["background.js"],
"persistent": false
},
"web_accessible_resources": [
"import.html",
"import.js"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
Expand Down
55 changes: 55 additions & 0 deletions popup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
color: #333;
margin: 0;
padding: 20px;
}

#container {
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
max-width: 300px;
margin: auto;
}

h1, h2 {
color: #2a9d8f;
}

button {
background-color: #2a9d8f;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
transition: background-color 0.3s;
}

button:hover {
background-color: #21867a;
}

p {
line-height: 1.6;
}

#status {
margin-bottom: 20px;
color: #555;
}

#selectionInfo, #watchedPrices {
background-color: #eef6f6;
border-radius: 5px;
padding: 10px;
margin-top: 20px;
}

#currentSelector, #selectedContent {
word-break: break-all;
}
Loading

0 comments on commit 2ae4c9c

Please sign in to comment.