add search command (#33)

* add search command
This commit is contained in:
Dave Gallant
2019-10-04 21:06:53 -04:00
committed by GitHub
parent 59e37a9105
commit ac46f2ae27
8 changed files with 87 additions and 73 deletions

View File

@@ -55,7 +55,7 @@ confidence=
disable=
attribute-defined-outside-init,
bad-option-value,
duplicate-code,
bad-continuation,
fixme,
invalid-name,
missing-docstring,

View File

@@ -16,8 +16,14 @@ pip install rfd
![rfd_demo_gif](https://user-images.githubusercontent.com/4519234/64501455-64836600-d28f-11e9-8381-3fbfda910230.gif)
### threads
```bash
rfd threads <topic-id> [--limit 10]
rfd threads [--forum-id 9] [--limit 10]
```
### search
```bash
rfd search pizza [--num-pages 100]
```
## Tab Completion

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
version = "0.2.1"
version = "0.3.0"

View File

@@ -26,15 +26,15 @@ def get_safe_per_page(limit):
return limit
def users_to_dict(users):
"""Create a dictionary of user ids to usernames."""
users_dict = {}
def create_user_map(users):
"""Create a map of user ids to usernames."""
m = dict()
for user in users:
users_dict[user.get("user_id")] = user.get("username")
return users_dict
m[user.get("user_id")] = user.get("username")
return m
def get_threads(forum_id, limit):
def get_threads(forum_id, limit, page=1):
"""Get threads from rfd api
Arguments:
@@ -46,8 +46,8 @@ def get_threads(forum_id, limit):
"""
try:
response = requests.get(
"{}/api/topics?forum_id={}&per_page={}".format(
API_BASE_URL, forum_id, get_safe_per_page(limit)
"{}/api/topics?forum_id={}&per_page={}&page={}".format(
API_BASE_URL, forum_id, get_safe_per_page(limit), page
)
)
if response.status_code == 200:
@@ -86,7 +86,7 @@ def get_posts(post):
API_BASE_URL, post_id, 40, page
)
)
users = users_to_dict(response.json().get("users"))
users = create_user_map(response.json().get("users"))
posts = response.json().get("posts")

View File

@@ -7,6 +7,7 @@ import sys
import click
from colorama import init, Fore, Style
from .api import get_threads, get_posts
from .search import search_threads
from .parsing import parse_threads
from .__version__ import version as current_version
@@ -88,7 +89,7 @@ def posts(post_id):
@cli.command(short_help="Displays threads in the specified forum.")
@click.option("--limit", default=10, help="Number of topics.")
@click.argument("forum_id", default=9)
@click.option("--forum-id", default=9, help="The forum id number")
def threads(limit, forum_id):
"""Displays threads in the specified forum id. Defaults to 9.
@@ -107,10 +108,10 @@ def threads(limit, forum_id):
88 \t cell phones
"""
_threads = parse_threads(get_threads(forum_id, limit), limit)
for i, thread in enumerate(_threads, 1):
for count, thread in enumerate(_threads, 1):
click.echo(
" "
+ str(i)
+ str(count)
+ "."
+ get_vote_color(thread.score)
+ Fore.RESET
@@ -120,5 +121,46 @@ def threads(limit, forum_id):
click.echo(Style.RESET_ALL)
@cli.command(short_help="Displays threads in the specified forum.")
@click.option("--num-pages", default=5, help="Number of pages to search.")
@click.option(
"--forum-id", default=9, help="The forum id number. Defaults to 9 (hot deals)."
)
@click.argument("keyword")
def search(num_pages, forum_id, keyword):
"""Searches for deals based on a keyword in the specified forum id.
Popular forum ids:
\b
9 \t hot deals
14 \t computer and electronics
15 \t offtopic
17 \t entertainment
18 \t food and drink
40 \t automotive
53 \t home and garden
67 \t fashion and apparel
74 \t shopping discussion
88 \t cell phones
"""
count = 0
for page in range(1, num_pages):
_threads = parse_threads(get_threads(forum_id, 100, page=page), limit=100)
for thread in search_threads(threads=_threads, keyword=keyword):
count += 1
click.echo(
" "
+ str(count)
+ "."
+ get_vote_color(thread.score)
+ Fore.RESET
+ "[%s] %s" % (thread.dealer_name, thread.title)
)
click.echo(Fore.BLUE + " {}".format(thread.url))
click.echo(Style.RESET_ALL)
if __name__ == "__main__":
cli()

View File

@@ -6,6 +6,9 @@ class Thread:
self.title = title
self.url = url
def __repr__(self):
return "Thread(%s)" % self.title
class Post:
def __init__(self, body, score, user):

13
rfd/search.py Normal file
View File

@@ -0,0 +1,13 @@
def search_threads(threads, keyword=None):
"""Match deal title and dealer names with keyword specified."""
if keyword is None:
return
keyword = str(keyword)
for deal in threads:
if keyword.lower() in deal.title.lower() or (
deal.dealer_name and keyword.lower() in deal.dealer_name.lower()
):
yield deal

View File

@@ -1,6 +1,7 @@
from rfd.api import extract_post_id
from rfd.parsing import build_web_path, parse_threads
def test_build_web_path():
assert build_web_path("/test") == "https://forums.redflagdeals.com/test"
@@ -18,62 +19,11 @@ def test_extract_post_id():
def test_parse_threads(threads_api_response):
assert len(parse_threads(threads_api_response, 10)) == len(
[
{
"score": 0,
"title": "[Sponsored] 3 Months Free, Cable 75M, Unlimited Internet $34.99/30 "
"Days, Free Installation/Modem Rental",
"url": "https://forums.redflagdeals.com/carrytel-sponsored-3-months-free-cable-75m-unlimited-internet-34-99-30-days-free-installation-modem-rental-2197859/",
},
{
"score": 92,
"title": "WyzeCam 1080p HD Wireless Smart Home Camera v2 $37.49",
"url": "https://forums.redflagdeals.com/amazon-ca-wyzecam-1080p-hd-wireless-smart-home-camera-v2-37-49-2191108/",
},
{
"score": 8,
"title": "Jabra Elite 65T $169.99",
"url": "https://forums.redflagdeals.com/best-buy-jabra-elite-65t-169-99-2197916/",
},
{
"score": 1,
"title": "Glad Cling Wrap Plastic Wrap, 300 Metre Roll - best price $9.47",
"url": "https://forums.redflagdeals.com/amazon-ca-glad-cling-wrap-plastic-wrap-300-metre-roll-best-price-9-47-2198211/",
},
{
"score": 17,
"title": "Firman 3300 inverter generator $599",
"url": "https://forums.redflagdeals.com/costco-firman-3300-inverter-generator-599-2195171/",
},
{
"score": 3,
"title": "HOT - KitchenAid Stand Mixer - $199",
"url": "https://forums.redflagdeals.com/walmart-hot-kitchenaid-stand-mixer-199-2198199/",
},
{
"score": -1,
"title": "Seagate Expansion 4TB Portable External Hard Drive USB 3.0 "
"(STEA4000400) $119.92",
"url": "https://forums.redflagdeals.com/amazon-ca-seagate-expansion-4tb-portable-external-hard-drive-usb-3-0-stea4000400-119-92-2198164/",
},
{
"score": 0,
"title": "WORKSHOP Wet Dry Vacs Ash Vacuum Cleaner WS0500ASH, 5-Gallon Ash "
"Vac 65% Off, Now: $48.54",
"url": "https://forums.redflagdeals.com/workshop-wet-dry-vacs-ash-vacuum-cleaner-ws0500ash-5-gallon-ash-vac-65-off-now-48-54-2198212/",
},
{
"score": 4,
"title": "NBA 2K18 (Nintendo Switch) -$19.99 or $16.99 PM",
"url": "https://forums.redflagdeals.com/the-source-nba-2k18-nintendo-switch-19-99-16-99-pm-2198191/",
},
{
"score": 5,
"title": "CROCS.CA 40%OFF Select style - at checkout",
"url": "https://forums.redflagdeals.com/crocs-crocs-ca-40-off-select-style-checkout-2198145/",
},
]
)
limit = 10
threads = parse_threads(threads_api_response, limit)
assert len(threads) == limit
assert len(parse_threads(None, 10)) is 0
def test_parse_threads_empty():
assert parse_threads(None, 10) == []