6 Commits

Author SHA1 Message Date
x 3e9fe9a199 bump version to 1.3 2025-03-18 12:55:38 +01:00
x a540f1eb0a add cloudflare 2025-03-18 12:55:32 +01:00
x 940b8bbec4 fix manifest 2025-03-18 12:55:17 +01:00
x 3419544ba4 firefox approved 2025-03-17 19:49:27 +01:00
x 87b4c93268 Create PRIVACY.md 2025-03-16 11:32:29 +01:00
x feaaa65960 add showcase 2025-03-15 22:05:41 +01:00
7 changed files with 109 additions and 49 deletions
+36
View File
@@ -0,0 +1,36 @@
# Privacy Policy
**Last Updated:** 2025-03-16
Thank you for using HostInfo (the "Extension"). This Privacy Policy explains how we handle your information when you use our Extension. Please read this policy carefully to understand our practices regarding your data.
## 1. **Information We Do Not Collect**
HostInfo does not collect, store, or transmit any personal or sensitive information from its users. This includes, but is not limited to:
- Personal identification information (e.g., name, email address, phone number).
- Browsing history or activity.
- IP addresses or location data (except as described below for GeoIP lookups).
- Any other data that could be used to identify you.
## 2. **Third-Party Services**
The Extension uses the following third-party services to provide functionality:
- **Cloudflare DNS (`cloudflare-dns.com`)**: The Extension queries hostnames using Cloudflare's DNS service to resolve website IP addresses. This is done to provide accurate and fast DNS resolution. Cloudflare's privacy policy can be found [here](https://www.cloudflare.com/privacypolicy/).
- **GeoIP Lookups (`ip.albert.lol`)**: The Extension uses `ip.albert.lol` to perform GeoIP lookups. This service may receive your IP address to determine your approximate geographic location (e.g., country or region). No other personal information is shared with this service.
Neither of these services is used to collect, store, or track your personal information. The data sent to these services is used solely for the purpose of providing the Extension's functionality.
## 3. **How We Use Information**
Since we do not collect any personal information, there is no data to use, share, or sell. The Extension operates locally on your device and only communicates with the aforementioned third-party services for DNS resolution and GeoIP lookups.
## 4. **Changes to This Privacy Policy**
We may update this Privacy Policy from time to time. If we make any changes, we will update the "Last Updated" date at the top of this policy. We encourage you to review this Privacy Policy periodically to stay informed about how we are protecting your information.
## 5. **Contact Us**
If you have any questions or concerns about this Privacy Policy, please feel free to contact us at `contact@albert.lol`.
+4
View File
@@ -2,6 +2,10 @@
A browser extension built with [WXT.dev](https://wxt.dev) and React that lets you discover the origin of the website you're visiting. With a single click, you can view detailed information such as the **country of origin**, **IP address**, **ASN (Autonomous System Number)**, and more. You can also quickly search for the website's details on [Censys](https://censys.io) for deeper insights. A browser extension built with [WXT.dev](https://wxt.dev) and React that lets you discover the origin of the website you're visiting. With a single click, you can view detailed information such as the **country of origin**, **IP address**, **ASN (Autonomous System Number)**, and more. You can also quickly search for the website's details on [Censys](https://censys.io) for deeper insights.
<img src="https://github.com/user-attachments/assets/83a6316c-54b8-41a8-8d43-c794a5f62696" alt="Showcase" width="200"/>
<a href="https://addons.mozilla.org/addon/hostinfo/"><img src="https://github.com/user-attachments/assets/4e69214c-c11a-4202-919a-fac7d58dbb55" alt="Get hostinfo for Firefox"></a>
--- ---
## ✨ Features ## ✨ Features
+19 -4
View File
@@ -42,7 +42,14 @@ async function handleTabUpdate(url: string) {
const apiResponse = await fetch(`https://ip.albert.lol/${ip}`) const apiResponse = await fetch(`https://ip.albert.lol/${ip}`)
const apiData = await apiResponse.json() const apiData = await apiResponse.json()
await updateIcon(apiData.country || null) const country = apiData.country || null
const asn = apiData.org?.split(' ')[0]
let iconCode = country
if (!iconCode && asn === 'AS13335') {
iconCode = 'cloudflare'
}
await updateIcon(iconCode)
} catch (error) { } catch (error) {
console.error('Failed to handle tab update:', error) console.error('Failed to handle tab update:', error)
await updateIcon(null) await updateIcon(null)
@@ -60,7 +67,8 @@ browser.tabs.onUpdated.addListener(async (_tabId, changeInfo) => {
export default defineBackground({ export default defineBackground({
main() { main() {
browser.runtime.onMessage.addListener((request: any, _sender, sendResponse) => { browser.runtime.onMessage.addListener(
(request: any, _sender, sendResponse) => {
if (request.type === 'FETCH_SERVER_INFO') { if (request.type === 'FETCH_SERVER_INFO') {
;(async () => { ;(async () => {
try { try {
@@ -76,7 +84,13 @@ export default defineBackground({
const parsed = psl.parse(request.hostname) const parsed = psl.parse(request.hostname)
const origin = 'domain' in parsed ? parsed.domain : null const origin = 'domain' in parsed ? parsed.domain : null
await updateIcon(apiData.country) const country = apiData.country || null
const asn = apiData.org?.split(' ')[0]
let iconCode = country
if (!iconCode && asn === 'AS13335') {
iconCode = 'cloudflare'
}
await updateIcon(iconCode)
sendResponse({ sendResponse({
error: null, error: null,
@@ -102,6 +116,7 @@ export default defineBackground({
sendResponse({ error: 'Unknown request type', data: null }) sendResponse({ error: 'Unknown request type', data: null })
return true return true
}) }
)
}, },
}) })
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "hostinfo", "name": "hostinfo",
"description": "Receive information of a domain directly in the browser when browsing a website", "description": "Receive information of a domain directly in the browser when browsing a website",
"private": true, "private": true,
"version": "1.2", "version": "1.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "wxt", "dev": "wxt",
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

+7 -2
View File
@@ -1,9 +1,14 @@
export async function updateIcon(countryCode: string | null) { export async function updateIcon(countryCode: string | null) {
const validCode = let validCode
if (countryCode === 'cloudflare') {
validCode = 'cloudflare'
} else {
validCode =
countryCode?.match(/^[A-Z]{2}$/i)?.[0]?.toLowerCase() || 'unknown' countryCode?.match(/^[A-Z]{2}$/i)?.[0]?.toLowerCase() || 'unknown'
}
const loadImageBitmap = async (code: string): Promise<ImageBitmap> => { const loadImageBitmap = async (code: string): Promise<ImageBitmap> => {
const url = browser.runtime.getURL("/") const url = browser.runtime.getURL('/')
try { try {
const response = await fetch(url + `${code}.webp`) const response = await fetch(url + `${code}.webp`)
if (!response.ok) throw new Error('Flag not found') if (!response.ok) throw new Error('Flag not found')
+4 -4
View File
@@ -1,17 +1,17 @@
import { defineConfig } from 'wxt'; import { defineConfig } from 'wxt'
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from '@tailwindcss/vite'
export default defineConfig({ export default defineConfig({
extensionApi: 'webextension-polyfill', extensionApi: 'webextension-polyfill',
modules: ['@wxt-dev/module-react'], modules: ['@wxt-dev/module-react'],
manifest: { manifest: {
permissions: ['tabs', 'activeTab', 'webRequest'], permissions: ['tabs', 'activeTab', 'webRequest'],
host_permissions: ['https://ip.albert.lol/*', 'https://dns.google/*', 'https://flagcdn.com/*'], host_permissions: ['https://ip.albert.lol/*', 'https://dns.google/*'],
action: { action: {
default_title: 'Host Info', default_title: 'Host Info',
}, },
}, },
vite: () => ({ vite: () => ({
plugins: [tailwindcss()], plugins: [tailwindcss()],
}),
}) })
});