Skip to content

Commit

Permalink
Merge pull request #147 from mikepsinn/develop
Browse files Browse the repository at this point in the history
Enhancements to Browser Extension and Documentation Updates
  • Loading branch information
mikepsinn authored Mar 16, 2024
2 parents ad04c72 + 34ddd61 commit 51ba4b2
Show file tree
Hide file tree
Showing 73 changed files with 11,654 additions and 143 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Get this from https://platform.openai.com/account/api-keys
OPENAI_API_KEY=YOUR_API_KEY
OPENAI_MODEL=gpt-3.5-turbo-0125

# Get this from https://lightsail.aws.amazon.com/ls/webapp/us-east-1/buckets
AWS_ACCESS_KEY_ID=your_access_key_id
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ litellm_uuid.txt
.smart-connections
.space
.makemd
desktop.ini
129 changes: 65 additions & 64 deletions apps/browser-extension/background.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { extractAndSaveAmazon } from './extractAndSaveAmazon.js';

chrome.runtime.onInstalled.addListener(() => {
setDailyAlarm(); // Set an alarm on installation
});

function setDailyAlarm() {
chrome.storage.sync.get("frequency", ({ frequency }) => {
const minutes = parseInt(frequency, 10) || 1440; // Default to 1440 minutes (once a day) if not set
chrome.alarms.create("dailyPopup", { periodInMinutes: minutes });
chrome.alarms.create("trackingPopup", { periodInMinutes: minutes });
});
}

Expand All @@ -18,20 +20,63 @@ chrome.storage.onChanged.addListener((changes, namespace) => {
}
});

chrome.alarms.onAlarm.addListener((alarm) => {
console.log("Got an alarm!", alarm);
if (alarm.name === "dailyPopup") {
console.log("Time to show the daily popup!");
// Open a window instead of creating a notification
let popupId = null;

function showTrackingPopup() {
debugger
console.log('Time to show the daily popup!');

let origin = 'https://safe.fdai.earth';
//origin = 'https://local.quantimo.do';

if (popupId !== null) {
chrome.windows.get(popupId, { populate: true }, (win) => {
if (chrome.runtime.lastError) {
// The window was closed or never created. Create it.
chrome.windows.create({
url: origin + '/app/public/android_popup.html',
type: 'popup',
width: 1,
height: 1,
left: 100,
top: 100,
focused: false
}, (win) => {
popupId = win.id;
});
} else {
// The window exists. Update it.
chrome.windows.update(popupId, { focused: true });
}
});
} else {
// No window ID, create a new window.
chrome.windows.create({
url: 'https://safe.fdai.earth/app/public/android_popup.html',
url: origin + '/app/public/android_popup.html',
type: 'popup',
width: 300,
height: 200,
width: 1,
height: 1,
left: 100,
top: 100
top: 100,
focused: false
}, (win) => {
popupId = win.id;
});
}
}

// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "showTrackingPopup") {
showTrackingPopup();
}
});

chrome.alarms.onAlarm.addListener((alarm) => {
console.log("Got an alarm!", alarm);
if (alarm.name === "trackingPopup") {
showTrackingPopup();
}
});

