improved handling of gopher connections and support for animated gif
This commit is contained in:
parent
2413c1bf19
commit
dc7e9156c8
|
@ -73,7 +73,7 @@ To avoid using unstable or too recent libraries, the rule of thumb is that a lib
|
||||||
* [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup) and [Readability](https://github.com/buriy/python-readability) are both needed to render HTML. Without them, HTML will not be rendered or be sent to an external parser like Lynx. (apt-get install python3-bs4 python3-readability or pip3 install readability-lxml)
|
* [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup) and [Readability](https://github.com/buriy/python-readability) are both needed to render HTML. Without them, HTML will not be rendered or be sent to an external parser like Lynx. (apt-get install python3-bs4 python3-readability or pip3 install readability-lxml)
|
||||||
* [Python-feedparser](https://github.com/kurtmckee/feedparser) will allow parsing of RSS/Atom feeds and thus subscriptions to them. (apt-get install python3-feedparser)
|
* [Python-feedparser](https://github.com/kurtmckee/feedparser) will allow parsing of RSS/Atom feeds and thus subscriptions to them. (apt-get install python3-feedparser)
|
||||||
* The [ansiwrap library](https://pypi.org/project/ansiwrap/) may result in
|
* The [ansiwrap library](https://pypi.org/project/ansiwrap/) may result in
|
||||||
neater display of text which makes use of ANSI escape codes to control colour (not in Debian?).
|
neater display of text which makes use of ANSI escape codes to control colour. Ansiwrap is also required to display pictures in HTML pages (together with Chafa and python-pil) (not in Debian?).
|
||||||
* The [cryptography library](https://pypi.org/project/cryptography/) will
|
* The [cryptography library](https://pypi.org/project/cryptography/) will
|
||||||
provide a better and slightly more secure experience when using the default
|
provide a better and slightly more secure experience when using the default
|
||||||
TOFU certificate validation mode and is highly recommended (apt-get install python3-cryptography).
|
TOFU certificate validation mode and is highly recommended (apt-get install python3-cryptography).
|
||||||
|
@ -81,6 +81,7 @@ To avoid using unstable or too recent libraries, the rule of thumb is that a lib
|
||||||
* [Python editor](https://github.com/fmoo/python-editor) is used to edit your lists with "list edit". (apt-get install python3-editor)
|
* [Python editor](https://github.com/fmoo/python-editor) is used to edit your lists with "list edit". (apt-get install python3-editor)
|
||||||
* [Xsel](http://www.vergenet.net/~conrad/software/xsel/) allows to `go` to the URL copied in the clipboard without having to paste it (both X and traditional clipboards are supported). Also needed to use the `copy` command. (apt-get install xsel)
|
* [Xsel](http://www.vergenet.net/~conrad/software/xsel/) allows to `go` to the URL copied in the clipboard without having to paste it (both X and traditional clipboards are supported). Also needed to use the `copy` command. (apt-get install xsel)
|
||||||
* [Chafa](https://hpjansson.org/chafa/) allows to display pictures in your console. Install it and browse to an HTML page with picture to see the magic.
|
* [Chafa](https://hpjansson.org/chafa/) allows to display pictures in your console. Install it and browse to an HTML page with picture to see the magic.
|
||||||
|
* [Python-pil](http://python-pillow.github.io/) is required to only display the first frame of animated gif with chafa.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
51
offpunk.py
51
offpunk.py
|
@ -52,9 +52,23 @@ except ModuleNotFoundError:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ansiwrap as textwrap
|
import ansiwrap as textwrap
|
||||||
|
_HAS_ANSIWRAP = True
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
print("Try installing python-ansiwrap for better rendering")
|
print("Try installing python-ansiwrap for better rendering")
|
||||||
import textwrap
|
import textwrap
|
||||||
|
_HAS_ANSIWRAP = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
if _HAS_ANSIWRAP and shutil.which('chafa'):
|
||||||
|
_RENDER_IMAGE = True
|
||||||
|
else:
|
||||||
|
print("chafa and ansiwrap are required to render images in terminal")
|
||||||
|
_RENDER_IMAGE = False
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("python-pil, chafa and ansiwrap are required to render images")
|
||||||
|
_RENDER_IMAGE = False
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
|
@ -586,12 +600,16 @@ class HtmlRenderer():
|
||||||
src = element.get("src")
|
src = element.get("src")
|
||||||
text = ""
|
text = ""
|
||||||
ansi_img = ""
|
ansi_img = ""
|
||||||
if shutil.which('chafa'):
|
if _RENDER_IMAGE:
|
||||||
abs_url = urllib.parse.urljoin(self.url, src)
|
abs_url = urllib.parse.urljoin(self.url, src)
|
||||||
g = GeminiItem(abs_url)
|
g = GeminiItem(abs_url)
|
||||||
if g.is_cache_valid():
|
if g.is_cache_valid():
|
||||||
img = g.get_cache_path()
|
img = g.get_cache_path()
|
||||||
return_code = subprocess.run("chafa --bg white -s 40 %s"%img, \
|
img_obj = Image.open(img)
|
||||||
|
if hasattr(img_obj,"n_frames") and img_obj.n_frames > 1:
|
||||||
|
# we remove all frames but the first one
|
||||||
|
img_obj.save(img,save_all=False)
|
||||||
|
return_code = subprocess.run("chafa --bg white -s 40 %s -w 1"%img, \
|
||||||
shell=True, capture_output=True)
|
shell=True, capture_output=True)
|
||||||
ansi_img = return_code.stdout.decode()
|
ansi_img = return_code.stdout.decode()
|
||||||
alt = element.get("alt")
|
alt = element.get("alt")
|
||||||
|
@ -644,8 +662,14 @@ class HtmlRenderer():
|
||||||
i_indent = ""
|
i_indent = ""
|
||||||
s_indent = i_indent
|
s_indent = i_indent
|
||||||
if line.strip() != "":
|
if line.strip() != "":
|
||||||
wrapped = textwrap.fill(line,width,initial_indent=i_indent,
|
try:
|
||||||
|
wrapped = textwrap.fill(line,width,initial_indent=i_indent,
|
||||||
subsequent_indent=s_indent)
|
subsequent_indent=s_indent)
|
||||||
|
except Exception as err:
|
||||||
|
wrapped = line
|
||||||
|
#print(self.url)
|
||||||
|
#print(err)
|
||||||
|
#crash
|
||||||
wrapped += "\n"
|
wrapped += "\n"
|
||||||
else:
|
else:
|
||||||
wrapped = ""
|
wrapped = ""
|
||||||
|
@ -1254,7 +1278,7 @@ class GeminiClient(cmd.Cmd):
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
elif gi.scheme in ("gopher"):
|
elif gi.scheme in ("gopher"):
|
||||||
gi = self._fetch_gopher(gi)
|
gi = self._fetch_gopher(gi,timeout=self.options["short_timeout"])
|
||||||
else:
|
else:
|
||||||
gi = self._fetch_over_network(gi)
|
gi = self._fetch_over_network(gi)
|
||||||
except UserAbortException:
|
except UserAbortException:
|
||||||
|
@ -1340,7 +1364,9 @@ class GeminiClient(cmd.Cmd):
|
||||||
gi.write_body(body,mime)
|
gi.write_body(body,mime)
|
||||||
return gi
|
return gi
|
||||||
|
|
||||||
def _fetch_gopher(self,gi):
|
def _fetch_gopher(self,gi,timeout=10):
|
||||||
|
if not looks_like_url(gi.url):
|
||||||
|
print("%s is not a valide url" %gi.url)
|
||||||
parsed =urllib.parse.urlparse(gi.url)
|
parsed =urllib.parse.urlparse(gi.url)
|
||||||
host = parsed.hostname
|
host = parsed.hostname
|
||||||
port = parsed.port or 70
|
port = parsed.port or 70
|
||||||
|
@ -1356,7 +1382,22 @@ class GeminiClient(cmd.Cmd):
|
||||||
else:
|
else:
|
||||||
itemtype = "1"
|
itemtype = "1"
|
||||||
selector = parsed.path
|
selector = parsed.path
|
||||||
|
addresses = socket.getaddrinfo(host, port, family=0,type=socket.SOCK_STREAM)
|
||||||
s = socket.create_connection((host,port))
|
s = socket.create_connection((host,port))
|
||||||
|
for address in addresses:
|
||||||
|
self._debug("Connecting to: " + str(address[4]))
|
||||||
|
s = socket.socket(address[0], address[1])
|
||||||
|
s.settimeout(timeout)
|
||||||
|
try:
|
||||||
|
s.connect(address[4])
|
||||||
|
break
|
||||||
|
except OSError as e:
|
||||||
|
err = e
|
||||||
|
else:
|
||||||
|
# If we couldn't connect to *any* of the addresses, just
|
||||||
|
# bubble up the exception from the last attempt and deny
|
||||||
|
# knowledge of earlier failures.
|
||||||
|
raise err
|
||||||
if parsed.query:
|
if parsed.query:
|
||||||
request = selector + "\t" + parsed.query
|
request = selector + "\t" + parsed.query
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue