Files
eleakxir/front/src/routes/search/[id]/index.svelte

236 lines
7.8 KiB
Svelte

<script lang="ts">
import type { Result } from "$src/lib/types";
import axios from "axios";
import { navigate, route } from "sv-router/generated";
import { serverPassword, serverUrl } from "$src/lib/stores/server";
import Searchbar from "$src/lib/components/index/search/searchbar.svelte";
import { toast } from "svelte-sonner";
import { onMount } from "svelte";
import Stats from "$src/lib/components/index/search/id/stats.svelte";
import Rows from "$src/lib/components/index/search/id/rows.svelte";
import {
ChevronDown,
CircleAlert,
CircleCheck,
CircleMinus,
CircleX,
Database,
Github,
} from "@lucide/svelte";
import { convertNanoSeconds } from "$src/lib/utils";
import GithubResult from "$src/lib/components/index/search/id/githubResult.svelte";
route.getParams("/search/:id");
let { id } = route.params;
let result = $state<Result | null>(null);
function loadData() {
if (id === undefined) {
return;
}
if (id === "") {
return;
}
axios
.get(`${$serverUrl}/search/${id}`, {
headers: {
"X-Password": $serverPassword,
},
})
.then((r) => {
result = r.data;
console.log(r.data);
if (result && result.Status !== "pending") {
clearInterval(intervalId);
}
})
.catch((e) => {
toast.error("Failed to fetch search result!");
clearInterval(intervalId);
navigate("/search");
});
}
let intervalId: ReturnType<typeof setInterval>;
let elapsedTime = 0;
let pollingInterval = 10000; // Start with a 10-second interval
onMount(() => {
if ($serverUrl === "") {
toast.error("Please, configure your server first!");
navigate("/");
return;
}
loadData();
intervalId = setInterval(() => {
elapsedTime += pollingInterval;
// Check for status change inside the interval
if (result && result.Status !== "pending") {
clearInterval(intervalId);
return;
}
// Change polling frequency based on elapsed time
if (elapsedTime >= 120000 && pollingInterval !== 10000) {
clearInterval(intervalId);
pollingInterval = 15000;
intervalId = setInterval(loadData, pollingInterval);
return;
} else if (elapsedTime >= 600000 && pollingInterval !== 30000) {
clearInterval(intervalId);
pollingInterval = 30000;
intervalId = setInterval(loadData, pollingInterval);
return;
}
loadData();
}, pollingInterval);
return () => {
clearInterval(intervalId);
};
});
</script>
<main>
{#if result}
<header class="flex gap-5 flex-col">
<a href="/search">
<h1 class="h1"><span class="text-2xl align-middle">🔍</span> Search</h1>
</a>
<Searchbar
initialQuery={result.Query.Text}
initialFilter={result.Query.Column}
initialExactMatch={result.Query.ExactMatch}
/>
</header>
<div class="my-10"></div>
<div class="grid grid-cols-1 gap-5 [&>div]:border-neutral">
<div class="card card-border shadow col-span-full">
<Stats {result} />
</div>
<div class="collapse collapse-arrow bg-base-100 border">
<input type="radio" name="my-accordion-2" checked={true} />
<div
class="collapse-title font-semibold text-xl flex justify-between items-center"
>
<div class="flex items-center gap-2">
<Database size={18} class="text-base-content/60" />
Data wells lookup
</div>
{#if result.LeakResult.Error !== ""}
<CircleX size={16} class="text-error" />
{:else if result.LeakResult.Duration === 0}
<span class="loading loading-dots loading-xs"></span>
{:else if result.LeakResult.Rows.length > 0}
<CircleCheck size={16} class="text-success" />
{:else}
<CircleMinus size={16} class="text-base-content/60" />
{/if}
</div>
<div class="collapse-content">
{#if result.LeakResult.Error !== ""}
<div role="alert" class="alert alert-soft alert-error">
<CircleAlert size={20} />
<span>Error! {result.LeakResult.Error}</span>
</div>
{:else if result.LeakResult.Duration === 0}
<ul class="list rounded-box">
{#each Array(5) as _}
<div class="list-row text-left">
<div>
<div
class="skeleton size-10 rounded-box items-center justify-center flex"
></div>
</div>
<div>
<div class="skeleton h-5 mb-1 w-52"></div>
<div
class="text-xs skeleton h-4 w-34 uppercase font-semibold opacity-60"
></div>
</div>
<div class="btn btn-square btn-ghost">
<ChevronDown size={12} />
</div>
</div>
{/each}
</ul>
{:else}
<p class="text-base-content/60">
{result.LeakResult.Rows.length} results in {convertNanoSeconds(
result.LeakResult.Duration,
)}
</p>
{#if result.LeakResult.LimitHit}
<div role="alert" class="alert alert-soft my-4">
<CircleAlert size={20} />
<div>
<span class="font-semibold">Limit hit!</span> Consider refining
your search query for more specific results.
</div>
</div>
{/if}
<Rows {result} />
{/if}
</div>
</div>
<div class="collapse collapse-arrow bg-base-100 border">
<input type="radio" name="my-accordion-2" />
<div
class="collapse-title font-semibold text-xl flex justify-between items-center"
>
<div class="flex items-center gap-2">
<Github size={18} class="text-base-content/60" />
Github Recon
</div>
{#if result.GithubResult.Error !== ""}
<CircleX size={16} class="text-error" />
{:else if result.GithubResult.Duration === 0}
<span class="loading loading-dots loading-xs"></span>
{:else if !result.GithubResult.EmailResult?.Commits && !result.GithubResult.EmailResult?.Spoofing && !result.GithubResult.UsernameResult?.User}
<CircleMinus size={16} class="text-base-content/60" />
{:else if result.GithubResult.UsernameResult || result.GithubResult.EmailResult}
<CircleCheck size={16} class="text-success" />
{/if}
</div>
<div class="collapse-content">
{#if result.GithubResult.Error !== ""}
<div role="alert" class="alert alert-soft alert-error">
<CircleAlert size={20} />
<span>Error! {result.GithubResult.Error}</span>
</div>
{:else if result.GithubResult.Duration === 0}
<div role="alert" class="alert alert-soft">
<span class="loading loading-dots loading-sm"></span>
<span>Loading...</span>
</div>
{:else if !result.GithubResult.EmailResult?.Commits && !result.GithubResult.EmailResult?.Spoofing && !result.GithubResult.UsernameResult?.User}
<div role="alert" class="alert alert-soft">
<CircleMinus size={20} />
<span>No result</span>
</div>
{:else}
<p class="text-base-content/60 mb-4">
Found a result in {convertNanoSeconds(
result.GithubResult.Duration,
)}
</p>
<GithubResult githubResult={result.GithubResult} />
{/if}
</div>
</div>
</div>
{/if}
<div class="mb-10"></div>
</main>