"use client" import {useTheme} from "next-themes"; import Image from "next/image"; import {Feather, Search} from "lucide-react"; import {useEffect, useState} from "react"; import {Accordion, AccordionContent, AccordionItem, AccordionTrigger} from "@/components/ui/accordion"; import {Separator} from "@/components/ui/separator"; import Link from "next/link"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import {CryptoManager} from "@/lib/crypto/keys"; import UpdateKey from "@/lib/crypto/helpers/updateKey"; export default function SiPher() { const {theme, systemTheme} = useTheme(); const [mounted, setMounted] = useState(false); /** CryptoManager Alert */ const [privateKeyPresent, setPrivateKeyPresent] = useState(true); /** Consent Form states */ const [showConsentForm, setShowConsentForm] = useState(false); const [formError, setFormError] = useState(""); /** Input states */ const [inputDisabled, setInputDisabled] = useState(false); const [inputValue, setInputValue] = useState(""); /** Search expandability state */ const [isSearchExpanded, setIsSearchExpanded] = useState(false); useEffect(() => { setMounted(true); }, []); useEffect(() => { CryptoManager.getPrivateKey().then((res) => { if (!res) { console.log(res) setPrivateKeyPresent(false); } }) }, []) /** * @param search_term Either the SUUID or username (If not indexable, will return false.) */ const fetchUser = async (search_term: string) => { // Search term cannot be empty if (search_term.length <= 0) { return false; } // Sends the requisition to the API by using native fetch. const req = await fetch(`/api/user/search/user?uuid=${search_term}`); // Checks if the response is ok (200) or not, if not, returns false. if (!req.ok) { return false } const user = await req.json() as { exists: boolean }; // If the user does not exist, just return it if (!user.exists) return user.exists; setShowConsentForm(true); // Shows the confirmation to ask the other user to consent to the communication; setInputDisabled(true); // Makes the input disabled until either the user cancels the consent form or accepts it; return user.exists; // If everything went right and the user was found, return true } const sendRequest = async (user: string) => { if (user.length <= 0) { return false; } const req = await fetch(`/api/user/send/request`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ searchTerm: user, // SUUID or username }) }); if (!req.ok) { const res = await req.json(); setFormError(res.hint); return false; } const {sent} = await req.json() as { sent: boolean }; // If the user does not exist, just return it if (!sent) return sent; return sent; } const getTheme = () => { if (!mounted) return "light"; if (theme === "system") { return systemTheme === "dark" ? "dark" : "light"; } return theme === "dark" ? "dark" : "light"; }; const currentTheme = getTheme(); const MainPageAlerts = () => { return ( <> { if (!open) setFormError(""); }}> Consent Form { formError ? ( {formError} ) : null } Are you sure you want to contact {inputValue}? By continuing, {inputValue} will receive a notification to accept it. If accepted, that user will appear on your sidebar, if rejected, you will never know about it. { setShowConsentForm(false); setInputDisabled(false); }} >Cancel { sendRequest(inputValue); setInputDisabled(false); setShowConsentForm(false); }} >Continue Private Key Missing This app could not retrieve your private key, which means it's either lost, never stored or corrupted. Want to try again or insert it from a backup? You can also regenerate it if you do not have it backed up, but this would mean that you'll loose access to all old messages. { setShowConsentForm(false); setInputDisabled(false); }} >Cancel { sendRequest(inputValue).then((result) => { if (!result) setFormError("Could not send notification for whatever reason. Sorry."); }); setInputDisabled(false); }} >Try Again { UpdateKey().then((result) => { if (result.status !== 200) { return; } setPrivateKeyPresent(true) }) }} >Regenerate ) } return ( <>
SiPher

Where shadows dance and secrets nest, Silent Whisper serves as the dark sanctuary for those who value discretion above all. Born from ancient corvid traditions, this messenger’s haven ensures your whispers remain unheard by all but their intended recipients.

Like the sacred ravens of old, your messages fly through the darkness, their contents sealed by shadows and protected by forgotten wards. Each member of our dark fellowship is known only by their chosen name, their true identity shrouded in mystery.

setInputValue(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { fetchUser(inputValue).then((res) => { console.log(res); }) } }} />

F.A.Q

How does this works? Please, click here Why does this exists? I made this as a CS50X final project, hence why it is not intended for real usage. (Do not use it in a situation where you need real privacy.) Is this open-source? No, not yet (As of 11/12/2024)
); }