From dbcdc014576ba08fcbe0fb33620193e5dd3f4b46 Mon Sep 17 00:00:00 2001 From: Dave Gallant Date: Sun, 28 Jun 2020 23:48:20 -0400 Subject: [PATCH] Cleanup CLI interface and allow for regular expressions in search (#68) * Cleanup CLI interface and allow for regular expressions in search * Put a cap on beautifulsoup4 --- README.md | 38 +++++++++++++++++++++++++++++--------- requirements.txt | 3 ++- rfd/VERSION | 2 +- rfd/cli.py | 48 +++++++++++++++++++++++++++--------------------- rfd/search.py | 15 ++++++++------- 5 files changed, 67 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index ada419b..e333aa4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ Hot deals on the command line. [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/davegallant/rfd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/davegallant/rfd/context:python) -![screenshot](https://user-images.githubusercontent.com/4519234/76671943-c9d24f80-656f-11ea-872e-85897add37db.png) +![screenshot](https://user-images.githubusercontent.com/4519234/85969861-e10a4100-b996-11ea-9a31-6203322c60ee.png) + ## Install @@ -17,19 +18,38 @@ Hot deals on the command line. pip install rfd ``` -## Use +## Usage -### view threads -```bash -rfd threads [--forum-id 9] [--limit 10] +```shell +Usage: rfd [OPTIONS] COMMAND [ARGS]... + + CLI for https://forums.redflagdeals.com + +Options: + -v, --version + --help Show this message and exit. + +Commands: + posts Display all posts in a thread. + search Search deals based on a regular expression. + threads Displays threads in the forum. Defaults to hot deals. ``` -### search -```bash -rfd search pizza [--num-pages 100] +## Examples + +### view hot deals +```shell +rfd threads ``` -## Support Tab Completion +### search for pizza +```shell +rfd search 'pizza' +``` + +## Tab Completion + +To enable: ### bash diff --git a/requirements.txt b/requirements.txt index 62bda28..303c699 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ -beautifulsoup4>=4.8.1 +beautifulsoup4<=4.8.2 click>=7.0 colorama>=0.4.3 requests>=2.22.0 +soupsieve<=2.0 diff --git a/rfd/VERSION b/rfd/VERSION index 42045ac..c2c0004 100644 --- a/rfd/VERSION +++ b/rfd/VERSION @@ -1 +1 @@ -0.3.4 +0.3.5 diff --git a/rfd/cli.py b/rfd/cli.py index 3c1f5f3..c114534 100644 --- a/rfd/cli.py +++ b/rfd/cli.py @@ -36,34 +36,40 @@ def get_vote_color(score): return Fore.BLUE + " [" + str(score) + "] " +def print_version(ctx, value): + if not value or ctx.resilient_parsing: + return + click.echo(get_version()) + ctx.exit() + + @click.group(invoke_without_command=True) -@click.option("--version/--no-version", default=False) +@click.option( + "-v", + "--version", + is_flag=True, + callback=print_version, + expose_value=False, + is_eager=True, +) @click.pass_context -def cli(ctx, version): +def cli(ctx): """CLI for https://forums.redflagdeals.com""" - if version: - click.echo(get_version()) - elif not ctx.invoked_subcommand: + if not ctx.invoked_subcommand: click.echo(ctx.get_help()) -@cli.command("version") -def display_version(): - click.echo(get_version()) - - -@cli.command(short_help="Displays posts in a specific thread.") +@cli.command(short_help="Display all posts in a thread.") @click.argument("post_id") def posts(post_id): - """Displays posts in a specific thread. + """Iterate all pages and display all posts in a thread. post_id can be a full url or post id only Example: \b - url: https://forums.redflagdeals.com/koodo-targeted-public-mobile-12-120-koodo-5gb-40-no-referrals-2173603 - post_id: 2173603 + rfd posts https://forums.redflagdeals.com/koodo-targeted-public-mobile-12-120-koodo-5gb-40-no-referrals-2173603 """ try: @@ -87,11 +93,11 @@ def posts(post_id): sys.exit(1) -@cli.command(short_help="Displays threads in the specified forum.") +@cli.command(short_help="Displays threads in the forum. Defaults to hot deals.") @click.option("--limit", default=10, help="Number of topics.") @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. + """Display threads in the specified forum id. Defaults to 9 (hot deals). Popular forum ids: @@ -124,14 +130,14 @@ def threads(limit, forum_id): click.echo(Style.RESET_ALL) -@cli.command(short_help="Displays threads in the specified forum.") +@cli.command(short_help="Search deals based on a regular expression.") @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. +@click.argument("regex") +def search(num_pages, forum_id, regex): + """Search deals based on regex. Popular forum ids: @@ -151,7 +157,7 @@ def search(num_pages, forum_id, keyword): 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): + for thread in search_threads(threads=_threads, regex=regex): count += 1 click.echo( " " diff --git a/rfd/search.py b/rfd/search.py index 3666a50..507f0c1 100644 --- a/rfd/search.py +++ b/rfd/search.py @@ -1,13 +1,14 @@ -def search_threads(threads, keyword=None): - """Match deal title and dealer names with keyword specified.""" +import re - if keyword is None: - return - keyword = str(keyword) +def search_threads(threads, regex): + """Match deal title and dealer names with regex specified.""" + + regexp = re.compile(str(regex).lower()) for deal in threads: - if keyword.lower() in deal.title.lower() or ( - deal.dealer_name and keyword.lower() in deal.dealer_name.lower() + + if regexp.search(deal.title.lower()) or ( + deal.dealer_name and regexp.search(deal.dealer_name.lower()) ): yield deal