We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[search].duck is horribly broken.
It appears we're scraping the page wrong, since ".duck wikipedia" returns an ad page.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `willie/modules/search.py`
Content:
```
1 # coding=utf8
2 """
3 search.py - Willie Web Search Module
4 Copyright 2008-9, Sean B. Palmer, inamidst.com
5 Copyright 2012, Edward Powell, embolalia.net
6 Licensed under the Eiffel Forum License 2.
7 
8 http://willie.dftba.net
9 """
10 from __future__ import unicode_literals
11 
12 import re
13 from willie import web
14 from willie.module import commands, example
15 import json
16 import sys
17 import time
18 
19 
20 def google_ajax(query):
21     """Search using AjaxSearch, and return its JSON."""
22     uri = 'http://ajax.googleapis.com/ajax/services/search/web'
23     args = '?v=1.0&safe=off&q=' + query
24     bytes = web.get(uri + args)
25     return json.loads(bytes)
26 
27 
28 def google_search(query):
29     results = google_ajax(query)
30     try:
31         return results['responseData']['results'][0]['unescapedUrl']
32     except IndexError:
33         return None
34     except TypeError:
35         return False
36 
37 
38 def google_count(query):
39     results = google_ajax(query)
40     if not 'responseData' in results:
41         return '0'
42     if not 'cursor' in results['responseData']:
43         return '0'
44     if not 'estimatedResultCount' in results['responseData']['cursor']:
45         return '0'
46     return results['responseData']['cursor']['estimatedResultCount']
47 
48 
49 def formatnumber(n):
50     """Format a number with beautiful commas."""
51     parts = list(str(n))
52     for i in range((len(parts) - 3), 0, -3):
53         parts.insert(i, ',')
54     return ''.join(parts)
55 
56 
57 @commands('g', 'google')
58 @example('.g swhack')
59 def g(bot, trigger):
60     """Queries Google for the specified input."""
61     query = trigger.group(2)
62     if not query:
63         return bot.reply('.g what?')
64     uri = google_search(query)
65     if uri:
66         bot.reply(uri)
67         bot.memory['last_seen_url'][trigger.sender] = uri
68     elif uri is False:
69         bot.reply("Problem getting data from Google.")
70     else:
71         bot.reply("No results found for '%s'." % query)
72 
73 
74 @commands('gc')
75 @example('.gc extrapolate')
76 def gc(bot, trigger):
77     """Returns the number of Google results for the specified input."""
78     query = trigger.group(2)
79     if not query:
80         return bot.reply('.gc what?')
81     num = formatnumber(google_count(query))
82     bot.say(query + ': ' + num)
83 
84 r_query = re.compile(
85     r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+'
86 )
87 
88 
89 @commands('gcs', 'comp')
90 @example('.gcs foo bar')
91 def gcs(bot, trigger):
92     """Compare the number of Google search results"""
93     if not trigger.group(2):
94         return bot.reply("Nothing to compare.")
95     queries = r_query.findall(trigger.group(2))
96     if len(queries) > 6:
97         return bot.reply('Sorry, can only compare up to six things.')
98 
99     results = []
100     for i, query in enumerate(queries):
101         query = query.strip('[]')
102         n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
103         results.append((n, query))
104         if i >= 2:
105             time.sleep(0.25)
106         if i >= 4:
107             time.sleep(0.25)
108 
109     results = [(term, n) for (n, term) in reversed(sorted(results))]
110     reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)
111     bot.say(reply)
112 
113 r_bing = re.compile(r'<h3><a href="([^"]+)"')
114 
115 
116 def bing_search(query, lang='en-GB'):
117     base = 'http://www.bing.com/search?mkt=%s&q=' % lang
118     bytes = web.get(base + query)
119     m = r_bing.search(bytes)
120     if m:
121         return m.group(1)
122 
123 r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">')
124 
125 
126 def duck_search(query):
127     query = query.replace('!', '')
128     uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
129     bytes = web.get(uri)
130     m = r_duck.search(bytes)
131     if m:
132         return web.decode(m.group(1))
133 
134 
135 def duck_api(query):
136     if '!bang' in query.lower():
137         return 'https://duckduckgo.com/bang.html'
138 
139     uri = 'http://api.duckduckgo.com/?q=%s&format=json&no_html=1&no_redirect=1' % query
140     results = json.loads(web.get(uri))
141     if results['Redirect']:
142         return results['Redirect']
143     else:
144         return None
145 
146 
147 @commands('duck', 'ddg')
148 @example('.duck privacy or .duck !mcwiki obsidian')
149 def duck(bot, trigger):
150     """Queries Duck Duck Go for the specified input."""
151     query = trigger.group(2)
152     if not query:
153         return bot.reply('.ddg what?')
154 
155     #If the API gives us something, say it and stop
156     result = duck_api(query)
157     if result:
158         bot.reply(result)
159         return
160 
161     #Otherwise, look it up on the HTMl version
162     uri = duck_search(query)
163 
164     if uri:
165         bot.reply(uri)
166         bot.memory['last_seen_url'][trigger.sender] = uri
167     else:
168         bot.reply("No results found for '%s'." % query)
169 
170 
171 @commands('search')
172 @example('.search nerdfighter')
173 def search(bot, trigger):
174     """Searches Google, Bing, and Duck Duck Go."""
175     if not trigger.group(2):
176         return bot.reply('.search for what?')
177     query = trigger.group(2)
178     gu = google_search(query) or '-'
179     bu = bing_search(query) or '-'
180     du = duck_search(query) or '-'
181 
182     if (gu == bu) and (bu == du):
183         result = '%s (g, b, d)' % gu
184     elif (gu == bu):
185         result = '%s (g, b), %s (d)' % (gu, du)
186     elif (bu == du):
187         result = '%s (b, d), %s (g)' % (bu, gu)
188     elif (gu == du):
189         result = '%s (g, d), %s (b)' % (gu, bu)
190     else:
191         if len(gu) > 250:
192             gu = '(extremely long link)'
193         if len(bu) > 150:
194             bu = '(extremely long link)'
195         if len(du) > 150:
196             du = '(extremely long link)'
197         result = '%s (g), %s (b), %s (d)' % (gu, bu, du)
198 
199     bot.reply(result)
200 
201 
202 @commands('suggest')
203 def suggest(bot, trigger):
204     """Suggest terms starting with given input"""
205     if not trigger.group(2):
206         return bot.reply("No query term.")
207     query = trigger.group(2)
208     uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
209     answer = web.get(uri+query.replace('+', '%2B'))
210     if answer:
211         bot.say(answer)
212     else:
213         bot.reply('Sorry, no result.')
214
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/willie/modules/search.py b/willie/modules/search.py
--- a/willie/modules/search.py
+++ b/willie/modules/search.py
@@ -127,6 +127,8 @@
     query = query.replace('!', '')
     uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
     bytes = web.get(uri)
+    if 'web-result"' in bytes: #filter out the adds on top of the page
+        bytes = bytes.split('web-result"')[1]
     m = r_duck.search(bytes)
     if m:
         return web.decode(m.group(1))

{"golden_diff": "diff --git a/willie/modules/search.py b/willie/modules/search.py\n--- a/willie/modules/search.py\n+++ b/willie/modules/search.py\n@@ -127,6 +127,8 @@\n     query = query.replace('!', '')\n     uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query\n     bytes = web.get(uri)\n+    if 'web-result\"' in bytes: #filter out the adds on top of the page\n+        bytes = bytes.split('web-result\"')[1]\n     m = r_duck.search(bytes)\n     if m:\n         return web.decode(m.group(1))\n", "issue": "[search].duck is horribly broken.\nIt appears we're scraping the page wrong, since \".duck wikipedia\" returns an ad page.\n\n", "before_files": [{"content": "# coding=utf8\n\"\"\"\nsearch.py - Willie Web Search Module\nCopyright 2008-9, Sean B. Palmer, inamidst.com\nCopyright 2012, Edward Powell, embolalia.net\nLicensed under the Eiffel Forum License 2.\n\nhttp://willie.dftba.net\n\"\"\"\nfrom __future__ import unicode_literals\n\nimport re\nfrom willie import web\nfrom willie.module import commands, example\nimport json\nimport sys\nimport time\n\n\ndef google_ajax(query):\n    \"\"\"Search using AjaxSearch, and return its JSON.\"\"\"\n    uri = 'http://ajax.googleapis.com/ajax/services/search/web'\n    args = '?v=1.0&safe=off&q=' + query\n    bytes = web.get(uri + args)\n    return json.loads(bytes)\n\n\ndef google_search(query):\n    results = google_ajax(query)\n    try:\n        return results['responseData']['results'][0]['unescapedUrl']\n    except IndexError:\n        return None\n    except TypeError:\n        return False\n\n\ndef google_count(query):\n    results = google_ajax(query)\n    if not 'responseData' in results:\n        return '0'\n    if not 'cursor' in results['responseData']:\n        return '0'\n    if not 'estimatedResultCount' in results['responseData']['cursor']:\n        return '0'\n    return results['responseData']['cursor']['estimatedResultCount']\n\n\ndef formatnumber(n):\n    \"\"\"Format a number with beautiful commas.\"\"\"\n    parts = list(str(n))\n    for i in range((len(parts) - 3), 0, -3):\n        parts.insert(i, ',')\n    return ''.join(parts)\n\n\n@commands('g', 'google')\n@example('.g swhack')\ndef g(bot, trigger):\n    \"\"\"Queries Google for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.g what?')\n    uri = google_search(query)\n    if uri:\n        bot.reply(uri)\n        bot.memory['last_seen_url'][trigger.sender] = uri\n    elif uri is False:\n        bot.reply(\"Problem getting data from Google.\")\n    else:\n        bot.reply(\"No results found for '%s'.\" % query)\n\n\n@commands('gc')\n@example('.gc extrapolate')\ndef gc(bot, trigger):\n    \"\"\"Returns the number of Google results for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.gc what?')\n    num = formatnumber(google_count(query))\n    bot.say(query + ': ' + num)\n\nr_query = re.compile(\n    r'\\+?\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|\\[[^]\\\\]*(?:\\\\.[^]\\\\]*)*\\]|\\S+'\n)\n\n\n@commands('gcs', 'comp')\n@example('.gcs foo bar')\ndef gcs(bot, trigger):\n    \"\"\"Compare the number of Google search results\"\"\"\n    if not trigger.group(2):\n        return bot.reply(\"Nothing to compare.\")\n    queries = r_query.findall(trigger.group(2))\n    if len(queries) > 6:\n        return bot.reply('Sorry, can only compare up to six things.')\n\n    results = []\n    for i, query in enumerate(queries):\n        query = query.strip('[]')\n        n = int((formatnumber(google_count(query)) or '0').replace(',', ''))\n        results.append((n, query))\n        if i >= 2:\n            time.sleep(0.25)\n        if i >= 4:\n            time.sleep(0.25)\n\n    results = [(term, n) for (n, term) in reversed(sorted(results))]\n    reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)\n    bot.say(reply)\n\nr_bing = re.compile(r'<h3><a href=\"([^\"]+)\"')\n\n\ndef bing_search(query, lang='en-GB'):\n    base = 'http://www.bing.com/search?mkt=%s&q=' % lang\n    bytes = web.get(base + query)\n    m = r_bing.search(bytes)\n    if m:\n        return m.group(1)\n\nr_duck = re.compile(r'nofollow\" class=\"[^\"]+\" href=\"(.*?)\">')\n\n\ndef duck_search(query):\n    query = query.replace('!', '')\n    uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query\n    bytes = web.get(uri)\n    m = r_duck.search(bytes)\n    if m:\n        return web.decode(m.group(1))\n\n\ndef duck_api(query):\n    if '!bang' in query.lower():\n        return 'https://duckduckgo.com/bang.html'\n\n    uri = 'http://api.duckduckgo.com/?q=%s&format=json&no_html=1&no_redirect=1' % query\n    results = json.loads(web.get(uri))\n    if results['Redirect']:\n        return results['Redirect']\n    else:\n        return None\n\n\n@commands('duck', 'ddg')\n@example('.duck privacy or .duck !mcwiki obsidian')\ndef duck(bot, trigger):\n    \"\"\"Queries Duck Duck Go for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.ddg what?')\n\n    #If the API gives us something, say it and stop\n    result = duck_api(query)\n    if result:\n        bot.reply(result)\n        return\n\n    #Otherwise, look it up on the HTMl version\n    uri = duck_search(query)\n\n    if uri:\n        bot.reply(uri)\n        bot.memory['last_seen_url'][trigger.sender] = uri\n    else:\n        bot.reply(\"No results found for '%s'.\" % query)\n\n\n@commands('search')\n@example('.search nerdfighter')\ndef search(bot, trigger):\n    \"\"\"Searches Google, Bing, and Duck Duck Go.\"\"\"\n    if not trigger.group(2):\n        return bot.reply('.search for what?')\n    query = trigger.group(2)\n    gu = google_search(query) or '-'\n    bu = bing_search(query) or '-'\n    du = duck_search(query) or '-'\n\n    if (gu == bu) and (bu == du):\n        result = '%s (g, b, d)' % gu\n    elif (gu == bu):\n        result = '%s (g, b), %s (d)' % (gu, du)\n    elif (bu == du):\n        result = '%s (b, d), %s (g)' % (bu, gu)\n    elif (gu == du):\n        result = '%s (g, d), %s (b)' % (gu, bu)\n    else:\n        if len(gu) > 250:\n            gu = '(extremely long link)'\n        if len(bu) > 150:\n            bu = '(extremely long link)'\n        if len(du) > 150:\n            du = '(extremely long link)'\n        result = '%s (g), %s (b), %s (d)' % (gu, bu, du)\n\n    bot.reply(result)\n\n\n@commands('suggest')\ndef suggest(bot, trigger):\n    \"\"\"Suggest terms starting with given input\"\"\"\n    if not trigger.group(2):\n        return bot.reply(\"No query term.\")\n    query = trigger.group(2)\n    uri = 'http://websitedev.de/temp-bin/suggest.pl?q='\n    answer = web.get(uri+query.replace('+', '%2B'))\n    if answer:\n        bot.say(answer)\n    else:\n        bot.reply('Sorry, no result.')\n", "path": "willie/modules/search.py"}], "after_files": [{"content": "# coding=utf8\n\"\"\"\nsearch.py - Willie Web Search Module\nCopyright 2008-9, Sean B. Palmer, inamidst.com\nCopyright 2012, Edward Powell, embolalia.net\nLicensed under the Eiffel Forum License 2.\n\nhttp://willie.dftba.net\n\"\"\"\nfrom __future__ import unicode_literals\n\nimport re\nfrom willie import web\nfrom willie.module import commands, example\nimport json\nimport sys\nimport time\n\n\ndef google_ajax(query):\n    \"\"\"Search using AjaxSearch, and return its JSON.\"\"\"\n    uri = 'http://ajax.googleapis.com/ajax/services/search/web'\n    args = '?v=1.0&safe=off&q=' + query\n    bytes = web.get(uri + args)\n    return json.loads(bytes)\n\n\ndef google_search(query):\n    results = google_ajax(query)\n    try:\n        return results['responseData']['results'][0]['unescapedUrl']\n    except IndexError:\n        return None\n    except TypeError:\n        return False\n\n\ndef google_count(query):\n    results = google_ajax(query)\n    if not 'responseData' in results:\n        return '0'\n    if not 'cursor' in results['responseData']:\n        return '0'\n    if not 'estimatedResultCount' in results['responseData']['cursor']:\n        return '0'\n    return results['responseData']['cursor']['estimatedResultCount']\n\n\ndef formatnumber(n):\n    \"\"\"Format a number with beautiful commas.\"\"\"\n    parts = list(str(n))\n    for i in range((len(parts) - 3), 0, -3):\n        parts.insert(i, ',')\n    return ''.join(parts)\n\n\n@commands('g', 'google')\n@example('.g swhack')\ndef g(bot, trigger):\n    \"\"\"Queries Google for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.g what?')\n    uri = google_search(query)\n    if uri:\n        bot.reply(uri)\n        bot.memory['last_seen_url'][trigger.sender] = uri\n    elif uri is False:\n        bot.reply(\"Problem getting data from Google.\")\n    else:\n        bot.reply(\"No results found for '%s'.\" % query)\n\n\n@commands('gc')\n@example('.gc extrapolate')\ndef gc(bot, trigger):\n    \"\"\"Returns the number of Google results for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.gc what?')\n    num = formatnumber(google_count(query))\n    bot.say(query + ': ' + num)\n\nr_query = re.compile(\n    r'\\+?\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|\\[[^]\\\\]*(?:\\\\.[^]\\\\]*)*\\]|\\S+'\n)\n\n\n@commands('gcs', 'comp')\n@example('.gcs foo bar')\ndef gcs(bot, trigger):\n    \"\"\"Compare the number of Google search results\"\"\"\n    if not trigger.group(2):\n        return bot.reply(\"Nothing to compare.\")\n    queries = r_query.findall(trigger.group(2))\n    if len(queries) > 6:\n        return bot.reply('Sorry, can only compare up to six things.')\n\n    results = []\n    for i, query in enumerate(queries):\n        query = query.strip('[]')\n        n = int((formatnumber(google_count(query)) or '0').replace(',', ''))\n        results.append((n, query))\n        if i >= 2:\n            time.sleep(0.25)\n        if i >= 4:\n            time.sleep(0.25)\n\n    results = [(term, n) for (n, term) in reversed(sorted(results))]\n    reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)\n    bot.say(reply)\n\nr_bing = re.compile(r'<h3><a href=\"([^\"]+)\"')\n\n\ndef bing_search(query, lang='en-GB'):\n    base = 'http://www.bing.com/search?mkt=%s&q=' % lang\n    bytes = web.get(base + query)\n    m = r_bing.search(bytes)\n    if m:\n        return m.group(1)\n\nr_duck = re.compile(r'nofollow\" class=\"[^\"]+\" href=\"(.*?)\">')\n\n\ndef duck_search(query):\n    query = query.replace('!', '')\n    uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query\n    bytes = web.get(uri)\n    if 'web-result\"' in bytes: #filter out the adds on top of the page\n        bytes = bytes.split('web-result\"')[1]\n    m = r_duck.search(bytes)\n    if m:\n        return web.decode(m.group(1))\n\n\ndef duck_api(query):\n    if '!bang' in query.lower():\n        return 'https://duckduckgo.com/bang.html'\n\n    uri = 'http://api.duckduckgo.com/?q=%s&format=json&no_html=1&no_redirect=1' % query\n    results = json.loads(web.get(uri))\n    if results['Redirect']:\n        return results['Redirect']\n    else:\n        return None\n\n\n@commands('duck', 'ddg')\n@example('.duck privacy or .duck !mcwiki obsidian')\ndef duck(bot, trigger):\n    \"\"\"Queries Duck Duck Go for the specified input.\"\"\"\n    query = trigger.group(2)\n    if not query:\n        return bot.reply('.ddg what?')\n\n    #If the API gives us something, say it and stop\n    result = duck_api(query)\n    if result:\n        bot.reply(result)\n        return\n\n    #Otherwise, look it up on the HTMl version\n    uri = duck_search(query)\n\n    if uri:\n        bot.reply(uri)\n        bot.memory['last_seen_url'][trigger.sender] = uri\n    else:\n        bot.reply(\"No results found for '%s'.\" % query)\n\n\n@commands('search')\n@example('.search nerdfighter')\ndef search(bot, trigger):\n    \"\"\"Searches Google, Bing, and Duck Duck Go.\"\"\"\n    if not trigger.group(2):\n        return bot.reply('.search for what?')\n    query = trigger.group(2)\n    gu = google_search(query) or '-'\n    bu = bing_search(query) or '-'\n    du = duck_search(query) or '-'\n\n    if (gu == bu) and (bu == du):\n        result = '%s (g, b, d)' % gu\n    elif (gu == bu):\n        result = '%s (g, b), %s (d)' % (gu, du)\n    elif (bu == du):\n        result = '%s (b, d), %s (g)' % (bu, gu)\n    elif (gu == du):\n        result = '%s (g, d), %s (b)' % (gu, bu)\n    else:\n        if len(gu) > 250:\n            gu = '(extremely long link)'\n        if len(bu) > 150:\n            bu = '(extremely long link)'\n        if len(du) > 150:\n            du = '(extremely long link)'\n        result = '%s (g), %s (b), %s (d)' % (gu, bu, du)\n\n    bot.reply(result)\n\n\n@commands('suggest')\ndef suggest(bot, trigger):\n    \"\"\"Suggest terms starting with given input\"\"\"\n    if not trigger.group(2):\n        return bot.reply(\"No query term.\")\n    query = trigger.group(2)\n    uri = 'http://websitedev.de/temp-bin/suggest.pl?q='\n    answer = web.get(uri+query.replace('+', '%2B'))\n    if answer:\n        bot.say(answer)\n    else:\n        bot.reply('Sorry, no result.')\n", "path": "willie/modules/search.py"}]}