-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat(Hackviser): add activity #10579
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
Changes from 11 commits
7f08e4c
7b498a9
9916b1d
10ea68e
2b5ee86
9bf1fa8
43daea3
f6c4919
c4e8c9d
e057b05
e286237
09589b0
66c2f03
e3022a1
ec41f2c
4c096f8
a74f427
5bf3e14
8d5922a
5724b39
8fdbeb6
a00c784
cf8b55a
49781b3
750bc98
20e780f
7a62efb
1648036
ddd6d1b
a252a37
355a0e1
364a809
5f3011f
cf82ac3
3dd8b59
035aa54
eb7ee2e
307959c
23c56e4
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,27 @@ | ||||||
| { | ||||||
| "$schema": "https://schemas.premid.app/metadata/1.16", | ||||||
| "apiVersion": 1, | ||||||
| "author": { | ||||||
| "id": "378501743366897675", | ||||||
| "name": "hackviser" | ||||||
| }, | ||||||
| "service": "Hackviser", | ||||||
| "description": { | ||||||
| "en": "Hackviser is an online cybersecurity training platform where you can practice hacking skills through labs, CTF challenges, learning paths, and real-world scenarios.", | ||||||
| "tr": "Hackviser, laboratuvarlar, CTF yarışmaları, öğrenme yolları ve gerçek dünya senaryoları aracılığıyla siber güvenlik becerilerinizi geliştirebileceğiniz çevrimiçi bir eğitim platformudur." | ||||||
| }, | ||||||
| "url": "hackviser.com", | ||||||
| "regExp": "([a-zA-Z0-9-]+\\.)*hackviser\\.com", | ||||||
efekrbas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| "regExp": "([a-zA-Z0-9-]+\\.)*hackviser\\.com", | |
| "regExp": "^https?[:][/][/]([a-zA-Z0-9-]+[.])*hackviser[.]com[/]", |
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.
Is there anything else I need to correct? @Bas950
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.
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
Fixed
Show fixed
Hide fixed
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,301 @@ | ||
| const presence = new Presence({ | ||
| clientId: '1476565376513999030', | ||
| }) | ||
|
|
||
| let startTimestamp = Math.floor(Date.now() / 1000) | ||
| let lastPage = '' | ||
|
|
||
| /** | ||
| * Converts a URL slug into a human-readable title. | ||
| * e.g. "my-cool-lab" → "My Cool Lab" | ||
| */ | ||
| function extractPageTitle(pathname: string): string | null { | ||
| const parts = pathname.split('/').filter((p) => p.length > 0) | ||
|
||
| if (parts.length >= 2) { | ||
| const slug = parts[parts.length - 1] || '' | ||
| return slug | ||
|
||
| .replace(/[-_]/g, ' ') | ||
| .replace(/\b\w/g, (l) => l.toUpperCase()) | ||
|
||
| } | ||
| return null | ||
| } | ||
|
|
||
| /** | ||
| * Determines page info from the current pathname. | ||
| * Ported from the Chrome extension's parseHackviserUrl() logic. | ||
| */ | ||
| function getPageData(pathname: string): { | ||
| page: string, | ||
|
||
| details: string, | ||
|
||
| state: string, | ||
|
||
| sensitive: boolean, | ||
|
||
| } { | ||
| // ── Auth pages (sensitive) ────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/login') | ||
| || pathname.startsWith('/register') | ||
| || pathname.startsWith('/forgot') | ||
| || pathname.startsWith('/reset') | ||
| ) { | ||
| return { | ||
| page: 'login', | ||
| details: 'Logging In', | ||
| state: '', | ||
| sensitive: true, | ||
| } | ||
| } | ||
|
|
||
| // ── Home ──────────────────────────────────────────────────── | ||
| if (pathname.startsWith('/home') || pathname === '/') { | ||
| return { | ||
| page: 'home', | ||
| details: 'Home Page', | ||
| state: 'Viewing Home Page', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Dashboard ─────────────────────────────────────────────── | ||
| if (pathname.startsWith('/dashboard')) { | ||
| return { | ||
| page: 'dashboard', | ||
| details: 'Dashboard', | ||
| state: 'Viewing Stats', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Academy ───────────────────────────────────────────────── | ||
| if (pathname.startsWith('/academy')) { | ||
| const subPage = extractPageTitle(pathname) | ||
| return { | ||
| page: 'academy', | ||
| details: 'Academy', | ||
| state: subPage || 'Browsing Categories', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Warmups ───────────────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/warmups') | ||
| || pathname.startsWith('/warmup') | ||
| ) { | ||
| const name = extractPageTitle(pathname) | ||
| return { | ||
| page: 'warmups', | ||
| details: 'Warmups', | ||
| state: name || 'Warming Up...', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Scenarios ─────────────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/scenarios') | ||
| || pathname.startsWith('/scenario') | ||
| ) { | ||
| const name = extractPageTitle(pathname) | ||
| return { | ||
| page: 'scenarios', | ||
| details: 'Scenarios', | ||
| state: name || 'Running Scenario', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Missions ──────────────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/missions') | ||
| || pathname.startsWith('/mission') | ||
| ) { | ||
| const name = extractPageTitle(pathname) | ||
| return { | ||
| page: 'missions', | ||
| details: 'Missions', | ||
| state: name || 'On a Mission', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Certifications ────────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/certifications') | ||
| || pathname.startsWith('/certification') | ||
| ) { | ||
| const name = extractPageTitle(pathname) | ||
| return { | ||
| page: 'certifications', | ||
| details: 'Certifications', | ||
| state: name || 'Viewing Certifications', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Labs / Machines ───────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/labs') | ||
| || pathname.startsWith('/lab') | ||
| || pathname.startsWith('/machines') | ||
| ) { | ||
| const labName = extractPageTitle(pathname) | ||
| return { | ||
| page: 'labs', | ||
| details: 'Solving Labs', | ||
| state: labName || 'Hacking in Progress...', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Support ───────────────────────────────────────────────── | ||
| if (pathname.startsWith('/support')) { | ||
| return { | ||
| page: 'support', | ||
| details: 'Support', | ||
| state: 'Getting Support', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Learning Paths / Courses ──────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/learning') | ||
| || pathname.startsWith('/paths') | ||
| || pathname.startsWith('/courses') | ||
| ) { | ||
| return { | ||
| page: 'learning', | ||
| details: 'Learning Paths', | ||
| state: 'Studying Cyber Security', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── CTF / Challenges ──────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/ctf') | ||
| || pathname.startsWith('/challenges') | ||
| ) { | ||
| return { | ||
| page: 'ctf', | ||
| details: 'CTF Challenge', | ||
| state: 'Capturing Flags', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Account Settings ──────────────────────────────────────── | ||
| if (pathname.startsWith('/account/settings')) { | ||
| return { | ||
| page: 'settings', | ||
| details: 'Settings', | ||
| state: 'A few changes', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Pricing Plans ─────────────────────────────────────────── | ||
| if (pathname.startsWith('/pricing-plans')) { | ||
| return { | ||
| page: 'pricing', | ||
| details: 'Pricing Plans', | ||
| state: 'Looking Pricing Plans', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── FAQ ───────────────────────────────────────────────────── | ||
| if (pathname.startsWith('/frequently-asked-questions')) { | ||
| return { | ||
| page: 'faq', | ||
| details: 'Frequently Asked Questions', | ||
| state: 'Is looking for answers to the questions on his mind', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Profile / User ────────────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/profile') | ||
| || pathname.startsWith('/user') | ||
| || pathname.startsWith('/settings') | ||
| ) { | ||
| return { | ||
| page: 'profile', | ||
| details: 'Profile', | ||
| state: 'Viewing Profile', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Leaderboard / Rankings ────────────────────────────────── | ||
| if ( | ||
| pathname.startsWith('/leaderboard') | ||
| || pathname.startsWith('/scoreboard') | ||
| || pathname.startsWith('/ranking') | ||
| ) { | ||
| return { | ||
| page: 'leaderboard', | ||
| details: 'Leaderboard', | ||
| state: 'Checking Rankings', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Ticket ────────────────────────────────────────────────── | ||
| if (pathname.startsWith('/ticket')) { | ||
| return { | ||
| page: 'ticket', | ||
| details: 'Ticket', | ||
| state: 'Viewing Ticket', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Default: browsing ─────────────────────────────────────── | ||
| return { | ||
| page: 'browsing', | ||
| details: 'Browsing Platform', | ||
| state: '', | ||
| sensitive: false, | ||
| } | ||
| } | ||
|
|
||
| // ── Main update loop ──────────────────────────────────────────── | ||
| presence.on('UpdateData', async () => { | ||
| const pathname = document.location.pathname | ||
|
||
| const pageData = getPageData(pathname) | ||
|
|
||
| // Reset timer when the page changes | ||
| if (pageData.page !== lastPage) { | ||
| startTimestamp = Math.floor(Date.now() / 1000) | ||
| lastPage = pageData.page | ||
| } | ||
|
|
||
| const presenceData: PresenceData = { | ||
|
||
| startTimestamp, | ||
| } | ||
|
|
||
| // Sensitive pages: only show "Logging In", hide details | ||
| if (pageData.sensitive) { | ||
| presenceData.details = pageData.details | ||
|
||
| } | ||
| else { | ||
| if (pageData.details) { | ||
| presenceData.details = pageData.details | ||
|
||
| } | ||
| if (pageData.state) { | ||
| presenceData.state = pageData.state | ||
|
||
| } | ||
| } | ||
|
|
||
| // Buttons | ||
| presenceData.buttons = [ | ||
|
||
| { | ||
| label: 'Learn Cybersecurity', | ||
| url: 'https://hackviser.com/', | ||
| }, | ||
|
||
| ] | ||
|
|
||
| presence.setActivity(presenceData) | ||
|
||
| }) | ||

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.
Remove image assets from PR
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.
I removed