chrome.runtime.onStartup.addListener(() => {
Expand Down Expand Up @@ -98,7 +143,7 @@ chrome.contextMenus.onClicked.addListener((info, tab) => {
// target: {tabId: tab.id},
// function: extractAndSaveAmazon
// });
chrome.tabs.create({url: "https://www.amazon.com/gp/css/order-history?ref_=nav_orders_first"});
chrome.tabs.create({url: "https://www.amazon.com/gp/css/order-history"});
}
});

Expand All @@ -121,7 +166,7 @@ function parseDate(deliveryDate) {
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
console.log("Tab updated:", changeInfo);
// Check if the updated tab's URL is the Amazon order history page
if (changeInfo.url === "https://www.amazon.com/gp/css/order-history?ref_=nav_orders_first") {
if (changeInfo.url && changeInfo.url.startsWith("https://www.amazon.com/gp/css/order-history")) {
debugger
console.log("Amazon order history page loaded");
// Execute the extractAndSaveAmazon function
Expand All @@ -144,59 +189,7 @@ async function getQuantimodoAccessToken() {
});
}

async function extractAndSaveAmazon() {
const productBoxes = document.querySelectorAll('.a-fixed-left-grid.item-box.a-spacing-small, .a-fixed-left-grid.item-box.a-spacing-none');
const deliveryDate = document.querySelector('.delivery-box__primary-text').textContent.trim();
const storedProducts = JSON.parse(localStorage.getItem('products')) || [];
let measurements = [];

for (const box of productBoxes) {
const productImage = box.querySelector('.product-image a img').src;
const productTitle = box.querySelector('.yohtmlc-product-title').textContent.trim();
const productLink = box.querySelector('.product-image a').href;

// Check if the product is already in localStorage
const isProductStored = storedProducts.some(product => product.url === productLink);

if (!isProductStored) {
// If not stored, add the product to the array and localStorage
const newProduct = {
date: deliveryDate,
title: productTitle,
image: productImage,
url: productLink
};
storedProducts.push(newProduct);
localStorage.setItem('products', JSON.stringify(storedProducts));

// Add the product details to the array
measurements.push({
startAt: parseDate(deliveryDate),
variableName: productTitle,
unitName: "Count",
value: 1,
url: productLink,
image: productImage
});
}
}

if(measurements.length > 0) {
const quantimodoAccessToken = await getQuantimodoAccessToken();
const response = await fetch('https://safe.fdai.earth/api/v1/measurements', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${quantimodoAccessToken}`
},
body: JSON.stringify(measurements)
});
const data = await response.json();
console.log('Response from Quantimodo API:', data);
}

console.log(`Processed ${productBoxes.length} products.`);
}

function hasAccessToken() {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -255,7 +248,15 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// Execute your function here
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
//console.log("tabs", tabs);
if(!tabs[0]) {
console.log("No active tabs. Tabs:", tabs);
return;
}
chrome.tabs.sendMessage(tabs[0].id, {message: "getFdaiLocalStorage", key: "accessToken"}, function(response) {
if(!response) {
console.error("No response from getFdaiLocalStorage");
return;
}
//console.log(response.data);
chrome.storage.sync.set({quantimodoAccessToken: response.data}, function() {
console.log('Access token saved:')//, response.data);
Expand Down
2 changes: 1 addition & 1 deletion apps/browser-extension/contentScript.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Function to extract the data
function extractAndSaveAmazon() {
// Send a message to the background script to navigate to the Amazon order history page
chrome.runtime.sendMessage({action: "navigate", url: "https://www.amazon.com/gp/css/order-history?ref_=nav_orders_first"});
chrome.runtime.sendMessage({action: "navigate", url: "https://www.amazon.com/gp/css/order-history"});

// Rest of your function code here...
}
99 changes: 99 additions & 0 deletions apps/browser-extension/extractAndSaveAmazon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
function showNotification(title, message) {
chrome.notifications.create({
type: 'basic',
iconUrl: 'icons/icon.png', // Path to the icon for the notification
title: title,
message: message
});
}

export async function extractAndSaveAmazon(html) {
debugger

html = html || document;

const orderCards = html.querySelectorAll('.order-card');
let measurements = JSON.parse(localStorage.getItem('measurements')) || [];
for (const orderCard of orderCards) {
console.log('Order card:', orderCard);
debugger
let startAt = orderCard.querySelector('.delivery-box__primary-text').textContent.trim();
if(startAt === 'Order received') {
continue;
}
if(startAt.includes('Arriving')) {
continue;
}
startAt = startAt.replace('Delivered ', '').trim();
startAt = startAt + ', ' + new Date().getFullYear();
startAt = parseDate(startAt);
const productBoxes = orderCard.querySelectorAll('.a-fixed-left-grid.item-box.a-spacing-small, .a-fixed-left-grid.item-box.a-spacing-none');
for (const box of productBoxes) {
const image = box.querySelector('.product-image a img').src;
const variableName = "Purchase of " + box.querySelector('.yohtmlc-product-title').textContent.trim();
const url = box.querySelector('.product-image a').href;

showNotification('Saving Purchase Data', `Saving ${variableName} from Amazon`);


// Check if the product is already in localStorage
const isMeasurementStored = measurements.some(measurement => measurement.url === url && measurement.startAt === startAt);

if (!isMeasurementStored) {

// Add the product details to the array
measurements.push({
startAt,
variableName,
unitName: "Count",
value: 1,
variableCategoryName: "Treatments",
sourceName: "Amazon",
url,
image
});
}
}
console.log(`Processed ${orderCards.length} products. Measurements:`, measurements);
}

if(typeof global.apiOrigin === 'undefined') {
global.apiOrigin = 'https://safe.fdai.earth';
}

if(measurements.length > 0) {
console.log('Saving measurements:', measurements);
const quantimodoAccessToken = await getQuantimodoAccessToken();
let input = global.apiOrigin + '/api/v1/measurements?XDEBUG_SESSION_START=PHPSTORM';
const response = await fetch(input, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${quantimodoAccessToken}`,
'X-CLIENT-ID': 'digital-twin-safe',
},
body: JSON.stringify(measurements)
});
// const response = await fetch('https://local.quantimo.do/api/v1/measurements', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// 'Authorization': `Bearer demo`,
// },
// body: JSON.stringify([])
// });
if (!response.ok) {
const text = await response.text();
console.error('Error response:', text);
throw new Error(`HTTP error! status: ${response.status}`);
} else {
const data = await response.json();
console.log('Post Measurement Response from API:', data);
localStorage.setItem('measurements', JSON.stringify(measurements));
}
}
return measurements;

}

