Compare commits

...

10 Commits

Author SHA1 Message Date
991fd13184 Update README.md 2025-02-27 11:21:38 -06:00
3032a81915 Make it my own to self host 2025-02-27 11:19:34 -06:00
Theo Browne
cea48a6584
* the name 2025-02-19 03:58:47 -08:00
Theo Browne
f96ce5706d
Merge pull request #5 from samyakbardiya/fix/handle-non-alphanumeric-chars
fix: Handle non-alphanumeric characters in bangs
2025-02-15 18:16:14 -08:00
Theo Browne
5cf34e3467
Merge pull request #7 from irsyadpage/main
Add padding to .content-container
2025-02-15 18:08:35 -08:00
Theo Browne
34f64869c0
pwa because why not 2025-02-15 18:03:21 -08:00
Irsyad Aminuddin
b9763e2124
Add padding to .content-container 2025-02-15 22:22:03 +08:00
Samyak Bardiya
001e48129b
fix: update regex to handle non-alphanumeric chars 2025-02-15 18:33:21 +05:30
Theo Browne
3165c3dccb
default bang in localstorage 2025-02-14 23:33:45 -08:00
Theo Browne
0b569d2b86
hack to handle slashes 2025-02-14 23:27:00 -08:00
7 changed files with 3281 additions and 40 deletions

View File

@ -1,13 +1,15 @@
# Unduck
# Bang
*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.
```
https://unduck.link?q=%s
https://bang.gbrown.org?q=%s
```
## 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.
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.
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.

View File

@ -11,5 +11,14 @@
"devDependencies": {
"typescript": "~5.7.2",
"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,6 +1,15 @@
// This file was (mostly) ripped from https://duckduckgo.com/bang.js
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",
d: "www.t3.chat",
@ -10,24 +19,6 @@ export const bangs = [
t: "t3",
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",
d: "boxofficemojo.com",
@ -93872,7 +93863,7 @@ export const bangs = [
r: 46,
s: "Sourcegraph",
sc: "Programming",
t: "sg",
t: "srcg",
u: "https://sourcegraph.com/search?q={{{s}}}",
},
{

View File

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

View File

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

10
vite.config.ts Normal file
View File

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