Compare commits
10 Commits
6efab00e75
...
991fd13184
Author | SHA1 | Date | |
---|---|---|---|
991fd13184 | |||
3032a81915 | |||
|
cea48a6584 | ||
|
f96ce5706d | ||
|
5cf34e3467 | ||
|
34f64869c0 | ||
|
b9763e2124 | ||
|
001e48129b | ||
|
3165c3dccb | ||
|
0b569d2b86 |
@ -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.
|
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?
|
## 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.
|
||||||
|
|
||||||
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.
|
||||||
|
@ -11,5 +11,14 @@
|
|||||||
"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
3237
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
29
src/bang.ts
29
src/bang.ts
@ -1,6 +1,15 @@
|
|||||||
// 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",
|
||||||
@ -10,24 +19,6 @@ 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",
|
||||||
@ -93872,7 +93863,7 @@ export const bangs = [
|
|||||||
r: 46,
|
r: 46,
|
||||||
s: "Sourcegraph",
|
s: "Sourcegraph",
|
||||||
sc: "Programming",
|
sc: "Programming",
|
||||||
t: "sg",
|
t: "srcg",
|
||||||
u: "https://sourcegraph.com/search?q={{{s}}}",
|
u: "https://sourcegraph.com/search?q={{{s}}}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -89,6 +89,7 @@ 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 */
|
||||||
@ -98,6 +99,7 @@ textarea {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button {
|
.copy-button {
|
||||||
|
26
src/main.ts
26
src/main.ts
@ -1,20 +1,17 @@
|
|||||||
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>Unduck</h1>
|
<h1>Bang</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="https://unduck.link?q=%s"
|
value="bang.gbrown.org?q=%s"
|
||||||
readonly
|
readonly
|
||||||
/>
|
/>
|
||||||
<button class="copy-button">
|
<button class="copy-button">
|
||||||
@ -22,13 +19,6 @@ 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>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -37,7 +27,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(urlInput.value);
|
await navigator.clipboard.writeText("https://" + urlInput.value);
|
||||||
copyIcon.src = "/clipboard-check.svg";
|
copyIcon.src = "/clipboard-check.svg";
|
||||||
|
|
||||||
setTimeout(() => {
|
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() {
|
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() ?? "";
|
||||||
@ -54,19 +47,20 @@ function getBangredirectUrl() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = query.match(/!([a-z0-9]+)/i);
|
const match = query.match(/!(\S+)/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(/![a-z0-9]+\s*/i, "").trim();
|
const cleanQuery = query.replace(/!\S+\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}}}",
|
||||||
encodeURIComponent(cleanQuery)
|
// Replace %2F with / to fix formats like "!ghr+t3dotgg/unduck"
|
||||||
|
encodeURIComponent(cleanQuery).replace(/%2F/g, "/")
|
||||||
);
|
);
|
||||||
if (!searchUrl) return null;
|
if (!searchUrl) return null;
|
||||||
|
|
||||||
|
10
vite.config.ts
Normal file
10
vite.config.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { defineConfig } from "vite";
|
||||||
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
VitePWA({
|
||||||
|
registerType: "autoUpdate",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user