Compare commits

..

No commits in common. "991fd1318465af6334d42d9adca365047852848d" and "6efab00e75877dbf8361d51798b7dfbfa3cad09f" have entirely different histories.

7 changed files with 40 additions and 3281 deletions

View File

@ -1,15 +1,13 @@
# Bang # Unduck
*This is a fork of [unduck](https://unduck.link) by [Theo](https://github.com/t3dotgg/unduck).*
DuckDuckGo's bang redirects are too slow. Add the following URL as a custom search engine to your browser. Enables all of DuckDuckGo's bangs to work, but much faster. DuckDuckGo's bang redirects are too slow. Add the following URL as a custom search engine to your browser. Enables all of DuckDuckGo's bangs to work, but much faster.
``` ```
https://bang.gbrown.org?q=%s https://unduck.link?q=%s
``` ```
## How is it that much faster? ## How is it that much faster?
DuckDuckGo does their redirects server side. Their DNS is...not always great. Result is that it often takes ages. DuckDuckGo does their redirects server side. Their DNS is...not always great. Result is that it often takes ages.
Theo solved this by doing all of the work client side. Once you've went to https://unduck.link once, the JS is all cache'd and will never need to be downloaded again. Your device does the redirects, not me. I solved this by doing all of the work client side. Once you've went to https://unduck.link once, the JS is all cache'd and will never need to be downloaded again. Your device does the redirects, not me.

View File

@ -11,14 +11,5 @@
"devDependencies": { "devDependencies": {
"typescript": "~5.7.2", "typescript": "~5.7.2",
"vite": "^6.1.0" "vite": "^6.1.0"
},
"dependencies": {
"vite-plugin-pwa": "^0.21.1"
},
"packageManager": "pnpm@10.5.2+sha512.da9dc28cd3ff40d0592188235ab25d3202add8a207afbedc682220e4a0029ffbff4562102b9e6e46b4e3f9e8bd53e6d05de48544b0c57d4b0179e22c76d1199b",
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
} }
} }

