forked from jshrake/ddg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ddg.py
executable file
·129 lines (103 loc) · 4.11 KB
/
ddg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python
"""www.duckduckgo.com zero-click api for your command-line"""
import sys
import webbrowser
import argparse
import duckduckgo
def main():
"""Controls the flow of the ddg application"""
'Build the parser and parse the arguments'
parser = argparse.ArgumentParser(
description='www.duckduckgo.com zero-click api for your command-line'
)
parser.add_argument('query', nargs='*', help='the search query')
parser.add_argument('-b', '--bang', action='store_true',
help='open the !bang redirect url in a new browser tab')
parser.add_argument('-d', '--define', action='store_true',
help='return the definition result')
parser.add_argument('-j', '--json', action='store_true',
help='return the zero-click info api json response')
parser.add_argument('-l', '--lucky', action='store_true',
help='open the result url in a new browser tab')
parser.add_argument('-s', '--search', action='store_true',
help='launch a DuckDuckGo search in a new browser tab')
parser.add_argument('-u', '--url', action='store_true',
help='return the result url')
args = parser.parse_args()
'Get the queries'
if args.query:
queries = [' '.join(args.query)]
elif not sys.stdin.isatty():
queries = sys.stdin.read().splitlines()
else:
parser.print_help()
return
'Determine if we need to add any prefixes based on user flags'
prefix = '!ddg ' if args.search else '!' if args.bang else ''
'Loop through each query'
for query in queries:
'Prefix the query'
query = prefix + query
'Get a response from api.duckduck.com using the duckduckgo module'
results = duckduckgo.search(query)
'If results is null, continue to the next query'
if not results:
continue
'Print the raw json output and return'
if args.json:
print_result(results.json)
continue
'a list of where to look for an answer first'
results_priority = get_results_priority(args)
'do we want the text or url output of the answer found'
var = get_text_or_url(args)
'action to perform when an answer is found'
action = get_action(args)
'Search for an answer and perform an action'
failed_to_find_answer = True
for r in results_priority:
result = getattr(getattr(results, r), var)
if result:
action(result)
failed_to_find_answer = False
break
'Let the user know if no answer was found'
if failed_to_find_answer:
if results.type == 'disambiguation':
print 'Your query was ambiguous, please be more specific'
else:
print 'No results found'
def get_results_priority(args):
"""Return a result priority list based on user input"""
redirect_mode = args.bang or args.search or args.lucky
if redirect_mode:
results_priority = ['redirect', 'result', 'abstract']
else:
results_priority = ['answer', 'abstract', 'result']
insert_pos = 0 if args.define else len(results_priority)
results_priority.insert(insert_pos, 'definition')
return results_priority
def get_action(args):
"""Return a function to launch the web browser or print a result"""
redirect_mode = args.bang or args.search or args.lucky
if redirect_mode and not args.url:
return webbrowser.open_new_tab
else:
return print_result
def get_text_or_url(args):
"""Determine if we need text or url output"""
redirect_mode = args.bang or args.search or args.lucky
if redirect_mode or args.url:
return 'url'
else:
return 'text'
def print_result(result):
"""Print the result, ascii encode if necessary"""
try:
print result
except RuntimeError:
print result.encode('ascii', 'ignore')
except:
print "Unexpected error attempting to print result"
if __name__ == "__main__":
main()