diff --git a/src/main.ts b/src/main.ts index 4452a6f4a..fb243b6ee 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,5 @@ import { bangs } from "./bang"; +import { t3Bangs } from "./t3bangs"; import "./global.css"; function noSearchDefaultPageRender() { @@ -30,59 +31,68 @@ function noSearchDefaultPageRender() { `; - const copyButton = app.querySelector(".copy-button")!; - const copyIcon = copyButton.querySelector("img")!; - const urlInput = app.querySelector(".url-input")!; + const copyButton = app.querySelector(".copy-button")!; + const copyIcon = copyButton.querySelector("img")!; + const urlInput = app.querySelector(".url-input")!; - copyButton.addEventListener("click", async () => { - await navigator.clipboard.writeText(urlInput.value); - copyIcon.src = "/clipboard-check.svg"; + copyButton.addEventListener("click", async () => { + await navigator.clipboard.writeText(urlInput.value); + copyIcon.src = "/clipboard-check.svg"; - setTimeout(() => { - copyIcon.src = "/clipboard.svg"; - }, 2000); - }); + setTimeout(() => { + copyIcon.src = "/clipboard.svg"; + }, 2000); + }); } const LS_DEFAULT_BANG = localStorage.getItem("default-bang") ?? "g"; +const LS_DEFAULT_T3_BANG = localStorage.getItem("default-t3-bang") ?? "g25f"; const defaultBang = bangs.find((b) => b.t === LS_DEFAULT_BANG); +const defaultT3Bang = t3Bangs.find((b) => b.t === LS_DEFAULT_T3_BANG); function getBangredirectUrl() { - const url = new URL(window.location.href); - const query = url.searchParams.get("q")?.trim() ?? ""; - if (!query) { - noSearchDefaultPageRender(); - return null; - } + const url = new URL(window.location.href); + const query = url.searchParams.get("q")?.trim() ?? ""; + if (!query) { + noSearchDefaultPageRender(); + return null; + } - const match = query.match(/!(\S+)/i); + const match = query.match(/!(\S+?)(?=@|\s|$)/i); + const t3Match = query.match(/@(\S+?)(?=\s|$)/i); - const bangCandidate = match?.[1]?.toLowerCase(); - const selectedBang = bangs.find((b) => b.t === bangCandidate) ?? defaultBang; + const bangCandidate = match?.[1]?.toLowerCase(); + const selectedBang = bangs.find((b) => b.t === bangCandidate) ?? defaultBang; + let selectedUrl = selectedBang?.u; + if (selectedBang?.t === "t3") { + const t3BangCandidate = t3Match?.[1]?.toLowerCase(); + const selectedT3Bang = + t3Bangs.find((b) => b.t === t3BangCandidate) ?? defaultT3Bang; + selectedUrl = selectedT3Bang?.u; + } + // Remove the first bang from the query + const cleanQuery = query.replace(/!\S+(@\S+)?\s*/i, "").trim(); - // Remove the first bang from the query - const cleanQuery = query.replace(/!\S+\s*/i, "").trim(); + // If the query is just `!gh`, use `github.com` instead of `github.com/search?q=` + if (cleanQuery === "") + return selectedBang ? `https://${selectedBang.d}` : null; - // If the query is just `!gh`, use `github.com` instead of `github.com/search?q=` - if (cleanQuery === "") - return selectedBang ? `https://${selectedBang.d}` : null; + // Format of the url is: + // https://www.google.com/search?q={{{s}}} + const searchUrl = selectedUrl?.replace( + "{{{s}}}", + // Replace %2F with / to fix formats like "!ghr+t3dotgg/unduck" + encodeURIComponent(cleanQuery).replace(/%2F/g, "/") + ); + if (!searchUrl) return null; - // Format of the url is: - // https://www.google.com/search?q={{{s}}} - const searchUrl = selectedBang?.u.replace( - "{{{s}}}", - // Replace %2F with / to fix formats like "!ghr+t3dotgg/unduck" - encodeURIComponent(cleanQuery).replace(/%2F/g, "/"), - ); - if (!searchUrl) return null; - - return searchUrl; + return searchUrl; } function doRedirect() { - const searchUrl = getBangredirectUrl(); - if (!searchUrl) return; - window.location.replace(searchUrl); + const searchUrl = getBangredirectUrl(); + if (!searchUrl) return; + window.location.replace(searchUrl); } doRedirect(); diff --git a/src/t3bangs.ts b/src/t3bangs.ts new file mode 100644 index 000000000..cc7c99b1c --- /dev/null +++ b/src/t3bangs.ts @@ -0,0 +1,52 @@ +export const t3Bangs = [ + { + m: "GPT o4 Mini", + t: "o4m", + u: "https://t3.chat/new?model=gpt-o4-mini&q={{{s}}}", + }, + { + m: "Gemini 2.5 Flash", + t: "g25f", + u: "https://t3.chat/new?model=gemini-2.5-flash&q={{{s}}}", + }, + { + m: "Gemini 2.5 Flash Lite", + t: "g25fl", + u: "https://t3.chat/new?model=gemini-2.5-flash-lite&q={{{s}}}", + }, + { + m: "Gemini 2.5 Pro", + t: "g25p", + u: "https://t3.chat/new?model=gemini-2.5-pro&q={{{s}}}", + }, + { + m: "Gemini Imagen 4", + t: "gi4", + u: "https://t3.chat/new?model=gemini-imagen-4&q={{{s}}}", + }, + { + m: "Gemini Imagen 4 Ultra", + t: "gi4u", + u: "https://t3.chat/new?model=gemini-imagen-4-ultra&q={{{s}}}", + }, + { + m: "GPT ImageGen", + t: "gpti", + u: "https://t3.chat/new?model=gpt-image-1&q={{{s}}}", + }, + { + m: "Claude 4 Sonnet", + t: "c4s", + u: "https://t3.chat/new?model=claude-4-sonnet&q={{{s}}}", + }, + { + m: "Claude 4 Sonnet (Reasoning)", + t: "c4sr", + u: "https://t3.chat/new?model=claude-4-sonnet-reasoning&q={{{s}}}", + }, + { + m: "Deepseek R1", + t: "r1", + u: "https://t3.chat/new?model=deepseek-r1-groq&q={{{s}}}", + }, +];