first commit.

This commit is contained in:
Dave G
2018-03-07 23:57:52 -05:00
commit c580bbd913
15 changed files with 615 additions and 0 deletions

0
rfd/README.md Normal file
View File

0
rfd/__init__.py Normal file
View File

102
rfd/api.py Normal file
View File

@@ -0,0 +1,102 @@
"""RFD API."""
from math import ceil
import requests
from bs4 import BeautifulSoup
try:
from urllib.parse import urlparse # python 3
except ImportError:
from urlparse import urlparse # python 2
def build_web_path(slug):
return "https://forums.redflagdeals.com{}".format(slug)
def extract_post_id(url):
return url.split('/')[3].split('-')[-1]
def is_int(number):
try:
int(number)
return True
except ValueError:
return False
def get_vote_score(up_vote, down_vote):
return up_vote - down_vote
def get_safe_per_page(limit):
if limit < 5:
return 5
elif limit > 40:
return 40
return limit
def users_to_dict(users):
users_dict = {}
for user in users:
users_dict[user.get('user_id')] = user.get('username')
return users_dict
def strip_html(text):
return BeautifulSoup(text, "html.parser").get_text()
def is_valid_url(url):
result = urlparse(url)
return all([result.scheme, result.netloc, result.path])
def get_threads(forum_id, limit):
threads = []
response = requests.get(
"https://forums.redflagdeals.com/api/topics?forum_id={}&per_page={}".format(forum_id, get_safe_per_page(limit)))
for topic in response.json().get('topics'):
threads.append({
'title': topic.get('title'),
'score': get_vote_score(topic.get('votes').get('total_up'), topic.get('votes').get('total_down')),
'url': build_web_path(topic.get('web_path')),
})
return threads[:limit]
def get_posts(post, limit=5):
if is_valid_url(post):
post_id = extract_post_id(post)
elif is_int(post):
post_id = post
else:
raise ValueError()
if limit == 0:
response = requests.get(
"https://forums.redflagdeals.com/api/topics/{}/posts?per_page=40&page=1".format(post_id))
pages = response.json().get('pager').get('total_pages')
elif limit > 40:
pages = ceil(limit / 40)
else:
pages = 1
# Go through as many pages as necessary
for page in range(pages):
page = page + 1 # page 0 causes issues
response = requests.get(
"https://forums.redflagdeals.com/api/topics/{}/posts?per_page={}&page={}".format(post_id,
get_safe_per_page(
limit),
page))
users = users_to_dict(response.json().get('users'))
for _post in response.json().get('posts'):
yield{
'body': strip_html(_post.get('body')),
'score': get_vote_score(_post.get('votes').get('total_up'), _post.get('votes').get('total_down')),
'user': users[_post.get('author_id')],
}

91
rfd/rfd_cli.py Normal file
View File

@@ -0,0 +1,91 @@
import sys
import os
import click
from colorama import init, Fore, Style
from rfd.api import get_threads, get_posts
init()
print()
def get_terminal_width():
_, columns = os.popen('stty size', 'r').read().split()
return int(columns)
def get_vote_color(score):
if score > 0:
return Fore.GREEN + " [+" + str(score) + "] "
elif score < 0:
return Fore.RED + " [" + str(score) + "] "
return Fore.BLUE + " [" + str(score) + "] "
@click.group()
def cli():
"""Welcome to the RFD CLI. (RedFlagDeals.com)"""
pass
@cli.command(short_help="Displays posts in a specific thread.")
@click.option('--count', default=5, help='Number of topics. 0 for all topics')
@click.argument('post_id')
def posts(count, post_id):
"""Displays posts in a specific 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
"""
if count < 0:
click.echo("Invalid count.")
sys.exit(1)
try:
click.echo("-" * get_terminal_width())
for post in get_posts(post_id, count):
click.echo(" -" + get_vote_color(post.get('score')) + Fore.RESET +
post.get('body') + Fore.YELLOW + " ({})".format(post.get('user')))
click.echo(Style.RESET_ALL)
click.echo("-" * get_terminal_width())
except ValueError:
click.echo("Invalid post id.")
sys.exit(1)
except AttributeError:
click.echo("AttributeError: RFD API did not return expected data.")
@cli.command(short_help="Displays threads in the specified forum.")
@click.option('--count', default=5, help='Number of topics.')
@click.argument('forum_id')
def threads(count, forum_id):
"""Displays threads 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
"""
_threads = get_threads(forum_id, count)
for i, thread in enumerate(_threads, 1):
click.echo(" " + str(i) + "." +
get_vote_color(thread.get('score')) + Fore.RESET + thread.get('title'))
click.echo(Fore.BLUE + " {}".format(thread.get('url')))
click.echo(Style.RESET_ALL)
if __name__ == '__main__':
cli()