Fighting with mailcap

This commit is contained in:
Michael Lazar
2016-07-08 23:51:42 -07:00
parent 06ac572b20
commit 1d8c555c27
5 changed files with 60 additions and 4 deletions

View File

@@ -59,6 +59,9 @@ def build_parser():
parser.add_argument( parser.add_argument(
'--copy-config', dest='copy_config', action='store_const', const=True, '--copy-config', dest='copy_config', action='store_const', const=True,
help='Copy the default configuration to {HOME}/.config/rtv/rtv.cfg') help='Copy the default configuration to {HOME}/.config/rtv/rtv.cfg')
parser.add_argument(
'--enable-media', dest='enable_media', action='store_const', const=True,
help='Open external links using programs defined in the mailcap config')
return parser return parser

View File

@@ -1,7 +1,7 @@
import re import re
import mimetypes import mimetypes
from html.parser import HTMLParser
from six.moves.html_parser import HTMLParser
import requests import requests
@@ -116,7 +116,8 @@ class ImgurHandler(BaseHandler):
def get_mimetype(url): def get_mimetype(url):
imgur_page = requests.get(url) imgur_page = requests.get(url)
try: try:
ImgurHTMLParser().feed(imgur_page.text) # convert_charrefs will be true by default in python 3.5
ImgurHTMLParser(convert_charrefs=True).feed(imgur_page.text)
except HTMLParsed as data: except HTMLParsed as data:
# We found a link # We found a link
url = data.data url = data.data

View File

@@ -34,6 +34,9 @@ clear_auth = False
; Maximum number of opened links that will be saved in the history file. ; Maximum number of opened links that will be saved in the history file.
history_size = 200 history_size = 200
; Open external links using programs defined in the mailcap config.
enable_media = True
################ ################
# OAuth Settings # OAuth Settings
################ ################

View File

@@ -106,7 +106,7 @@ class SubredditPage(Page):
self.open_submission(url=data['url_full']) self.open_submission(url=data['url_full'])
self.config.history.add(data['url_full']) self.config.history.add(data['url_full'])
else: else:
self.term.open_browser(data['url_full']) self.term.open_link(data['url_full'])
self.config.history.add(data['url_full']) self.config.history.add(data['url_full'])
@SubredditController.register(Command('SUBREDDIT_POST')) @SubredditController.register(Command('SUBREDDIT_POST'))

View File

@@ -7,6 +7,7 @@ import time
import codecs import codecs
import curses import curses
import logging import logging
import mailcap
import tempfile import tempfile
import webbrowser import webbrowser
import subprocess import subprocess
@@ -19,8 +20,10 @@ import six
from kitchen.text.display import textual_width_chop from kitchen.text.display import textual_width_chop
from . import exceptions from . import exceptions
from . import mime_handlers
from .objects import LoadScreen, Color from .objects import LoadScreen, Color
try: try:
# Added in python 3.4+ # Added in python 3.4+
from html import unescape from html import unescape
@@ -49,6 +52,9 @@ class Terminal(object):
self.loader = LoadScreen(self) self.loader = LoadScreen(self)
self._display = None self._display = None
# TODO: Load from custom location
self._mailcap_dict = mailcap.getcaps()
@property @property
def up_arrow(self): def up_arrow(self):
symbol = '^' if self.config['ascii'] else '' symbol = '^' if self.config['ascii'] else ''
@@ -304,6 +310,49 @@ class Terminal(object):
return ch return ch
def open_link(self, url):
_logger.info('Opening link %s', url)
if not self.config['enable_media']:
return self.open_browser(url)
command = None
for handler in mime_handlers.handlers:
if handler.pattern.match(url):
modified_url, content_type = handler.get_mimetype(url)
_logger.info('MIME type: %s', content_type)
_logger.info('Modified url: %s', modified_url)
if not content_type or content_type == 'text/html':
# Could not figure out the Content-Type
return self.open_browser(modified_url)
# http://bugs.python.org/issue14977
command, entry = mailcap.findmatch(
self._mailcap_dict, content_type, filename=modified_url)
if not entry:
_logger.info('Could not find a valid mailcap entry')
return self.open_browser(modified_url)
break
with self.loader('Opening page in a new window', delay=0):
args = [command]
_logger.info('Running command: %s', args)
# Non-blocking, run with a full shell to support pipes
p = subprocess.Popen(
args, shell=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Wait a little while to make sure that the command doesn't exit
# with an error. This isn't perfect, but it should be good enough
# to catch invalid commands.
time.sleep(1.0)
code = p.poll()
if code is not None and code != 0:
stdout, stderr = p.communicate()
_logger.warning(stderr)
raise exceptions.BrowserError(
'Program exited with status=%s' % code)
def open_browser(self, url): def open_browser(self, url):
""" """
Open the given url using the default webbrowser. The preferred browser Open the given url using the default webbrowser. The preferred browser
@@ -346,7 +395,7 @@ class Terminal(object):
break # Success break # Success
elif code is not None: elif code is not None:
raise exceptions.BrowserError( raise exceptions.BrowserError(
'Browser exited with status=%s' % code) 'Program exited with status=%s' % code)
time.sleep(0.01) time.sleep(0.01)
else: else:
raise exceptions.BrowserError( raise exceptions.BrowserError(