mirror of
https://github.com/davegallant/rfd.git
synced 2025-08-07 09:02:32 +00:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
31ff0e480f | ||
|
d0103f0733 | ||
|
46af76750e | ||
|
8a9e84a30a | ||
|
062baa7707 | ||
|
31ed869d05 | ||
|
eb349c0ff9 | ||
|
f4afe538e5 | ||
|
0cb97f56e7 | ||
|
460ea6eef0 | ||
|
f73fdc71b6 | ||
|
398cb19161 | ||
|
1c28c9875e | ||
|
027e79739e | ||
|
2d98bc54f6 | ||
|
11837addf1 | ||
|
185700447e | ||
|
ae91f7e419 | ||
|
9ecc413eb0 | ||
|
6a4242434f |
10
.github/workflows/black.yml
vendored
Normal file
10
.github/workflows/black.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
name: Black
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: psf/black@stable
|
23
README.md
23
README.md
@@ -7,7 +7,7 @@
|
|||||||
<!-- BEGIN mktoc -->
|
<!-- BEGIN mktoc -->
|
||||||
- [Description](#description)
|
- [Description](#description)
|
||||||
- [Motivation](#motivation)
|
- [Motivation](#motivation)
|
||||||
- [Install](#install)
|
- [Installation](#installation)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [View Hot Deals](#view-hot-deals)
|
- [View Hot Deals](#view-hot-deals)
|
||||||
- [View and Sort Hot Deals](#view-and-sort-hot-deals)
|
- [View and Sort Hot Deals](#view-and-sort-hot-deals)
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
This is a CLI utility that allows you to view [Redflagdeals.com](https://forums.redflagdeals.com) on the command line.
|
This is a CLI utility that allows you to view [RedFlagDeals.com](https://forums.redflagdeals.com) on the command line.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -29,12 +29,25 @@ This is a CLI utility that allows you to view [Redflagdeals.com](https://forums.
|
|||||||
|
|
||||||
It is often faster to use a CLI than to load up a web page and navigate web elements. This tool can search for deals and sort them based on score and views. It is also able to load entire threads (without pagination) for additional analysis.
|
It is often faster to use a CLI than to load up a web page and navigate web elements. This tool can search for deals and sort them based on score and views. It is also able to load entire threads (without pagination) for additional analysis.
|
||||||
|
|
||||||
## Install
|
## Installation
|
||||||
|
|
||||||
```bash
|
### pip
|
||||||
pip install rfd
|
|
||||||
|
```sh
|
||||||
|
pip3 install --user rfd
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This can also be installed with [pipx](https://github.com/pypa/pipx).
|
||||||
|
|
||||||
|
### brew
|
||||||
|
|
||||||
|
If you have [brew](https://brew.sh):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install davegallant/public/rfd
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
All commands open up in a [terminal pager](https://en.wikipedia.org/wiki/Terminal_pager).
|
All commands open up in a [terminal pager](https://en.wikipedia.org/wiki/Terminal_pager).
|
||||||
|
109
poetry.lock
generated
109
poetry.lock
generated
@@ -19,7 +19,7 @@ pyyaml = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "astroid"
|
name = "astroid"
|
||||||
version = "2.5.6"
|
version = "2.8.0"
|
||||||
description = "An abstract syntax tree for Python with inference support."
|
description = "An abstract syntax tree for Python with inference support."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -28,6 +28,7 @@ python-versions = "~=3.6"
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
lazy-object-proxy = ">=1.4.0"
|
lazy-object-proxy = ">=1.4.0"
|
||||||
typed-ast = {version = ">=1.4.0,<1.5", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""}
|
typed-ast = {version = ">=1.4.0,<1.5", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""}
|
||||||
|
typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""}
|
||||||
wrapt = ">=1.11,<1.13"
|
wrapt = ">=1.11,<1.13"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -54,14 +55,14 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beautifulsoup4"
|
name = "beautifulsoup4"
|
||||||
version = "4.9.3"
|
version = "4.10.0"
|
||||||
description = "Screen-scraping library"
|
description = "Screen-scraping library"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = ">3.0.0"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""}
|
soupsieve = ">1.2"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
html5lib = ["html5lib"]
|
html5lib = ["html5lib"]
|
||||||
@@ -84,20 +85,27 @@ optional = false
|
|||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chardet"
|
name = "charset-normalizer"
|
||||||
version = "4.0.0"
|
version = "2.0.1"
|
||||||
description = "Universal encoding detector for Python 2 and 3"
|
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=3.5.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
unicode_backport = ["unicodedata2"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "7.1.2"
|
version = "8.0.1"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
|
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
@@ -146,7 +154,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "4.0.1"
|
version = "4.0.1"
|
||||||
description = "Read metadata from Python packages"
|
description = "Read metadata from Python packages"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
@@ -229,6 +237,18 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyparsing = ">=2.0.2"
|
pyparsing = ">=2.0.2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "2.3.0"
|
||||||
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
|
||||||
|
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
@@ -273,18 +293,20 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pylint"
|
name = "pylint"
|
||||||
version = "2.8.2"
|
version = "2.11.1"
|
||||||
description = "python code static checker"
|
description = "python code static checker"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "~=3.6"
|
python-versions = "~=3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
astroid = ">=2.5.6,<2.7"
|
astroid = ">=2.8.0,<2.9"
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
isort = ">=4.2.5,<6"
|
isort = ">=4.2.5,<6"
|
||||||
mccabe = ">=0.6,<0.7"
|
mccabe = ">=0.6,<0.7"
|
||||||
|
platformdirs = ">=2.2.0"
|
||||||
toml = ">=0.7.1"
|
toml = ">=0.7.1"
|
||||||
|
typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyparsing"
|
name = "pyparsing"
|
||||||
@@ -296,7 +318,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "6.2.3"
|
version = "6.2.5"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -309,7 +331,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
||||||
iniconfig = "*"
|
iniconfig = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
pluggy = ">=0.12,<1.0.0a1"
|
pluggy = ">=0.12,<2.0"
|
||||||
py = ">=1.8.2"
|
py = ">=1.8.2"
|
||||||
toml = "*"
|
toml = "*"
|
||||||
|
|
||||||
@@ -326,32 +348,32 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.25.1"
|
version = "2.26.0"
|
||||||
description = "Python HTTP for Humans."
|
description = "Python HTTP for Humans."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
certifi = ">=2017.4.17"
|
certifi = ">=2017.4.17"
|
||||||
chardet = ">=3.0.2,<5"
|
charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
|
||||||
idna = ">=2.5,<3"
|
idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
|
||||||
urllib3 = ">=1.21.1,<1.27"
|
urllib3 = ">=1.21.1,<1.27"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
|
|
||||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||||
|
use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rope"
|
name = "rope"
|
||||||
version = "0.19.0"
|
version = "0.20.1"
|
||||||
description = "a python refactoring library..."
|
description = "a python refactoring library..."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["pytest"]
|
dev = ["pytest", "pytest-timeout"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
@@ -389,7 +411,7 @@ python-versions = "*"
|
|||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "3.10.0.0"
|
version = "3.10.0.0"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.5+"
|
description = "Backported and Experimental Type Hints for Python 3.5+"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
@@ -438,7 +460,7 @@ python-versions = "*"
|
|||||||
name = "zipp"
|
name = "zipp"
|
||||||
version = "3.4.1"
|
version = "3.4.1"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
@@ -449,7 +471,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
content-hash = "a0e1b38f299c25eb42448b06889d89ad93977c6b5909a8793a10f5c6f13bb2ad"
|
content-hash = "5ee93b78656e5bc815fc41056cd80448eac2f8cee62db11c140c7248ab8b2834"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
appdirs = [
|
appdirs = [
|
||||||
@@ -461,8 +483,8 @@ appdirs = [
|
|||||||
{file = "aspy.yaml-1.3.0.tar.gz", hash = "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"},
|
{file = "aspy.yaml-1.3.0.tar.gz", hash = "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"},
|
||||||
]
|
]
|
||||||
astroid = [
|
astroid = [
|
||||||
{file = "astroid-2.5.6-py3-none-any.whl", hash = "sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e"},
|
{file = "astroid-2.8.0-py3-none-any.whl", hash = "sha256:dcc06f6165f415220013801642bd6c9808a02967070919c4b746c6864c205471"},
|
||||||
{file = "astroid-2.5.6.tar.gz", hash = "sha256:8a398dfce302c13f14bab13e2b14fe385d32b73f4e4853b9bdfb64598baa1975"},
|
{file = "astroid-2.8.0.tar.gz", hash = "sha256:fe81f80c0b35264acb5653302ffbd935d394f1775c5e4487df745bf9c2442708"},
|
||||||
]
|
]
|
||||||
atomicwrites = [
|
atomicwrites = [
|
||||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||||
@@ -473,9 +495,8 @@ attrs = [
|
|||||||
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"},
|
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"},
|
||||||
]
|
]
|
||||||
beautifulsoup4 = [
|
beautifulsoup4 = [
|
||||||
{file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"},
|
{file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
|
||||||
{file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
|
{file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
|
||||||
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
|
|
||||||
]
|
]
|
||||||
certifi = [
|
certifi = [
|
||||||
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
|
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
|
||||||
@@ -485,13 +506,13 @@ cfgv = [
|
|||||||
{file = "cfgv-3.0.0-py2.py3-none-any.whl", hash = "sha256:f22b426ed59cd2ab2b54ff96608d846c33dfb8766a67f0b4a6ce130ce244414f"},
|
{file = "cfgv-3.0.0-py2.py3-none-any.whl", hash = "sha256:f22b426ed59cd2ab2b54ff96608d846c33dfb8766a67f0b4a6ce130ce244414f"},
|
||||||
{file = "cfgv-3.0.0.tar.gz", hash = "sha256:04b093b14ddf9fd4d17c53ebfd55582d27b76ed30050193c14e560770c5360eb"},
|
{file = "cfgv-3.0.0.tar.gz", hash = "sha256:04b093b14ddf9fd4d17c53ebfd55582d27b76ed30050193c14e560770c5360eb"},
|
||||||
]
|
]
|
||||||
chardet = [
|
charset-normalizer = [
|
||||||
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
|
{file = "charset-normalizer-2.0.1.tar.gz", hash = "sha256:ad0da505736fc7e716a8da15bf19a985db21ac6415c26b34d2fafd3beb3d927e"},
|
||||||
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
|
{file = "charset_normalizer-2.0.1-py3-none-any.whl", hash = "sha256:b68b38179052975093d71c1b5361bf64afd80484697c1f27056e50593e695ceb"},
|
||||||
]
|
]
|
||||||
click = [
|
click = [
|
||||||
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
|
||||||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
{file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
|
||||||
]
|
]
|
||||||
colorama = [
|
colorama = [
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
@@ -565,6 +586,10 @@ packaging = [
|
|||||||
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
|
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
|
||||||
{file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
|
{file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
|
||||||
]
|
]
|
||||||
|
platformdirs = [
|
||||||
|
{file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"},
|
||||||
|
{file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"},
|
||||||
|
]
|
||||||
pluggy = [
|
pluggy = [
|
||||||
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
||||||
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
||||||
@@ -578,16 +603,16 @@ py = [
|
|||||||
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
|
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
|
||||||
]
|
]
|
||||||
pylint = [
|
pylint = [
|
||||||
{file = "pylint-2.8.2-py3-none-any.whl", hash = "sha256:f7e2072654a6b6afdf5e2fb38147d3e2d2d43c89f648637baab63e026481279b"},
|
{file = "pylint-2.11.1-py3-none-any.whl", hash = "sha256:0f358e221c45cbd4dad2a1e4b883e75d28acdcccd29d40c76eb72b307269b126"},
|
||||||
{file = "pylint-2.8.2.tar.gz", hash = "sha256:586d8fa9b1891f4b725f587ef267abe2a1bad89d6b184520c7f07a253dd6e217"},
|
{file = "pylint-2.11.1.tar.gz", hash = "sha256:2c9843fff1a88ca0ad98a256806c82c5a8f86086e7ccbdb93297d86c3f90c436"},
|
||||||
]
|
]
|
||||||
pyparsing = [
|
pyparsing = [
|
||||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||||
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
|
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
|
||||||
]
|
]
|
||||||
pytest = [
|
pytest = [
|
||||||
{file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"},
|
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
|
||||||
{file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"},
|
{file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
|
||||||
]
|
]
|
||||||
pyyaml = [
|
pyyaml = [
|
||||||
{file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
|
{file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
|
||||||
@@ -621,11 +646,11 @@ pyyaml = [
|
|||||||
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
|
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
|
||||||
]
|
]
|
||||||
requests = [
|
requests = [
|
||||||
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
|
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
|
||||||
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
|
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
|
||||||
]
|
]
|
||||||
rope = [
|
rope = [
|
||||||
{file = "rope-0.19.0.tar.gz", hash = "sha256:64e6d747532e1f5c8009ec5aae3e5523a5bcedf516f39a750d57d8ed749d90da"},
|
{file = "rope-0.20.1.tar.gz", hash = "sha256:505a2f6b4ac7b18e0429be179f4d8712243a194da5c866b0731f9d91ce7590bb"},
|
||||||
]
|
]
|
||||||
six = [
|
six = [
|
||||||
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
|
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "rfd"
|
name = "rfd"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
description = "view RedFlagDeals.com from the command line"
|
description = "view RedFlagDeals.com from the command line"
|
||||||
authors = ["Dave Gallant <davegallant@gmail.com>"]
|
authors = ["Dave Gallant <davegallant@gmail.com>"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
@@ -8,7 +8,7 @@ readme = "README.md"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
beautifulsoup4 = "<4.9.4"
|
beautifulsoup4 = "<4.10.1"
|
||||||
click = ">=7.0"
|
click = ">=7.0"
|
||||||
colorama = ">=0.4.3"
|
colorama = ">=0.4.3"
|
||||||
requests = ">=2.22.0"
|
requests = ">=2.22.0"
|
||||||
@@ -16,9 +16,12 @@ soupsieve = "<3.0"
|
|||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pre-commit = "1.21.0"
|
pre-commit = "1.21.0"
|
||||||
pylint = "^2.8.2"
|
pylint = "^2.11.1"
|
||||||
pytest = ">=4.6.6"
|
pytest = ">=4.6.6"
|
||||||
rope = "0.19.0"
|
rope = "0.20.1"
|
||||||
|
|
||||||
|
[tool.poetry.scripts]
|
||||||
|
rfd = "rfd.__main__:cli"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
0.7.0
|
|
@@ -1,12 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from os.path import dirname, abspath, join
|
|
||||||
|
|
||||||
|
|
||||||
def load_version():
|
|
||||||
with open(join(dirname(abspath(__file__)), "VERSION")) as handle:
|
|
||||||
return handle.read()
|
|
||||||
|
|
||||||
|
|
||||||
version = load_version()
|
|
16
rfd/api.py
16
rfd/api.py
@@ -27,7 +27,7 @@ def get_safe_per_page(limit):
|
|||||||
|
|
||||||
def create_user_map(users):
|
def create_user_map(users):
|
||||||
"""Create a map of user ids to usernames."""
|
"""Create a map of user ids to usernames."""
|
||||||
m = dict()
|
m = {}
|
||||||
for user in users:
|
for user in users:
|
||||||
m[user.get("user_id")] = user.get("username")
|
m[user.get("user_id")] = user.get("username")
|
||||||
return m
|
return m
|
||||||
@@ -47,12 +47,12 @@ def get_threads(forum_id, pages):
|
|||||||
try:
|
try:
|
||||||
for page in range(1, pages + 1):
|
for page in range(1, pages + 1):
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
"{}/api/topics?forum_id={}&per_page=40&page={}".format(
|
f"{API_BASE_URL}/api/topics?forum_id={forum_id}&per_page=40&page={page}"
|
||||||
API_BASE_URL, forum_id, page
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise Exception("When collecting threads, received a status code: %s" % response.status_code)
|
raise Exception(
|
||||||
|
f"When collecting threads, received a status code: {response.status_code}"
|
||||||
|
)
|
||||||
threads += response.json().get("topics")
|
threads += response.json().get("topics")
|
||||||
except JSONDecodeError as err:
|
except JSONDecodeError as err:
|
||||||
logging.error("Unable to decode threads. %s", err)
|
logging.error("Unable to decode threads. %s", err)
|
||||||
@@ -76,16 +76,14 @@ def get_posts(post):
|
|||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
"{}/api/topics/{}/posts?per_page=40&page=1".format(API_BASE_URL, post_id)
|
f"{API_BASE_URL}/api/topics/{post_id}/posts?per_page=40&page=1"
|
||||||
)
|
)
|
||||||
|
|
||||||
total_pages = response.json().get("pager").get("total_pages")
|
total_pages = response.json().get("pager").get("total_pages")
|
||||||
|
|
||||||
for page in range(0, total_pages + 1):
|
for page in range(0, total_pages + 1):
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
"{}/api/topics/{}/posts?per_page={}&page={}".format(
|
f"{API_BASE_URL}/api/topics/{post_id}/posts?per_page=40&page={page}"
|
||||||
API_BASE_URL, post_id, 40, page
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
users = create_user_map(response.json().get("users"))
|
users = create_user_map(response.json().get("users"))
|
||||||
|
|
||||||
|
18
rfd/cli.py
18
rfd/cli.py
@@ -4,11 +4,16 @@ from __future__ import unicode_literals
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
try:
|
||||||
|
from importlib import metadata
|
||||||
|
except ImportError: # for Python<3.8
|
||||||
|
import importlib_metadata as metadata
|
||||||
from colorama import init
|
from colorama import init
|
||||||
from .api import get_threads, get_posts
|
from .api import get_threads, get_posts
|
||||||
from .threads import parse_threads, search_threads, sort_threads, generate_thread_output
|
from .threads import parse_threads, search_threads, sort_threads, generate_thread_output
|
||||||
from .posts import generate_posts_output
|
from .posts import generate_posts_output
|
||||||
from .__version__ import version as current_version
|
|
||||||
|
|
||||||
init()
|
init()
|
||||||
|
|
||||||
@@ -18,12 +23,13 @@ logging.getLogger().addHandler(logging.StreamHandler())
|
|||||||
|
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
return "rfd v" + current_version
|
return "rfd v" + metadata.version("rfd")
|
||||||
|
|
||||||
def print_version(ctx, value):
|
|
||||||
|
def print_version(ctx, _, value):
|
||||||
if not value or ctx.resilient_parsing:
|
if not value or ctx.resilient_parsing:
|
||||||
return
|
return
|
||||||
click.echo(get_version(), nl=False)
|
click.echo(get_version(), nl=True)
|
||||||
ctx.exit()
|
ctx.exit()
|
||||||
|
|
||||||
|
|
||||||
@@ -87,7 +93,9 @@ def threads(forum_id, pages, sort_by):
|
|||||||
74 \t shopping discussion
|
74 \t shopping discussion
|
||||||
88 \t cell phones
|
88 \t cell phones
|
||||||
"""
|
"""
|
||||||
_threads = sort_threads(parse_threads(get_threads(forum_id, pages)), sort_by=sort_by)
|
_threads = sort_threads(
|
||||||
|
parse_threads(get_threads(forum_id, pages)), sort_by=sort_by
|
||||||
|
)
|
||||||
click.echo_via_pager(generate_thread_output(_threads))
|
click.echo_via_pager(generate_thread_output(_threads))
|
||||||
|
|
||||||
|
|
||||||
|
11
rfd/posts.py
11
rfd/posts.py
@@ -3,19 +3,22 @@ import os
|
|||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
from .scores import get_vote_color
|
from .scores import get_vote_color
|
||||||
|
|
||||||
|
|
||||||
class Post:
|
class Post:
|
||||||
def __init__(self, body, score, user):
|
def __init__(self, body, score, user):
|
||||||
self.body = body
|
self.body = body
|
||||||
self.score = score
|
self.score = score
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
|
|
||||||
def get_terminal_width():
|
def get_terminal_width():
|
||||||
_, columns = os.popen("stty size", "r").read().split()
|
_, columns = os.popen("stty size", "r").read().split()
|
||||||
return int(columns)
|
return int(columns)
|
||||||
|
|
||||||
|
|
||||||
def generate_posts_output(posts):
|
def generate_posts_output(posts):
|
||||||
output = ""
|
output = ""
|
||||||
output += ("-" * get_terminal_width())
|
output += "-" * get_terminal_width()
|
||||||
for post in posts:
|
for post in posts:
|
||||||
output += (
|
output += (
|
||||||
" -"
|
" -"
|
||||||
@@ -23,10 +26,10 @@ def generate_posts_output(posts):
|
|||||||
+ Fore.RESET
|
+ Fore.RESET
|
||||||
+ post.body
|
+ post.body
|
||||||
+ Fore.YELLOW
|
+ Fore.YELLOW
|
||||||
+ " ({})".format(post.user)
|
+ f" ({post.user})"
|
||||||
)
|
)
|
||||||
output += (Style.RESET_ALL)
|
output += Style.RESET_ALL
|
||||||
output += "\n"
|
output += "\n"
|
||||||
output += ("-" * get_terminal_width())
|
output += "-" * get_terminal_width()
|
||||||
output += "\n"
|
output += "\n"
|
||||||
return output
|
return output
|
||||||
|
@@ -3,7 +3,7 @@ from colorama import Fore, Style
|
|||||||
from . import API_BASE_URL
|
from . import API_BASE_URL
|
||||||
from .scores import calculate_score, get_vote_color
|
from .scores import calculate_score, get_vote_color
|
||||||
|
|
||||||
# pylint: disable=old-style-class
|
|
||||||
class Thread:
|
class Thread:
|
||||||
def __init__(self, title, dealer_name, score, url, views):
|
def __init__(self, title, dealer_name, score, url, views):
|
||||||
self.dealer_name = dealer_name
|
self.dealer_name = dealer_name
|
||||||
@@ -13,11 +13,11 @@ class Thread:
|
|||||||
self.views = views
|
self.views = views
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Thread(%s)" % self.title
|
return f"Thread({self.title})"
|
||||||
|
|
||||||
|
|
||||||
def build_web_path(slug):
|
def build_web_path(slug):
|
||||||
return "{}{}".format(API_BASE_URL, slug)
|
return f"{API_BASE_URL}{slug}"
|
||||||
|
|
||||||
|
|
||||||
def get_dealer(topic):
|
def get_dealer(topic):
|
||||||
@@ -88,12 +88,12 @@ def generate_thread_output(threads):
|
|||||||
+ "."
|
+ "."
|
||||||
+ get_vote_color(thread.score)
|
+ get_vote_color(thread.score)
|
||||||
+ Fore.RESET
|
+ Fore.RESET
|
||||||
+ "%s%s" % (dealer, thread.title)
|
+ f"{dealer}{thread.title}"
|
||||||
+ Fore.LIGHTYELLOW_EX
|
+ Fore.LIGHTYELLOW_EX
|
||||||
+ " (%d views)" % thread.views
|
+ f" ({thread.views} views)"
|
||||||
+ Fore.RESET
|
+ Fore.RESET
|
||||||
)
|
)
|
||||||
output += Fore.BLUE + " {}".format(thread.url)
|
output += Fore.BLUE + f" {thread.url}"
|
||||||
output += Style.RESET_ALL
|
output += Style.RESET_ALL
|
||||||
output += "\n\n"
|
output += "\n\n"
|
||||||
yield output
|
yield output
|
||||||
|
Reference in New Issue
Block a user