1
|
|
|
from lib.actions import BaseAction |
2
|
|
|
from dotted.utils import dot |
3
|
|
|
from fuzzywuzzy import fuzz |
4
|
|
|
from functools import partial |
5
|
|
|
import json |
6
|
|
|
import pprint |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
class ArticleSearch(BaseAction): |
10
|
|
|
def run(self, query, include_body=False, limit=5): |
11
|
|
|
response = self._api_get('/articles') |
12
|
|
|
articles = response['articles'] |
13
|
|
|
|
14
|
|
|
ranks_fun = partial(self._rank_article, query=query) |
15
|
|
|
ranks = map(ranks_fun, articles) |
16
|
|
|
|
17
|
|
|
results = sorted(ranks, key=lambda rank: rank[0], reverse=True)[:limit] |
18
|
|
|
response_fun = partial(self._extract_article_data, |
19
|
|
|
include_body=include_body) |
20
|
|
|
response = map(response_fun, results) |
21
|
|
|
return json.dumps(response) |
22
|
|
|
|
23
|
|
|
# Takes an incoming query and an article, and runs a fuzzy token |
24
|
|
|
# search to get data from an article. |
25
|
|
|
# |
26
|
|
|
# Returns a tuple of (rank, article) |
27
|
|
|
def _rank_article(self, article, query): |
28
|
|
|
rank = fuzz.token_set_ratio(query, article['body'].encode('utf-8')) |
29
|
|
|
return (rank, article) |
30
|
|
|
|
31
|
|
|
# Takes a tuple of (rank, article), and extracts data from the |
32
|
|
|
# object based on whether the user asks for additional body data |
33
|
|
|
# or not. |
34
|
|
|
def _extract_article_data(self, result, include_body=False): |
35
|
|
|
article = result[1] |
36
|
|
|
|
37
|
|
|
article_data = { |
38
|
|
|
'title': article['title'], |
39
|
|
|
'url': article['url'], |
40
|
|
|
} |
41
|
|
|
if include_body: |
42
|
|
|
article_data['body'] = article['body'] |
43
|
|
|
|
44
|
|
|
return article_data |
45
|
|
|
|
46
|
|
|
|