//module.exports = extractAndSaveAmazon;
3 changes: 2 additions & 1 deletion apps/browser-extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"https://www.amazon.com/"
],
"background": {
"service_worker": "background.js"
"service_worker": "background.js",
"type": "module"
},
"content_scripts": [
{
Expand Down
32 changes: 17 additions & 15 deletions apps/browser-extension/options.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@
--border-color: #ffffff; /* White for borders */
}

body, html {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}

body {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: radial-gradient(rgba(118, 0, 191, 0.5) 0%, transparent 70%), linear-gradient(#0b161e 40%, #202076 70%);
perspective: 700px;
font-size: clamp(10px, 2vw, 20px);
}


.title {
text-align: center;
Expand Down Expand Up @@ -84,22 +101,7 @@ button:hover {
}


body, html {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}

body {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: radial-gradient(rgba(118, 0, 191, 0.5) 0%, transparent 70%), linear-gradient(#0b161e 40%, #202076 70%);
perspective: 700px;
font-size: clamp(10px, 2vw, 20px);
}

.lines {
position: fixed;
Expand Down
8 changes: 5 additions & 3 deletions apps/browser-extension/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

</head>
<body>
<div class="grid"></div>
<!--<div class="grid"></div>-->
<div class="lines"></div>
<h1>
<span>DIGITAL</span>
Expand All @@ -25,20 +25,22 @@ <h2>Twin Safe</h2>
<div class="option">
<label class="option-label">
<input type="radio" name="behavior" value="popup" checked>
Less Noticeable Background Notification
Less Noticeable Small Notification
</label>
</div>
<div class="option">
<label class="option-label">
<input type="radio" name="behavior" value="direct">
Open Tab Immediately in Foreground
Open Full Inbox Immediately in Foreground
</label>
</div>
<div class="option">
<label for="frequency" class="option-label">Popup Frequency:</label>
<select id="frequency" name="frequency" class="input-field">
<option value="1">Every minute</option>
<option value="60">Every hour</option>
<option value="240">Every 4 hours</option>
<option value="480">Every 8 hours</option>
<option value="1440" selected>Once a day</option>
<option value="10080">Once a week</option>
</select>
Expand Down
Loading

0 comments on commit 51ba4b2

Please sign in to comment.