-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tabtracker #47
base: main
Are you sure you want to change the base?
Add tabtracker #47
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
let userId = null; | ||
|
||
// Load userId from chrome storage when the background script starts | ||
chrome.storage.local.get(['userId'], (result) => { | ||
if (result.userId) { | ||
userId = result.userId; | ||
startTrackingTabs(); | ||
} | ||
}); | ||
|
||
// Listener for the login event | ||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { | ||
if (request.action === 'login') { | ||
userId = request.userId; | ||
|
||
// Store userId in chrome.storage | ||
chrome.storage.local.set({ userId: userId }, () => { | ||
console.log('User ID saved in background script.'); | ||
}); | ||
|
||
startTrackingTabs(); | ||
sendResponse({ status: 'Tracking started' }); | ||
} | ||
}); | ||
|
||
// Function to start tracking tabs indefinitely | ||
function startTrackingTabs() { | ||
setInterval(async () => { | ||
if (!userId) return; // Stop tracking if user is not logged in | ||
|
||
const tabs = await chrome.tabs.query({}); | ||
tabs.forEach(async (tab) => { | ||
const tabVisited = tab.url; // URL of the visited tab | ||
await trackActivity(userId, tabVisited); | ||
}); | ||
}, 10000); // Check every 10 seconds | ||
} | ||
|
||
// Function to log activity to your server | ||
async function trackActivity(userId, tabVisited) { | ||
if (tabVisited) { | ||
await fetch('https://d1af270f-5b2a-4e81-97ef-1383b66ba676-00-1an6e8o4o3ogo.worf.replit.dev/track', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ userId, tabVisited }) | ||
}); | ||
} | ||
} | ||
|
||
async function loadRules() { | ||
const response = await fetch(chrome.runtime.getURL('rules.json')); | ||
const rules = await response.json(); | ||
|
||
// Remove existing rules before adding new ones | ||
const ruleIds = rules.map(rule => rule.id); | ||
chrome.declarativeNetRequest.updateDynamicRules({ | ||
removeRuleIds: ruleIds, | ||
addRules: rules | ||
}, () => { | ||
if (chrome.runtime.lastError) { | ||
console.error("Error loading rules:", chrome.runtime.lastError); | ||
} else { | ||
console.log("Rules loaded successfully"); | ||
} | ||
}); | ||
} | ||
|
||
// Call the function to load the rules | ||
loadRules(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
document.addEventListener('DOMContentLoaded', async () => { | ||
// Check if the user is already logged in | ||
chrome.storage.local.get(['userId'], (result) => { | ||
if (result.userId) { | ||
document.getElementById('loginForm').style.display = 'none'; | ||
document.getElementById('signupForm').style.display = 'none'; | ||
document.getElementById('successMessage').style.display = 'block'; | ||
} else { | ||
document.getElementById('loginForm').style.display = 'block'; | ||
} | ||
}); | ||
|
||
// Toggle between login and signup forms | ||
document.getElementById('toggleToSignup').addEventListener('click', () => { | ||
document.getElementById('loginForm').style.display = 'none'; | ||
document.getElementById('signupForm').style.display = 'block'; | ||
}); | ||
|
||
document.getElementById('toggleToLogin').addEventListener('click', () => { | ||
document.getElementById('signupForm').style.display = 'none'; | ||
document.getElementById('loginForm').style.display = 'block'; | ||
}); | ||
|
||
// Handle login | ||
document.getElementById('loginButton').addEventListener('click', async () => { | ||
const username = document.getElementById('loginUsername').value; | ||
const password = document.getElementById('loginPassword').value; | ||
|
||
const response = await fetch('https://d1af270f-5b2a-4e81-97ef-1383b66ba676-00-1an6e8o4o3ogo.worf.replit.dev/login', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ username, password }) | ||
}); | ||
|
||
if (response.ok) { | ||
const data = await response.json(); | ||
const userId = data.userId; | ||
|
||
// Store the userId in chrome.storage | ||
chrome.storage.local.set({ userId: userId }, () => { | ||
console.log('User ID saved.'); | ||
|
||
// Hide the forms and show the success message | ||
document.getElementById('loginForm').style.display = 'none'; | ||
document.getElementById('signupForm').style.display = 'none'; | ||
document.getElementById('successMessage').style.display = 'block'; | ||
}); | ||
|
||
// Send the userId to the background script | ||
chrome.runtime.sendMessage({ action: 'login', userId: userId }); | ||
} else { | ||
alert('Login failed. Please check your credentials.'); | ||
} | ||
}); | ||
|
||
// Handle signup | ||
document.getElementById('signupButton').addEventListener('click', async () => { | ||
const username = document.getElementById('signupUsername').value; | ||
const password = document.getElementById('signupPassword').value; | ||
|
||
const response = await fetch('https://d1af270f-5b2a-4e81-97ef-1383b66ba676-00-1an6e8o4o3ogo.worf.replit.dev/register', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ username, password }) | ||
}); | ||
|
||
if (response.ok) { | ||
const data = await response.json(); | ||
const userId = data.userId; | ||
|
||
// Store the userId in chrome.storage | ||
chrome.storage.local.set({ userId: userId }, () => { | ||
console.log('User ID saved.'); | ||
|
||
// Hide the forms and show the success message | ||
document.getElementById('signupForm').style.display = 'none'; | ||
document.getElementById('successMessage').style.display = 'block'; | ||
}); | ||
|
||
// Send the userId to the background script | ||
chrome.runtime.sendMessage({ action: 'login', userId: userId }); | ||
} else { | ||
alert('Signup failed. Please try again.'); | ||
} | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"manifest_version": 3, | ||
"name": "Activity Tracker", | ||
"version": "1.0", | ||
"permissions": [ | ||
"storage", | ||
"tabs", | ||
"activeTab", | ||
"declarativeNetRequest", | ||
"declarativeNetRequestFeedback", | ||
"webRequest" | ||
], | ||
"background": { | ||
"service_worker": "background.js" | ||
}, | ||
"action": { | ||
"default_popup": "popup.html" | ||
}, | ||
"declarative_net_request": { | ||
"rule_resources": [ | ||
{ | ||
"id": "ruleset_1", | ||
"enabled": true, | ||
"path": "rules.json" | ||
} | ||
] | ||
}, | ||
"content_security_policy": { | ||
"extension_pages": "script-src 'self'; object-src 'self'" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Activity Tracker</title> | ||
<script src="main.js" defer></script> | ||
<style> | ||
body { | ||
font-family: Arial, sans-serif; | ||
margin: 20px; | ||
background-color: #f4f4f4; | ||
} | ||
.form-container { | ||
display: none; | ||
} | ||
#loginForm { | ||
display: block; | ||
} | ||
#successMessage { | ||
display: none; | ||
color: green; | ||
} | ||
#toggleForm { | ||
margin-top: 10px; | ||
cursor: pointer; | ||
color: blue; | ||
text-decoration: underline; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="loginForm" class="form-container"> | ||
<h2>Login</h2> | ||
<input type="text" id="loginUsername" placeholder="Username" required> | ||
<input type="password" id="loginPassword" placeholder="Password" required> | ||
<button id="loginButton">Login</button> | ||
<p id="toggleToSignup">Don't have an account? Sign up here.</p> | ||
</div> | ||
|
||
<div id="signupForm" class="form-container"> | ||
<h2>Sign Up</h2> | ||
<input type="text" id="signupUsername" placeholder="Username" required> | ||
<input type="password" id="signupPassword" placeholder="Password" required> | ||
<button id="signupButton">Sign Up</button> | ||
<p id="toggleToLogin">Already have an account? Login here.</p> | ||
</div> | ||
|
||
<div id="successMessage"> | ||
<h2>Welcome!</h2> | ||
<p>You are now logged in and your activity is being tracked.</p> | ||
</div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
[ | ||
{ | ||
"id": 1, | ||
"condition": { | ||
"urlFilter": "harker.org", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume these are websites that are automatically tracked? What if someone wants to change the rules or remove some? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, these are the websites that the students can open - all others are blocked. When on one of these domains, any part of the website accessed is sent to the database and is visible to the teacher on the dashboard. I'm planning to add the feature to the teacher dashboard soon where the teacher can change the allowed urls - right now its just a pre-set list. |
||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "allow" | ||
} | ||
}, | ||
{ | ||
"id": 2, | ||
"condition": { | ||
"urlFilter": "google.com", | ||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "allow" | ||
} | ||
}, | ||
{ | ||
"id": 3, | ||
"condition": { | ||
"urlFilter": "nytimes.com", | ||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "allow" | ||
} | ||
}, | ||
{ | ||
"id": 4, | ||
"condition": { | ||
"urlFilter": "replit.com", | ||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "block" | ||
} | ||
}, | ||
{ | ||
"id": 5, | ||
"condition": { | ||
"urlFilter": "membean.com", | ||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "block" | ||
} | ||
}, | ||
{ | ||
"id": 6, | ||
"condition": { | ||
"urlFilter": ".*", | ||
"resourceTypes": ["main_frame"] | ||
}, | ||
"action": { | ||
"type": "block" | ||
} | ||
} | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does it do? and why do you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part of the code loads the websites that can be accessed by the students. I put the list in a separate file because I'm planning to add a feature to the dashboard where the teacher can change the sites the students can access(like for a different class, you might need to have canva open)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Keep working on it then