init
This commit is contained in:
226
front/src/routes/search/[id]/index.svelte
Normal file
226
front/src/routes/search/[id]/index.svelte
Normal file
@@ -0,0 +1,226 @@
|
||||
<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>
|
||||
<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>
|
||||
Reference in New Issue
Block a user