Skip to content

Commit

Permalink
Migrate from Click to Typer and add Plugin support (#14)
Browse files Browse the repository at this point in the history
Replaced Click with Typer

* Added support for plugins

* Updated README with plugin info
  • Loading branch information
arzkar authored Jan 17, 2022
1 parent 8d030aa commit 35a8a03
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 179 deletions.
10 changes: 5 additions & 5 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.4.5
current_version = 0.5.0
commit = True
tag = False
parse = ^
Expand All @@ -23,13 +23,13 @@ search = version='{current_version}'
replace = version='{new_version}'

[bumpversion:file:fichub_cli/cli.py]
search = click.echo("Version: {current_version}")
replace = click.echo("Version: {new_version}")
search = typer.echo("fichub-cli: v{current_version}")
replace = typer.echo("fichub-cli: v{new_version}")

[bumpversion:file:fichub_cli/utils/fichub.py]
search = 'User-Agent': 'fichub_cli/{current_version}'
replace = 'User-Agent': 'fichub_cli/{new_version}'

[bumpversion:file:tests/test_cli.py]
search = 'Version: {current_version}'
replace = 'Version: {new_version}'
search = 'fichub-cli: v{current_version}'
replace = 'fichub-cli: v{new_version}'
50 changes: 21 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pip install git+https://github.com/FicHub/fichub-cli@main

```
> fichub_cli
Usage: fichub_cli [OPTIONS]
Usage: fichub_cli [OPTIONS] COMMAND [ARGS]...
A CLI for the fichub.net API
Expand All @@ -34,29 +34,30 @@ Usage: fichub_cli [OPTIONS]
To report issues for the CLI, open an issue at
https://github.com/FicHub/fichub-cli/issues
Failed downloads will be saved in the `err.log` file in the current
directory.
Options:
-u, --url TEXT The url of the fanfiction enclosed within quotes
-i, --infile TEXT Give a filename to read URLs from
-l, --list-url TEXT Enter a comma separated list of urls to download, enclosed within quotes
-v, --verbose Verbose progressbar
-o, --out-dir TEXT Absolute path to the Output directory for files (default: Current Directory)
-f, --format TEXT Download Format: epub (default), mobi, pdf or html
--force Force overwrite of an existing file
--get-urls TEXT Get all story urls found from a page.Currently supports archiveofourown.org only
-s, --supported-sites List of supported sites
-d, --debug Show the log in the console for debugging
--meta-json TEXT Fetch only the metadata for the fanfiction in json format
--log Save the logfile for debugging
--version Display version & quit
--help Show this message and exit
-u, --url TEXT The url of the fanfiction enclosed within quotes
-i, --infile TEXT Path to a file to read URLs from
-l, --list-url TEXT Enter a comma separated list of urls to download, enclosed within quotes
-v, --verbose Verbose
-o, --out-dir TEXT Path to the Output directory for files (default: Current Directory)
--format TEXT Download Format: epub (default), mobi, pdf or html [default: epub]
--force / --no-force Force overwrite of an existing file [default: no-force]
--get-urls TEXT Get all story urls found from a page. Currently supports archiveofourown.org only
-ss, --supported-sites List of supported sites
-d, --debug Show the log in the console for debugging
--log / --no-log Save the logfile for debugging [default: no-log]
--version / --no-version Display version & quit [default: no-version]
--help Show this message and exit.
```

# Default Configuration

- The fanfiction will be downloaded in epub format. To change it, use `-f` followed by the format.
- The fanfiction will be downloaded in the current directory. To change it, use `-o` followed by the path to the directory.
- Failed downloads will be saved in the `err.log` file in the current directory.
- `--meta-json` takes either URL or a file containing a list of URLs. `--out-dir` can be used to select an output directory.

Check `fichub_cli --help` for more info.

Expand All @@ -83,7 +84,7 @@ fichub_cli -l "https://www.fanfiction.net/s/11191235/1/Harry-Potter-and-the-Prin
---

**NOTE**
`--out-dir` can be used in all the above commands to select an output directory.
`--out-dir` or `-o` can be used in all the above commands to select an output directory.

---

Expand All @@ -93,20 +94,11 @@ fichub_cli -l "https://www.fanfiction.net/s/11191235/1/Harry-Potter-and-the-Prin
fichub_cli --get-urls https://archiveofourown.org/users/flamethrower/
```

- To fetch only the metadata for the fanfiction in json format.
# Plugins

```
fichub_cli --meta-json "https://www.fanfiction.net/s/12933896/1/Things-you-cannot-leave-behind"
```

```
fichub_cli --meta-json urls.txt
```

```
fichub_cli --meta-json urls.txt --out-dir "~/Desktop/books"
```
- [fichub-cli-metadata](https://github.com/fichub-cli-contrib/fichub-cli-metadata): A metadata plugin to fetch Metadata from the Fichub API

# Links

- [Plugins](https://github.com/fichub-cli-contrib/)
- [Official Discord Server](https://discord.gg/sByBAhX)
105 changes: 70 additions & 35 deletions fichub_cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,75 @@
import click
import typer
import sys
from loguru import logger
from datetime import datetime
from colorama import init, Fore, Style

from .utils.processing import get_format_type
import importlib
import pkgutil

from .utils.fetch_data import FetchData
from .utils.processing import get_format_type


init(autoreset=True) # colorama init
timestamp = datetime.now().strftime("%Y-%m-%d T%H%M%S")

app = typer.Typer(add_completion=False)

discovered_plugins = {
name: importlib.import_module(name)
for finder, name, ispkg
in pkgutil.iter_modules()
if name.startswith('fichub_cli_')
}

for plugin in discovered_plugins.values():
app.add_typer(plugin.app)


# @logger.catch # for internal debugging
@click.command(no_args_is_help=True)
@click.option('-u', '--url', help='The url of the fanfiction enclosed within quotes')
@click.option('-i', '--infile', help='Give a filename to read URLs from')
@click.option('-l', '--list-url', 'list_url', help='Enter a comma separated list of urls to download, enclosed within quotes')
@click.option('-v', '--verbose', default=False, help='Verbose progressbar', is_flag=True)
@click.option('-o', '--out-dir', 'out_dir', default="", help='Absolute path to the Output directory for files (default: Current Directory)')
@click.option('-f', '--format', '_format', default="epub", help='Download Format: epub (default), mobi, pdf or html')
@click.option('--force', default=False, help=' Force overwrite of an existing file', is_flag=True)
@click.option('--get-urls', 'get_urls', default=None, help='Get all story urls found from a page. Currently supports archiveofourown.org only')
@click.option('-s', '--supported-sites', 'supported_sites', default=False, help='List of supported sites', is_flag=True)
@click.option('-d', '--debug', default=False, help='Show the log in the console for debugging', is_flag=True)
@click.option('--meta-json', 'meta_json', default=None, help='Fetch only the metadata for the fanfiction in json format')
@click.option('--log', default=False, help='Save the logfile for debugging', is_flag=True)
@click.option('-a', '--automated', default=False, help='For internal testing only', is_flag=True, hidden=True)
@click.option('--pytest', default=False, help='To run pytest on the CLI for internal testing', is_flag=True, hidden=True)
@click.option('--version', default=False, help='Display version & quit', is_flag=True)
def run_cli(infile: str, url: str, list_url: str, _format: str, get_urls: str,
out_dir: str, debug: bool, version: bool, log: bool,
supported_sites: bool, force: bool, automated: bool,
meta_json: str, verbose: bool, pytest: bool):
@app.callback(no_args_is_help=True, invoke_without_command=True)
def default(
ctx: typer.Context,
url: str = typer.Option(
"", "-u", "--url", help="The url of the fanfiction enclosed within quotes"),

infile: str = typer.Option(
"", "-i", "--infile", help="Path to a file to read URLs from"),

list_url: str = typer.Option(
"", "-l", "--list-url", help="Enter a comma separated list of urls to download, enclosed within quotes"),

verbose: bool = typer.Option(
False, "-v", "--verbose", help="Verbose", is_flag=True),

out_dir: str = typer.Option(
"", "-o", " --out-dir", help="Path to the Output directory for files (default: Current Directory)"),

format: str = typer.Option(
"epub", help="Download Format: epub (default), mobi, pdf or html"),

force: bool = typer.Option(
False, help="Force overwrite of an existing file", is_flag=True),

get_urls: str = typer.Option(
"", help="Get all story urls found from a page. Currently supports archiveofourown.org only"),

supported_sites: bool = typer.Option(
False, "-ss", "--supported-sites", help="List of supported sites", is_flag=True),

debug: bool = typer.Option(
False, "-d", " --debug", help="Show the log in the console for debugging", is_flag=True),

log: bool = typer.Option(
False, help="Save the logfile for debugging", is_flag=True),

automated: bool = typer.Option(
False, "-a", "--automated", help="For internal testing only", is_flag=True, hidden=True),

version: bool = typer.Option(
False, help="Display version & quit", is_flag=True)
):
"""
A CLI for the fichub.net API
Expand All @@ -41,17 +79,19 @@ def run_cli(infile: str, url: str, list_url: str, _format: str, get_urls: str,
Failed downloads will be saved in the `err.log` file in the current directory.
"""
if pytest: # for internal testing
import pytest
pytest.main(['-v'])
if ctx.invoked_subcommand is not None:
if debug:
typer.echo(
Fore.BLUE + "Skipping default command to run sub-command.")
return

if log:
debug = True
click.echo(
typer.echo(
Fore.GREEN + f"Creating fichub_cli - {timestamp}.log in the current directory")
logger.add(f"fichub_cli - {timestamp}.log")

format_type = get_format_type(_format)
format_type = get_format_type(format)
if infile:
fic = FetchData(format_type, out_dir, force,
debug, automated, verbose)
Expand All @@ -71,16 +111,11 @@ def run_cli(infile: str, url: str, list_url: str, _format: str, get_urls: str,
fic = FetchData(debug=debug, automated=automated)
fic.get_urls_from_page(get_urls)

elif meta_json:
fic = FetchData(debug=debug, automated=automated,
out_dir=out_dir)
fic.get_metadata(meta_json)

if version:
click.echo("Version: 0.4.5")
typer.echo("fichub-cli: v0.5.0")

if supported_sites:
click.echo(Fore.GREEN + """
typer.echo(Fore.GREEN + """
Supported Sites:""" + Style.RESET_ALL + """
- SpaceBattles, SufficientVelocity, QuestionableQuesting (XenForo)
Expand All @@ -107,7 +142,7 @@ def run_cli(infile: str, url: str, list_url: str, _format: str, get_urls: str,
""")
try:
if fic.exit_status == 1:
click.echo(Fore.RED + """
typer.echo(Fore.RED + """
Unsupported URLs found! Check err.log in the current directory!""" + Style.RESET_ALL)
sys.exit(fic.exit_status)
except UnboundLocalError:
Expand Down
61 changes: 1 addition & 60 deletions fichub_cli/utils/fetch_data.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import re
import os
from datetime import datetime
import requests
from tqdm import tqdm
from colorama import Fore, Style
Expand All @@ -10,7 +8,7 @@

from .fichub import FicHub
from .logging import init_log, download_processing_log, \
verbose_log, meta_fetched_log
verbose_log
from .processing import check_url, save_data

bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt}, {rate_fmt}{postfix}, ETA: {remaining}"
Expand Down Expand Up @@ -257,60 +255,3 @@ def get_urls_from_page(self, get_urls: str):
if found_flag is False:
tqdm.write(Fore.RED + "\nFound 0 urls.")
self.exit_status = 1

def get_metadata(self, _input: str):

meta_list = []
file_name = "metadata"
supported_url = None

# check if the input is a file
if os.path.isfile(_input):
if self.debug:
logger.info(f"Input file: {_input}")
# get the tail
_, file_name = os.path.split(_input)
file_name = os.path.splitext(file_name)[0]
with open(_input, "r") as f:
urls = f.read().splitlines()

else:
if self.debug:
logger.info("Input is an URL")
urls = [_input]

with tqdm(total=len(urls), ascii=False,
unit="url", bar_format=bar_format) as pbar:

for url in urls:
download_processing_log(self.debug, url)
pbar.update(1)
supported_url, self.exit_status = check_url(
url, self.debug, self.exit_status)

if supported_url:
fic = FicHub(self.debug, self.automated,
self.exit_status)
fic.get_fic_extraMetadata(url)

if fic.fic_extraMetadata:
meta_list.append(fic.fic_extraMetadata)
meta_fetched_log(self.debug, url)
else:
supported_url = None

meta_data = "{\"meta\": ["+", ".join(meta_list)+"]}"
timestamp = datetime.now().strftime("%Y-%m-%d T%H%M%S")
json_file = os.path.join(
self.out_dir, file_name) + f" - {timestamp}.json"

if meta_list:
with open(json_file, "w") as outfile:
if self.debug:
logger.info(f"Saving {json_file}")
outfile.write(meta_data)

tqdm.write(Fore.GREEN +
"\nMetadata saved as " + Fore.BLUE +
f"{os.path.abspath(json_file)}"+Style.RESET_ALL +
Style.RESET_ALL)
33 changes: 1 addition & 32 deletions fichub_cli/utils/fichub.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
from colorama import Fore, Style
from tqdm import tqdm
from loguru import logger
import json

headers = {
'User-Agent': 'fichub_cli/0.4.5',
'User-Agent': 'fichub_cli/0.5.0',
}

retry_strategy = Retry(
Expand Down Expand Up @@ -105,33 +104,3 @@ def get_fic_data(self, download_url: str):
if self.debug:
logger.debug(
f"GET: {self.response_data.status_code}: {self.response_data.url}")

def get_fic_extraMetadata(self, url: str):

params = {'q': url}
if self.automated: # for internal testing
params['automated'] = 'true'
if self.debug:
logger.debug(
"--automated flag was passed. Internal Testing mode is on.")

response = self.http.get(
"https://fichub.net/api/v0/epub", params=params,
allow_redirects=True, headers=headers, timeout=(6.1, 300)
)

if self.debug:
logger.debug(f"GET: {response.status_code}: {response.url}")

try:
self.response = response.json()
self.fic_extraMetadata = json.dumps(
self.response['meta'], indent=4)

# if metadata not found
except KeyError:
self.fic_extraMetadata = ""
tqdm.write(
Fore.RED + f"Skipping unsupported URL: {url}" +
Style.RESET_ALL + Fore.CYAN +
"\nReport the error if the URL is supported!")
7 changes: 0 additions & 7 deletions fichub_cli/utils/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,3 @@ def verbose_log(debug: bool, fic):
# Reason: Unsupported url
except KeyError:
pass


def meta_fetched_log(debug: bool, url: str):
if debug:
logger.info(f"Metadata fetched for {url}")
else:
tqdm.write(Fore.GREEN + f"Metadata fetched for {url}")
Loading

0 comments on commit 35a8a03

Please sign in to comment.