mirror of
https://github.com/anotherhadi/iknowyou.git
synced 2026-05-20 09:12:34 +02:00
Improve docs, responsive, add Material Icons
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
@@ -60,17 +60,19 @@
|
||||
{#each filtered as sheet}
|
||||
<a
|
||||
href={`/cheatsheets/${sheet.id}`}
|
||||
class="card bg-base-200 hover:bg-base-300 transition-colors p-4 flex flex-row items-center gap-4"
|
||||
class="card bg-base-200 hover:bg-base-300 transition-colors p-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4"
|
||||
>
|
||||
<div class="size-2 rounded-full bg-primary shrink-0"></div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-semibold text-sm">{sheet.title}</div>
|
||||
{#if sheet.description}
|
||||
<div class="text-base-content/50 text-xs mt-0.5">{sheet.description}</div>
|
||||
{/if}
|
||||
<div class="flex items-center gap-4 flex-1 min-w-0">
|
||||
<div class="size-2 rounded-full bg-primary shrink-0"></div>
|
||||
<div class="min-w-0">
|
||||
<div class="font-semibold text-sm">{sheet.title}</div>
|
||||
{#if sheet.description}
|
||||
<div class="text-base-content/50 text-xs mt-0.5">{sheet.description}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if sheet.tags && sheet.tags.length > 0}
|
||||
<div class="flex gap-1 shrink-0">
|
||||
<div class="flex flex-wrap gap-1 sm:justify-end">
|
||||
{#each sheet.tags as tag}
|
||||
<span class="badge badge-xs badge-ghost">{tag}</span>
|
||||
{/each}
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
{#if demo}
|
||||
<div class="w-full bg-warning/15 border-b border-warning/30 py-1.5 px-4 flex items-center justify-center gap-2 text-xs text-warning">
|
||||
<FlaskConical size={13} class="shrink-0" />
|
||||
<span>Demo mode — searches and configuration changes are disabled</span>
|
||||
<span>Demo mode: searches and configuration changes are disabled</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -158,8 +158,8 @@
|
||||
if (s === "found") return "Found";
|
||||
if (s === "not_found") return "Not found";
|
||||
if (s === "maybe") return "Maybe";
|
||||
if (s === "checking") return "Checking…";
|
||||
return "—";
|
||||
if (s === "checking") return "Checking...";
|
||||
return "-";
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -296,7 +296,7 @@
|
||||
{#if !userScannerAvailable}
|
||||
<div class="alert alert-warning text-sm gap-2">
|
||||
<TriangleAlert size={15} class="shrink-0" />
|
||||
<span><span class="font-mono">user-scanner</span> is not installed — email and username checking will be unavailable.</span>
|
||||
<span><span class="font-mono">user-scanner</span> is not installed, email and username checking will be unavailable.</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -414,7 +414,7 @@
|
||||
<HelpCircle size={13} /> Maybe
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-xs text-base-content/30">—</span>
|
||||
<span class="text-xs text-base-content/30">-</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
} from "@lucide/svelte";
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
let mobileMenuOpen = $state(false);
|
||||
|
||||
function onDocumentClick(e: MouseEvent) {
|
||||
if (!mobileMenuOpen) return;
|
||||
if (!(e.target as HTMLElement).closest("[data-mobile-nav]")) {
|
||||
mobileMenuOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
let {
|
||||
action,
|
||||
}: {
|
||||
@@ -46,17 +55,20 @@
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:document onclick={onDocumentClick} />
|
||||
|
||||
<div class="bg-base-200">
|
||||
<div class="navbar max-w-5xl m-auto">
|
||||
<div class="navbar-start">
|
||||
<div class="dropdown">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
|
||||
<Menu size={20} />
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="menu menu-sm dropdown-content bg-base-300 rounded-box z-50 mt-3 w-52 p-2"
|
||||
<div class="relative" data-mobile-nav>
|
||||
<button
|
||||
class="btn btn-ghost lg:hidden"
|
||||
onclick={(e) => { e.stopPropagation(); mobileMenuOpen = !mobileMenuOpen; }}
|
||||
>
|
||||
<Menu size={20} />
|
||||
</button>
|
||||
{#if mobileMenuOpen}
|
||||
<ul class="menu menu-sm absolute bg-base-300 rounded-box z-50 mt-1 w-52 p-2">
|
||||
{#each navLinks as link}
|
||||
<li>
|
||||
{#if link.children}
|
||||
@@ -64,7 +76,11 @@
|
||||
<ul class="p-2">
|
||||
{#each link.children as sublink}
|
||||
<li>
|
||||
<a href={sublink.href} class="flex items-center gap-2">
|
||||
<a
|
||||
href={sublink.href}
|
||||
class="flex items-center gap-2"
|
||||
onclick={() => (mobileMenuOpen = false)}
|
||||
>
|
||||
{#if sublink.icon}
|
||||
{@const Icon = sublink.icon}
|
||||
<Icon size={12} />
|
||||
@@ -75,7 +91,11 @@
|
||||
{/each}
|
||||
</ul>
|
||||
{:else}
|
||||
<a href={link.href} class="flex items-center gap-2">
|
||||
<a
|
||||
href={link.href}
|
||||
class="flex items-center gap-2"
|
||||
onclick={() => (mobileMenuOpen = false)}
|
||||
>
|
||||
{#if link.icon}
|
||||
{@const Icon = link.icon}
|
||||
<Icon size={12} />
|
||||
@@ -86,8 +106,9 @@
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- Logo à gauche sur écran moyen et grand -->
|
||||
<!-- Logo on medium/large screens -->
|
||||
<a
|
||||
href="/"
|
||||
class="btn btn-ghost text-xl hidden sm:flex justify-center gap-2 items-center"
|
||||
@@ -98,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<div class="navbar-center lg:flex">
|
||||
<!-- Logo centré sur petit écran (mobile) -->
|
||||
<!-- Logo centered on mobile -->
|
||||
<a
|
||||
href="/"
|
||||
class="btn btn-ghost text-xl flex sm:hidden justify-center gap-2 items-center"
|
||||
@@ -106,7 +127,7 @@
|
||||
<img src="/logo.svg" class="m-auto h-4" alt="iky logo" />
|
||||
<img src="/logo-large.svg" class="m-auto h-4" alt="iky logo large" />
|
||||
</a>
|
||||
<!-- Nav links sur grand écran -->
|
||||
<!-- Nav links on large screens -->
|
||||
<ul class="menu menu-horizontal px-1 hidden lg:flex">
|
||||
{#each navLinks as link}
|
||||
<li>
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
{#if proxies.length === 0}
|
||||
<p class="text-sm text-base-content/40">
|
||||
No proxies configured — tools will connect directly.
|
||||
No proxies configured, tools will connect directly.
|
||||
</p>
|
||||
{:else}
|
||||
{#each proxies as proxy, i}
|
||||
@@ -191,7 +191,7 @@
|
||||
<p class="text-xs text-base-content/40">
|
||||
Supported: <span class="font-mono">socks5://</span>,
|
||||
<span class="font-mono">socks4://</span>,
|
||||
<span class="font-mono">http://</span> — on failure, the next proxy is tried automatically.
|
||||
<span class="font-mono">http://</span>. On failure, the next proxy is tried automatically.
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
const DETECTORS = {
|
||||
email: (_raw, v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
|
||||
phone: (_raw, v) => /^\+\d{1,4} \d{4,}$/.test(v),
|
||||
ip: (_raw, v) => /^(\d{1,3}\.){3}\d{1,3}$/.test(v) || /^[0-9a-fA-F:]{3,39}$/.test(v),
|
||||
ip: (_raw, v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')),
|
||||
domain: (raw, v) => /^https?:\/\//.test(raw) || /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v),
|
||||
name: (_raw, v) => /^[a-zA-ZÀ-ÿ'-]+(?: [a-zA-ZÀ-ÿ'-]+){1,2}$/.test(v),
|
||||
};
|
||||
@@ -16,8 +16,8 @@
|
||||
const VALIDATORS = {
|
||||
email: { test: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v), msg: "Invalid email address" },
|
||||
username: { test: (v) => /^[a-zA-Z0-9._-]+$/.test(v), msg: "Username may only contain a-z, 0-9, . - _" },
|
||||
phone: { test: (v) => /^\+\d{1,4} \d{4,}$/.test(v), msg: "Format: +INDICATIF NUMERO (ex: +33 0612345678)" },
|
||||
ip: { test: (v) => /^(\d{1,3}\.){3}\d{1,3}$/.test(v) || /^[0-9a-fA-F:]{3,39}$/.test(v), msg: "Invalid IP address" },
|
||||
phone: { test: (v) => /^\+\d{1,4} \d{4,}$/.test(v), msg: "Format: +COUNTRYCODE NUMBER (e.g. +1 2025550147)" },
|
||||
ip: { test: (v) => /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/.test(v) || (/^[0-9a-fA-F:]{3,39}$/.test(v) && v.includes(':')), msg: "Invalid IP address" },
|
||||
domain: { test: (v) => /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(v), msg: "Invalid domain name" },
|
||||
};
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
</details>
|
||||
|
||||
{#if demo}
|
||||
<p class="text-xs text-base-content/40 italic">Results shown are not exhaustive — demo mode only displays a subset of what the tools can find.</p>
|
||||
<p class="text-xs text-base-content/40 italic">Results shown are not exhaustive: demo mode only displays a subset of what the tools can find.</p>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -406,7 +406,7 @@
|
||||
<div class="alert alert-warning py-2 px-3 text-sm gap-2">
|
||||
<AlertTriangle size={15} class="shrink-0" />
|
||||
<span>
|
||||
<strong>proxychains4</strong> not found in PATH — external binary tools
|
||||
<strong>proxychains4</strong> not found in PATH, external binary tools
|
||||
(maigret, ghunt, etc.) will <strong>not</strong> be proxied.
|
||||
Only HTTP-based tools are affected by the proxy config.
|
||||
</span>
|
||||
@@ -418,7 +418,7 @@
|
||||
{#if proxies.length === 0}
|
||||
<div class="border border-dashed border-base-300 rounded-box py-8 text-center">
|
||||
<Shield size={24} class="mx-auto mb-2 text-base-content/20" />
|
||||
<p class="text-sm text-base-content/40">No proxies — tools connect directly.</p>
|
||||
<p class="text-sm text-base-content/40">No proxies, tools connect directly.</p>
|
||||
</div>
|
||||
{:else}
|
||||
{#each proxies as proxy, i}
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
<script lang="ts">
|
||||
const { iconName = "", size=16 }: { iconName: string , size: number} = $props();
|
||||
const { iconName = "", size = 16 }: { iconName: string; size: number } = $props();
|
||||
|
||||
const genericFallbackUrl = "/Wrench.svg";
|
||||
|
||||
function resolveUrl(name: string): string {
|
||||
if (name.startsWith("mdi:")) {
|
||||
return `https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${name.slice(4)}.svg`;
|
||||
}
|
||||
if (name.startsWith("sh:")) {
|
||||
return `https://cdn.jsdelivr.net/gh/selfhst/icons/svg/${name.slice(3)}.svg`;
|
||||
}
|
||||
// si: prefix or no prefix, default to Simple Icons
|
||||
const slug = name.startsWith("si:") ? name.slice(3) : name;
|
||||
return `https://cdn.simpleicons.org/${slug}`;
|
||||
}
|
||||
|
||||
const src = $derived(iconName ? resolveUrl(iconName) : genericFallbackUrl);
|
||||
</script>
|
||||
|
||||
{#if iconName}
|
||||
<img
|
||||
src="https://cdn.simpleicons.org/{iconName}"
|
||||
alt={iconName + " icon"}
|
||||
class="opacity-50"
|
||||
width={size}
|
||||
height={size}
|
||||
style="filter: brightness(0) invert(1);"
|
||||
onerror={(e) => {
|
||||
const target = e.currentTarget as HTMLImageElement;
|
||||
target.src = genericFallbackUrl;
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<img
|
||||
src={genericFallbackUrl}
|
||||
alt={"Tool icon"}
|
||||
class="opacity-50"
|
||||
width={size}
|
||||
height={size}
|
||||
style="filter: brightness(0) invert(1);"
|
||||
/>
|
||||
{/if}
|
||||
<img
|
||||
{src}
|
||||
alt={iconName ? iconName + " icon" : "Tool icon"}
|
||||
class="opacity-50"
|
||||
width={size}
|
||||
height={size}
|
||||
style="filter: brightness(0) invert(1);"
|
||||
onerror={(e) => {
|
||||
const target = e.currentTarget as HTMLImageElement;
|
||||
target.src = genericFallbackUrl;
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -97,7 +97,7 @@ Once you have a **name**, an **email**, or a **unique username**, it’s time to
|
||||
|
||||
If you want to move from manual investigation to automated intelligence, check out [Github-Recon](https://github.com/anotherhadi/github-recon).
|
||||
Written in Go, this powerful CLI tool aggregates public OSINT data by automating the techniques mentioned above and more. Whether you start with a username or a single email address, it can retrieve SSH/GPG keys, enumerate social accounts, and find "close friends" based on interactions.
|
||||
Its standout features include a **Deep Scan** mode-which clones repositories to perform regex searches and TruffleHog secret detection—and an automated **Email Spoofing** engine that instantly identifies the account linked to any primary email address.
|
||||
Its standout features include a **Deep Scan** mode (clones repositories for regex searches and TruffleHog secret detection) and an automated **Email Spoofing** engine that identifies the account linked to any primary email address.
|
||||
|
||||
<a href="https://github.com/anotherhadi/github-recon" class="link-card" target="_blank">
|
||||
<span>
|
||||
|
||||
@@ -141,7 +141,7 @@ import Layout from "@src/layouts/Layout.astro";
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-base-content/70 text-sm leading-relaxed">
|
||||
If no proxies are configured, tools connect directly — behaviour is identical to before.
|
||||
If no proxies are configured, tools connect directly.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user