forked from solderpunk/gemini-demo-1
Forked from solderpunk's repo
Added all of my current changes to gemini-demo.py, updated README.md and LICENSE
This commit is contained in:
parent
eca985da3e
commit
dcc4b804d2
6
LICENSE
6
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) <year> <owner> . All rights reserved.
|
Copyright (c) 2020 Wholesomedonut . All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
@ -10,7 +10,7 @@ this list of conditions and the following disclaimer.
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
@ -19,4 +19,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
42
README.md
42
README.md
|
@ -1,18 +1,27 @@
|
||||||
# gemini-demo-1
|
# asparagus
|
||||||
|
|
||||||
Minimal but usable interactive Gemini client in < 100 LOC of Python 3
|
Larger, more functional version of solderpunk's gemini-demo-1,
|
||||||
|
which was a Gemini client in <=100 LOC in Python 3.
|
||||||
|
|
||||||
## Rationale
|
Mine is already 50% larger.
|
||||||
|
|
||||||
One of the original design criteria for the Gemini protocol was that
|
## Why the fork?
|
||||||
"a basic but usable (not ultra-spartan) client should fit comfortably
|
|
||||||
within 50 or so lines of code in a modern high-level language.
|
I really enjoyed solderpunk's work. Quick, clean, and tiny.
|
||||||
Certainly not more than 100". This client was written to gauge how
|
|
||||||
close to (or far from!) that goal the initial rough specification is.
|
I just wanted to try my luck at getting a more fleshed-out app going.
|
||||||
|
|
||||||
|
I've never done FOSS contributions before today. Consider this repo my beginning!
|
||||||
|
|
||||||
|
I'm literally developing this entirely on an iPad Pro for kicks and giggles, using:
|
||||||
|
* Pythonista
|
||||||
|
* Working Copy
|
||||||
|
|
||||||
|
I have no idea how long it'll last, if it even will at all.
|
||||||
|
|
||||||
## Capabilities
|
## Capabilities
|
||||||
|
|
||||||
This crude but functional client:
|
This fork has all of gemini-demo-1's functionality:
|
||||||
|
|
||||||
* Has a minimal interactive interface for "Gemini maps"
|
* Has a minimal interactive interface for "Gemini maps"
|
||||||
* Will print plain text in any encoding if it is properly declared in
|
* Will print plain text in any encoding if it is properly declared in
|
||||||
|
@ -23,8 +32,11 @@ This crude but functional client:
|
||||||
* Will report errors
|
* Will report errors
|
||||||
* Does NOT DO ANY validation of TLS certificates
|
* Does NOT DO ANY validation of TLS certificates
|
||||||
|
|
||||||
It's a *snug* fit in 100 lines, but it's possible. A 50 LOC client
|
### IN addition to:
|
||||||
would need to be much simpler.
|
|
||||||
|
* Has session-persistent history that you can repeatedly maneuver through
|
||||||
|
* Descriptive error texts
|
||||||
|
* More keyboard commands and CLI-accessible help text.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -35,6 +47,10 @@ visit a Gemini location.
|
||||||
If a Gemini menu is visited, you'll see numeric indices for links, ala
|
If a Gemini menu is visited, you'll see numeric indices for links, ala
|
||||||
VF-1 or AV-98. Type a number to visit that link.
|
VF-1 or AV-98. Type a number to visit that link.
|
||||||
|
|
||||||
There is very crude history: you can type `b` to go "back".
|
Press h to see a printout of your history,
|
||||||
|
b to go back a page,
|
||||||
|
and f to go forward a page.
|
||||||
|
|
||||||
Type `q` to quit.
|
Type ? to see a brief help text inside the client.
|
||||||
|
|
||||||
|
Press q to quit.
|
|
@ -13,6 +13,31 @@ caps = mailcap.getcaps()
|
||||||
menu = []
|
menu = []
|
||||||
hist = []
|
hist = []
|
||||||
|
|
||||||
|
def printHelp():
|
||||||
|
help = """ Type in a gemini:// address to go somewhere,
|
||||||
|
input 'b' to go back a page,
|
||||||
|
'f' to go forward,
|
||||||
|
'h' to show your history in order,
|
||||||
|
'?' to show this help again,
|
||||||
|
or 'q' to quit.
|
||||||
|
"""
|
||||||
|
print(help)
|
||||||
|
|
||||||
|
|
||||||
|
def printIntro():
|
||||||
|
o = """
|
||||||
|
Welcome to PyGemini, a single-file Python client for the Gemini protocol.
|
||||||
|
Original source code by, , at
|
||||||
|
forked by Wholesomedonut on Sep 6 2020.
|
||||||
|
|
||||||
|
Questions about this fork?
|
||||||
|
Email with subject "PyGemini + whatever-you-need",
|
||||||
|
to wholesomedonut[at]tuta[dot]io .
|
||||||
|
"""
|
||||||
|
print(o)
|
||||||
|
printHelp()
|
||||||
|
|
||||||
|
|
||||||
def absolutise_url(base, relative):
|
def absolutise_url(base, relative):
|
||||||
# Absolutise relative links
|
# Absolutise relative links
|
||||||
if "://" not in relative:
|
if "://" not in relative:
|
||||||
|
@ -21,6 +46,8 @@ def absolutise_url(base, relative):
|
||||||
relative = urllib.parse.urljoin(base, relative)
|
relative = urllib.parse.urljoin(base, relative)
|
||||||
relative = relative.replace("http://", "gemini://")
|
relative = relative.replace("http://", "gemini://")
|
||||||
return relative
|
return relative
|
||||||
|
|
||||||
|
printIntro()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# Get input
|
# Get input
|
||||||
|
@ -34,16 +61,61 @@ while True:
|
||||||
url = menu[int(cmd)-1]
|
url = menu[int(cmd)-1]
|
||||||
elif cmd.lower() == "b":
|
elif cmd.lower() == "b":
|
||||||
# Yes, twice
|
# Yes, twice
|
||||||
url = hist.pop()
|
# url = hist.pop()
|
||||||
url = hist.pop()
|
# url = hist.pop()
|
||||||
|
|
||||||
|
# updated to preserve history in list
|
||||||
|
# so you can use 'f' to go forward too. - WD
|
||||||
|
try:
|
||||||
|
url = hist[len(hist) - 2]
|
||||||
|
except IndexError as e:
|
||||||
|
print(e)
|
||||||
|
print('You do not have any history to go back to')
|
||||||
|
continue
|
||||||
|
elif cmd.lower() == "f":
|
||||||
|
# now you can go ahead in history too! - WD
|
||||||
|
try:
|
||||||
|
url = hist[url+1]
|
||||||
|
except NameError as e:
|
||||||
|
print(e)
|
||||||
|
print('You do not have any history')
|
||||||
|
except IndexError as e:
|
||||||
|
print(e)
|
||||||
|
print('You are at the front of your history already')
|
||||||
|
continue
|
||||||
|
elif cmd.lower() == "h":
|
||||||
|
# Will actually show history. - WD
|
||||||
|
try:
|
||||||
|
print("History:")
|
||||||
|
for x in range(len(hist)):
|
||||||
|
print('[',x,']',hist[x])
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
print('Looks like I dun goofed.')
|
||||||
|
elif cmd == "?":
|
||||||
|
try:
|
||||||
|
printHelp()
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
else:
|
else:
|
||||||
url = cmd
|
url = cmd
|
||||||
if not "://" in url:
|
if not "://" in url:
|
||||||
url = "gemini://" + url
|
url = "gemini://" + url
|
||||||
parsed_url = urllib.parse.urlparse(url)
|
# this try/except allows you to check for history with 'h'
|
||||||
|
# even if you have visited no pages yet, without crashing. - WD
|
||||||
|
try:
|
||||||
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
|
except NameError as e:
|
||||||
|
print('Error:',e,'\nso try having some history first by visiting a page')
|
||||||
|
continue
|
||||||
if parsed_url.scheme != "gemini":
|
if parsed_url.scheme != "gemini":
|
||||||
print("Sorry, Gemini links only.")
|
print("Sorry, Gemini links only.")
|
||||||
|
# break
|
||||||
continue
|
continue
|
||||||
|
# now it'll just loop again
|
||||||
|
# instead of quitting the program if you
|
||||||
|
# put the wrong thing in. - WD
|
||||||
# Do the Gemini transaction
|
# Do the Gemini transaction
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
@ -76,6 +148,8 @@ while True:
|
||||||
# Fail if transaction was not successful
|
# Fail if transaction was not successful
|
||||||
if not status.startswith("2"):
|
if not status.startswith("2"):
|
||||||
print("Error %s: %s" % (status, mime))
|
print("Error %s: %s" % (status, mime))
|
||||||
|
# haha funny error code - WD
|
||||||
|
print("OH NO I didn't communicate with the Gemini server right")
|
||||||
continue
|
continue
|
||||||
# Handle text
|
# Handle text
|
||||||
if mime.startswith("text/"):
|
if mime.startswith("text/"):
|
||||||
|
@ -113,4 +187,4 @@ while True:
|
||||||
os.system(cmd_str)
|
os.system(cmd_str)
|
||||||
os.unlink(tmpfp.name)
|
os.unlink(tmpfp.name)
|
||||||
# Update history
|
# Update history
|
||||||
hist.append(url)
|
hist.append(url)
|
Loading…
Reference in New Issue