Bundling webserver into RTV

This commit is contained in:
Théo Piboubès
2015-08-20 00:49:25 +02:00
parent 84039aa061
commit b25b533783
5 changed files with 59 additions and 17 deletions

View File

@@ -1,2 +1,3 @@
include version.py include version.py
include CHANGELOG.rst CONTRIBUTORS.rst LICENSE include CHANGELOG.rst CONTRIBUTORS.rst LICENSE
include rtv/templates/*.html

View File

@@ -152,7 +152,7 @@ def main():
reddit.config.decode_html_entities = False reddit.config.decode_html_entities = False
with curses_session() as stdscr: with curses_session() as stdscr:
oauth = OAuthTool(reddit, stdscr, LoadScreen(stdscr)) oauth = OAuthTool(reddit, stdscr, LoadScreen(stdscr))
if args.auto_login == 'True': if args.auto_login == 'True': # Ew!
oauth.authorize() oauth.authorize()
if args.link: if args.link:
page = SubmissionPage(stdscr, reddit, oauth, url=args.link) page = SubmissionPage(stdscr, reddit, oauth, url=args.link)
@@ -160,8 +160,6 @@ def main():
subreddit = args.subreddit or 'front' subreddit = args.subreddit or 'front'
page = SubredditPage(stdscr, reddit, oauth, subreddit) page = SubredditPage(stdscr, reddit, oauth, subreddit)
page.loop() page.loop()
except praw.errors.InvalidUserPass:
print('Invalid password for username: {}'.format(args.username))
except praw.errors.OAuthAppRequired: except praw.errors.OAuthAppRequired:
print('Invalid OAuth app config parameters') print('Invalid OAuth app config parameters')
except praw.errors.OAuthInvalidToken: except praw.errors.OAuthInvalidToken:

View File

@@ -10,5 +10,5 @@ OAuth settings
oauth_client_id = 'nxoobnwO7mCP5A' oauth_client_id = 'nxoobnwO7mCP5A'
oauth_client_secret = 'praw_gapfill' oauth_client_secret = 'praw_gapfill'
oauth_redirect_uri = 'https://rtv.theo-piboubes.fr/auth' oauth_redirect_uri = 'http://127.0.0.1:65000/auth'
oauth_scope = 'edit-history-identity-mysubreddits-privatemessages-read-report-save-submit-subscribe-vote' oauth_scope = 'edit-history-identity-mysubreddits-privatemessages-read-report-save-submit-subscribe-vote'

View File

@@ -1,4 +1,4 @@
import configparser from six.moves import configparser
import curses import curses
import logging import logging
import os import os
@@ -11,11 +11,37 @@ import praw
from . import config from . import config
from .curses_helpers import show_notification, prompt_input from .curses_helpers import show_notification, prompt_input
from tornado import ioloop, web
__all__ = ['token_validity', 'OAuthTool'] __all__ = ['token_validity', 'OAuthTool']
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
token_validity = 3540 token_validity = 3540
oauth_state = None
oauth_code = None
oauth_error = None
class HomeHandler(web.RequestHandler):
def get(self):
self.render('home.html')
class AuthHandler(web.RequestHandler):
def get(self):
global oauth_state
global oauth_code
global oauth_error
oauth_state = self.get_argument('state', default='state_placeholder')
oauth_code = self.get_argument('code', default='code_placeholder')
oauth_error = self.get_argument('error', default='error_placeholder')
self.render('auth.html', state=oauth_state, code=oauth_code, error=oauth_error)
ioloop.IOLoop.current().stop()
class OAuthTool(object): class OAuthTool(object):
def __init__(self, reddit, stdscr=None, loader=None, def __init__(self, reddit, stdscr=None, loader=None,
@@ -38,6 +64,13 @@ class OAuthTool(object):
self.token_expiration = 0 self.token_expiration = 0
# Initialize Tornado webapp and listen on port 65000
self.callback_app = web.Application([
(r'/', HomeHandler),
(r'/auth', AuthHandler),
], template_path='rtv/templates')
self.callback_app.listen(65000)
def get_config_fp(self): def get_config_fp(self):
HOME = os.path.expanduser('~') HOME = os.path.expanduser('~')
XDG_CONFIG_HOME = os.getenv('XDG_CONFIG_HOME', XDG_CONFIG_HOME = os.getenv('XDG_CONFIG_HOME',
@@ -105,27 +138,37 @@ class OAuthTool(object):
permission_ask_page_link = self.reddit.get_authorize_url(str(hex_uuid), permission_ask_page_link = self.reddit.get_authorize_url(str(hex_uuid),
scope=self.scope, refreshable=True) scope=self.scope, refreshable=True)
webbrowser.open(permission_ask_page_link) with self.loader(message='Waiting for authorization'):
show_notification(self.stdscr, ['Access prompt opened in web browser']) webbrowser.open(permission_ask_page_link)
final_state = prompt_input(self.stdscr, 'State: ') ioloop.IOLoop.current().start()
final_code = prompt_input(self.stdscr, 'Code: ')
if not final_state or not final_code: global oauth_state
curses.flash() global oauth_code
global oauth_error
self.final_state = oauth_state
self.final_code = oauth_code
self.final_error = oauth_error
# Check if access was denied
if self.final_error == 'access_denied':
show_notification(self.stdscr, ['Declined access'])
return
elif self.final_error != 'error_placeholder':
show_notification(self.stdscr, ['Authentication error'])
return return
# Check if UUID matches obtained state # Check if UUID matches obtained state
# (if not, authorization process is compromised, and I'm giving up) # (if not, authorization process is compromised, and I'm giving up)
if hex_uuid != final_state: elif hex_uuid != self.final_state:
show_notification(self.stdscr, ['UUID mismatch, stopping.']) show_notification(self.stdscr, ['UUID mismatch, stopping.'])
return return
# Get access information (tokens and scopes)
self.access_info = self.reddit.get_access_information(final_code)
try: try:
with self.loader(message='Logging in'): with self.loader(message='Logging in'):
# Get access information (tokens and scopes)
self.access_info = self.reddit.get_access_information(self.final_code)
self.reddit.set_access_credentials( self.reddit.set_access_credentials(
scope=set(self.access_info['scope']), scope=set(self.access_info['scope']),
access_token=self.access_info['access_token'], access_token=self.access_info['access_token'],

View File

@@ -13,7 +13,7 @@ setup(
keywords='reddit terminal praw curses', keywords='reddit terminal praw curses',
packages=['rtv'], packages=['rtv'],
include_package_data=True, include_package_data=True,
install_requires=['praw>=3.1.0', 'six', 'requests', 'kitchen'], install_requires=['tornado', 'praw>=3.1.0', 'six', 'requests', 'kitchen'],
entry_points={'console_scripts': ['rtv=rtv.__main__:main']}, entry_points={'console_scripts': ['rtv=rtv.__main__:main']},
classifiers=[ classifiers=[
'Intended Audience :: End Users/Desktop', 'Intended Audience :: End Users/Desktop',