├── .gitignore
├── LICENSE.md
├── Procfile
├── README.md
├── app.js
├── package.json
├── public
├── images
│ ├── bodybg.png
│ └── favicon.ico
├── opensearch.xml
├── opensearchsuggest.xml
└── stylesheets
│ └── style.css
└── views
├── browser.jade
├── index.jade
├── layout.jade
└── privacy.jade
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | node_modules
15 | npm-debug.log
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) Mike Crittenden
2 |
3 | ### MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: node app.js
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### OUTDATED: USE https://github.com/JadoJodo/duckduckgoog NOW
2 |
3 | duckduckgoog
4 | ============
5 |
6 | Use DuckDuckGo for !bangs and Google for everything else
7 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | http = require('http');
3 |
4 | var app = express();
5 |
6 | app.configure(function(){
7 | app.set('port', process.env.PORT || 3000);
8 | app.set('view engine', 'jade');
9 | app.use(express.favicon(__dirname + '/public/images/favicon.ico'));
10 | app.use(express.bodyParser());
11 | app.use(express.methodOverride());
12 | app.use(app.router);
13 | app.use(express.static(__dirname + '/public'));
14 | });
15 |
16 | app.configure('development', function(){
17 | app.use(express.errorHandler());
18 | app.use(express.logger('dev'));
19 | });
20 |
21 | app.configure('production', function(){
22 | app.use(express.errorHandler());
23 | app.use(express.logger());
24 | });
25 |
26 | app.get('/', function(req, res) {
27 | if (req.query["q"]) {
28 | query = req.query["q"];
29 | encQuery = encodeURIComponent(query);
30 |
31 | if (query.match(/![A-Za-z0-9]+/) || query.substring(0, 2) === "! " || query.substring(0, 1) === "\\") {
32 |
33 | console.log('Queried DuckDuckGo');
34 | res.redirect('https://duckduckgo.com?q=' + encQuery);
35 |
36 | } else if (req.query['searchengine']) {
37 |
38 | console.log('Queried custom search engine');
39 | searchEngine = req.query['searchengine'];
40 | if (searchEngine.search() != -1 && (searchEngine.lastIndexOf('http://', 0) === 0 || searchEngine.lastIndexOf('https://', 0) === 0)) {
41 | customSearchURL = searchEngine.replace(/%q/g, encQuery);
42 | res.redirect(customSearchURL);
43 | } else {
44 | console.log('Error in search engine syntax. Using Google.');
45 | res.redirect('https://www.google.com/search?q=' + encQuery);
46 | }
47 |
48 | } else {
49 |
50 | console.log('Queried Google');
51 | if (req.query['google']) {
52 | res.redirect('https://' + req.query['google'] + '/search?q=' + encQuery);
53 | } else {
54 | res.redirect('https://www.google.com/search?q=' + encQuery);
55 | }
56 |
57 | }
58 | }
59 | res.render('index');
60 | });
61 |
62 | app.get('/browser', function(req, res) {
63 | res.render('browser');
64 | });
65 |
66 | app.get('/privacy', function(req, res) {
67 | res.render('privacy');
68 | });
69 |
70 | http.createServer(app).listen(app.get('port'), function(){
71 | console.log("Express server listening on port " + app.get('port'));
72 | });
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "duckduckgoog",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node app"
7 | },
8 | "dependencies": {
9 | "express": "3.0.0",
10 | "jade": "*"
11 | },
12 | "engines": {
13 | "node": "8.1.4"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/public/images/bodybg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/crittermike/duckduckgoog/4c626318081b56983e6e64958d2d8561e0cbc379/public/images/bodybg.png
--------------------------------------------------------------------------------
/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/crittermike/duckduckgoog/4c626318081b56983e6e64958d2d8561e0cbc379/public/images/favicon.ico
--------------------------------------------------------------------------------
/public/opensearch.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | DuckDuckGoog
4 | DuckDuckGoog Web Search
5 | DuckDuckGoog passes !bang's to DuckDuckGo and everything else to Google
6 | UTF-8
7 | UTF-8
8 | false
9 | en-us
10 | Mike Crittenden
11 | mikecrittenden@gmail.com
12 | duckduckgo google search
13 | DuckDuckGo and Google
14 | open
15 |
16 | http://www.duckduckgoog.com/favicon.ico
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/public/opensearchsuggest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | DuckDuckGoog With Suggestions
4 | DuckDuckGoog Web Search With Google Search Suggestions
5 | DuckDuckGoog passes !bang's to DuckDuckGo and everything else to Google
6 | UTF-8
7 | UTF-8
8 | false
9 | en-us
10 | Mike Crittenden
11 | mikecrittenden@gmail.com
12 | duckduckgo google search
13 | DuckDuckGo and Google
14 | open
15 |
16 | http://www.duckduckgoog.com/favicon.ico
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | text-align: center;
3 | background: transparent url(../images/bodybg.png) repeat;
4 | font-family: 'Belgrano', serif;
5 | color: #888;
6 | }
7 | a {
8 | color: #888;
9 | }
10 | a:hover {
11 | color: #D83C3C;
12 | }
13 | code {
14 | color: black;
15 | }
16 | #container {
17 | width: 470px;
18 | margin: 30px auto 0;
19 | text-align: left;
20 | }
21 | #container h1 {
22 | text-align: center;
23 | }
24 | #search-container {
25 | position: absolute;
26 | top: 50%;
27 | left: 50%;
28 | margin-top: -150px;
29 | margin-left: -246px;
30 | }
31 | #search-container p {
32 | margin-top: 45px;
33 | }
34 | h1 {
35 | color: #222;
36 | font-weight: normal;
37 | font-size: 60px;
38 | margin-top: 0;
39 | }
40 | form#search-form:before, form#search-form:after {
41 | content:"";
42 | display:table;
43 | }
44 | form#search-form:after {
45 | clear:both;
46 | }
47 | form#search-form {
48 | zoom:1;
49 | width: 450px;
50 | padding: 15px;
51 | margin: 0 auto;
52 | background: #444;
53 | background: rgba(0,0,0,.2);
54 | -moz-border-radius: 10px;
55 | -webkit-border-radius: 10px;
56 | border-radius: 10px;
57 | -moz-box-shadow: 0 1px 1px rgba(0,0,0,.4) inset, 0 1px 0 rgba(255,255,255,.2);
58 | -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.4) inset, 0 1px 0 rgba(255,255,255,.2);
59 | box-shadow: 0 1px 1px rgba(0,0,0,.4) inset, 0 1px 0 rgba(255,255,255,.2);
60 | }
61 | form#search-form input {
62 | font-family: 'Belgrano', serif;
63 | width: 330px;
64 | height: 20px;
65 | padding: 10px 5px;
66 | float: left;
67 | font-size: 15px;
68 | border: 0;
69 | background: #eee;
70 | -moz-border-radius: 3px 0 0 3px;
71 | -webkit-border-radius: 3px 0 0 3px;
72 | border-radius: 3px 0 0 3px;
73 | }
74 | form#search-form input:focus {
75 | outline: 0;
76 | background: #fff;
77 | -moz-box-shadow: 0 0 2px rgba(0,0,0,.8) inset;
78 | -webkit-box-shadow: 0 0 2px rgba(0,0,0,.8) inset;
79 | box-shadow: 0 0 2px rgba(0,0,0,.8) inset;
80 | }
81 | form#search-form input::-webkit-input-placeholder {
82 | color: #999;
83 | font-weight: normal;
84 | font-style: italic;
85 | }
86 | form#search-form input:-moz-placeholder {
87 | color: #999;
88 | font-weight: normal;
89 | font-style: italic;
90 | }
91 | form#search-form input:-ms-input-placeholder {
92 | color: #999;
93 | font-weight: normal;
94 | font-style: italic;
95 | }
96 | form#search-form button {
97 | overflow: visible;
98 | position: relative;
99 | float: right;
100 | border: 0;
101 | padding: 0;
102 | cursor: pointer;
103 | height: 40px;
104 | width: 110px;
105 | font: bold 15px/40px 'Belgrano', serif;
106 | color: #fff;
107 | text-transform#search-form: uppercase;
108 | background: #d83c3c;
109 | -moz-border-radius: 0 3px 3px 0;
110 | -webkit-border-radius: 0 3px 3px 0;
111 | border-radius: 0 3px 3px 0;
112 | text-shadow: 0 -1px 0 rgba(0, 0 ,0, .3);
113 | }
114 | form#search-form button:hover{
115 | background: #e54040;
116 | }
117 | form#search-form button:active,
118 | form#search-form button:focus{
119 | background: #c42f2f;
120 | }
121 | form#search-form button:before {
122 | content: '';
123 | position: absolute;
124 | border-width: 8px 8px 8px 0;
125 | border-style: solid solid solid none;
126 | border-color: transparent #d83c3c transparent;
127 | top: 12px;
128 | left: -6px;
129 | }
130 | form#search-form button:hover:before{
131 | border-right-color: #e54040;
132 | }
133 | form#search-form button:focus:before{
134 | border-right-color: #c42f2f;
135 | }
136 | form#search-form button::-moz-focus-inner {
137 | border: 0;
138 | padding: 0;
139 | }
140 | #footer {
141 | position: absolute;
142 | bottom: 0;
143 | text-align: center;
144 | width: 100%;
145 | left: 0;
146 | opacity: 0.4;
147 | background: white;
148 | border-top: 1px solid #ccc;
149 | }
150 | #footer:hover {
151 | opacity: 1;
152 | }
153 |
--------------------------------------------------------------------------------
/views/browser.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | #container
5 | h1 DuckDuckGoog
6 | h2 Set your default browser search!
7 | hr
8 | h3 Chrome
9 | p
10 | strong Without Search Suggestions
11 | p Just by visiting the site, Chrome should have already stored it as a search engine. Just go to Chrome's search engine settings and find duckduckgoog.com in that list, then click "Make Default" next to it.
12 | p
13 | strong With Search Suggestions
14 | p Unfortunately Chrome can't auto-discover more than one search per site, so if you want to use search suggestions, click
15 | a(href='#', onclick='window.external.AddSearchProvider("http://duckduckgoog.com/opensearchsuggest.xml");') this link
16 | | . Note that after doing so you'll probably want to go into Chrome's search engine options to set it as the default search by clicking "Make Default" next to it.
17 | hr
18 |
19 | h3 Firefox
20 | p
21 | strong Search Bar
22 | p Click the little dropdown arrow in the Firefox search bar, then click "Add DuckDuckGoog" to save it--note that you can choose to use search suggestions or not. You might have to click it again to make it your default.
23 | p
24 | strong Awesomebar
25 | p Visit
26 | a(href="http://kb.mozillazine.org/Location_Bar_search#Location_Bar_search_.28external_-_search_engine.29") this page with instructions
27 | | and use the following URL as the search string (or see below if you want to use a localized Google URL):
28 | code http://www.duckduckgoog.com?q=
29 | br
30 | br
31 | hr
32 |
33 | h3 Other Browsers & Launchers
34 | p DuckDuckGoog should be easy to add to any browser or launcher (Alfred, GnomeDo, etc.) that supports custom searches.
35 | p Just use this search string in your browser/launcher's search engine options to create a custom search:
36 | code http://www.duckduckgoog.com?q=SEARCH
37 | p (Replace SEARCH with whatever your browser/launcher expects the placeholder to be).
38 |
39 | hr
40 | h3 Using a different (localized) Google URL
41 | p If you would rather make DuckDuckGoog search google.com.au or google.co.jp etc., than the default encrypted.google.com, then just include that in your search URL, using something like
42 | code http://www.duckduckgoog.com?q=searchstring&google=custom-google-url.com
43 | p For example, if you use Chrome and want to default your Google search to Google Japan, use this:
44 | code http://www.duckduckgoog.com?q=%s&google=google.co.jp
45 | p Note that if you use Firefox, you don't have the option to manually change search engine URLs like that, so you'll need to install an addon of something like
46 | a(href='http://mycroft.mozdev.org/index.html') Mycroft
47 | | that allows you to do this.
48 |
49 | hr
50 | h3 Using a custom search engine
51 | p If you would like to use another search engine other than google (Like Bing or Yahoo), simply put the url and a
52 | code %q
53 | | where the search goes, like so:
54 | code http://www.duckduckgoog.com?q=searchstring&searchengine=http://searchengine.com?query=%q
55 | p For example, if you use Chrome and want to default your search to Yahoo, use this:
56 | code http://www.duckduckgoog.com?q=%s&searchengine=http://search.yahoo.com/search?q=%q
57 | p Make sure to put the
58 | code http://
59 | | or the
60 | code https://
61 | | before the URL.
62 | p Also be aware that DuckDuckGoog will default to google.com if there is an error in the syntax.
63 |
64 | hr
65 | p If you have issues, feel free to
66 | a(href="mailto:mikecrittenden@gmail.com") email me.
67 |
68 |
--------------------------------------------------------------------------------
/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | #search-container
5 | h1 DuckDuckGoog
6 | form#search-form(method='get', action='')
7 | input(type='text', id='search-input', name='q', required, placeholder='Whatcha looking for?')
8 | button(type='submit') Search
9 | p Searches Google and !bangs DuckDuckGo. Tell your browser!
10 | #footer
11 | p Lovingly built by
12 | a(href="http://twitter.com/mcrittenden") Mike Crittenden
13 | | |
14 | a(href="http://github.com/mikecrittenden/duckduckgoog") Source on GitHub
15 | | |
16 | a(href="mailto:mikecrittenden@gmail.com") Email me
17 | | |
18 | a(href="/privacy") Privacy
19 |
--------------------------------------------------------------------------------
/views/layout.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | title DuckDuckGoog
5 | link(rel='stylesheet', href='/stylesheets/style.css')
6 | link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Belgrano')
7 | link(rel='search', type='application/opensearchdescription+xml', href='/opensearch.xml', title='DuckDuckGoog Without Suggestions')
8 | link(rel='search', type='application/opensearchdescription+xml', href='/opensearchsuggest.xml', title='DuckDuckGoog With Suggestions')
9 | meta(name='description', content='DuckDuckGoog lets you use DuckDuckGo for bang queries and Google for everything else, so you get the best of both worlds.')
10 | script.
11 | var _gaq = _gaq || [];
12 | _gaq.push(['_setAccount', 'UA-6322775-20']);
13 | _gaq.push(['_trackPageview']);
14 | (function() {
15 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
16 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
17 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
18 | })();
19 | script.
20 | function focusSearch() {
21 | if (document.getElementById("search-input")) {
22 | document.getElementById("search-input").focus();
23 | }
24 | }
25 | body(onload='focusSearch()')
26 | block content
27 |
--------------------------------------------------------------------------------
/views/privacy.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | #container
5 | h1 DuckDuckGoog
6 | h2 Privacy Policy
7 | p It's quite simple. DuckDuckGoog doesn't track any queries submitted whatsoever, It simply redirects you to DuckDuckGo or Google depending on whether your search contains a !bang or not.
8 | p The source code for this is available
9 | a(href='https://github.com/mikecrittenden/duckduckgoog/blob/master/app.js#L22') here on GitHub
10 | | so you're free to take a look or even host your own version if you'd like.
11 | p If you have any questions, feel free to
12 | a(href="mailto:mikecrittenden@gmail.com") email me.
13 |
--------------------------------------------------------------------------------