3237
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,6 @@
// This file was (mostly) ripped from https://duckduckgo.com/bang.js // This file was (mostly) ripped from https://duckduckgo.com/bang.js
export const bangs = [ export const bangs = [
{
c: "Online Services",
d: "search.gibbyb.com",
r: 0,
s: "GibbyB",
sc: "Search",
t: "sg",
u: "https://search.gibbyb.com/?q={{{s}}}",
},
{ {
c: "AI", c: "AI",
d: "www.t3.chat", d: "www.t3.chat",
@ -19,6 +10,24 @@ export const bangs = [
t: "t3", t: "t3",
u: "https://www.t3.chat/new?q={{{s}}}", u: "https://www.t3.chat/new?q={{{s}}}",
}, },
{
c: "Tech",
d: "www.01net.com",
r: 4,
s: "01net",
sc: "Downloads (apps)",
t: "01net",
u: "http://www.01net.com/recherche/recherche.php?searchstring={{{s}}}&chaine=home",
},
{
c: "Entertainment",
d: "www.bmw2002faq.com",
r: 0,
s: "BMW 2002 FAQ",
sc: "Forum",
t: "02faq",
u: "https://www.bmw2002faq.com/search/?q={{{s}}}",
},
{ {
c: "Entertainment", c: "Entertainment",
d: "boxofficemojo.com", d: "boxofficemojo.com",
@ -93863,7 +93872,7 @@ export const bangs = [
r: 46, r: 46,
s: "Sourcegraph", s: "Sourcegraph",
sc: "Programming", sc: "Programming",
t: "srcg", t: "sg",
u: "https://sourcegraph.com/search?q={{{s}}}", u: "https://sourcegraph.com/search?q={{{s}}}",
}, },
{ {

View File

@ -89,7 +89,6 @@ textarea {
.content-container { .content-container {
max-width: 36rem; max-width: 36rem;
text-align: center; text-align: center;
padding: 0 8px;
} }
/* Update url-input width to be 100% since container will control max width */ /* Update url-input width to be 100% since container will control max width */
@ -99,7 +98,6 @@ textarea {
border-radius: 4px; border-radius: 4px;
width: 100%; width: 100%;
background: #f5f5f5; background: #f5f5f5;
text-align: center;
} }
.copy-button { .copy-button {

View File

@ -1,17 +1,20 @@
import { bangs } from "./bang"; import { bangs } from "./bang";
import "./global.css"; import "./global.css";
const defaultBang = bangs.find((b) => b.t === "g");
function noSearchDefaultPageRender() { function noSearchDefaultPageRender() {
const app = document.querySelector<HTMLDivElement>("#app")!; const app = document.querySelector<HTMLDivElement>("#app")!;
app.innerHTML = ` app.innerHTML = `
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh;"> <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh;">
<div class="content-container"> <div class="content-container">
<h1>Bang</h1> <h1>Unduck</h1>
<p>DuckDuckGo's bang redirects are too slow. Add the following URL as a custom search engine to your browser. Enables <a href="https://duckduckgo.com/bang.html" target="_blank">all of DuckDuckGo's bangs.</a></p>
<div class="url-container"> <div class="url-container">
<input <input
type="text" type="text"
class="url-input" class="url-input"
value="bang.gbrown.org?q=%s" value="https://unduck.link?q=%s"
readonly readonly
/> />
<button class="copy-button"> <button class="copy-button">
@ -19,6 +22,13 @@ function noSearchDefaultPageRender() {
</button> </button>
</div> </div>
</div> </div>
<footer class="footer">
<a href="https://t3.chat" target="_blank">t3.chat</a>
<a href="https://x.com/theo" target="_blank">theo</a>
<a href="https://github.com/t3dotgg/unduck" target="_blank">github</a>
</footer>
</div> </div>
`; `;
@ -27,7 +37,7 @@ function noSearchDefaultPageRender() {
const urlInput = app.querySelector<HTMLInputElement>(".url-input")!; const urlInput = app.querySelector<HTMLInputElement>(".url-input")!;
copyButton.addEventListener("click", async () => { copyButton.addEventListener("click", async () => {
await navigator.clipboard.writeText("https://" + urlInput.value); await navigator.clipboard.writeText(urlInput.value);
copyIcon.src = "/clipboard-check.svg"; copyIcon.src = "/clipboard-check.svg";
setTimeout(() => { setTimeout(() => {
@ -36,9 +46,6 @@ function noSearchDefaultPageRender() {
}); });
} }
const LS_DEFAULT_BANG = localStorage.getItem("default-bang") ?? "sg";
const defaultBang = bangs.find((b) => b.t === LS_DEFAULT_BANG);
function getBangredirectUrl() { function getBangredirectUrl() {
const url = new URL(window.location.href); const url = new URL(window.location.href);
const query = url.searchParams.get("q")?.trim() ?? ""; const query = url.searchParams.get("q")?.trim() ?? "";
@ -47,20 +54,19 @@ function getBangredirectUrl() {
return null; return null;
} }
const match = query.match(/!(\S+)/i); const match = query.match(/!([a-z0-9]+)/i);
const bangCandidate = match?.[1]?.toLowerCase(); const bangCandidate = match?.[1]?.toLowerCase();
const selectedBang = bangs.find((b) => b.t === bangCandidate) ?? defaultBang; const selectedBang = bangs.find((b) => b.t === bangCandidate) ?? defaultBang;
// Remove the first bang from the query // Remove the first bang from the query
const cleanQuery = query.replace(/!\S+\s*/i, "").trim(); const cleanQuery = query.replace(/![a-z0-9]+\s*/i, "").trim();
// Format of the url is: // Format of the url is:
// https://www.google.com/search?q={{{s}}} // https://www.google.com/search?q={{{s}}}
const searchUrl = selectedBang?.u.replace( const searchUrl = selectedBang?.u.replace(
"{{{s}}}", "{{{s}}}",
// Replace %2F with / to fix formats like "!ghr+t3dotgg/unduck" encodeURIComponent(cleanQuery)
encodeURIComponent(cleanQuery).replace(/%2F/g, "/")
); );
if (!searchUrl) return null; if (!searchUrl) return null;

View File

@ -1,10 +0,0 @@
import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";
export default defineConfig({
plugins: [
VitePWA({
registerType: "autoUpdate",
}),
],
});