Begin on a web interface

master
Bob Mottram 2019-07-20 22:13:36 +01:00
parent 0350b9e33b
commit 2b02a1a442
3 changed files with 133 additions and 28 deletions

View File

@ -14,29 +14,30 @@ This project is currently *pre alpha* and not recommended for any real world use
## Goals
* A minimal ActivityPub server, comparable to an email MTA.
* A minimal ActivityPub server, comparable to an email MTA
* AGPLv3+
* Server-to-server and client-to-server protocols supported.
* Server-to-server and client-to-server protocols supported
* Implemented in a common language (Python 3)
* Keyword filtering.
* Being able to build crowdsouced organizations with roles and skills
* Sharings collection, similar to the gnusocial sharings plugin
* Quotas for received posts per day, per domain and per account
* Hellthread detection and removal
* Support content warnings, reporting and blocking.
* http signatures and basic auth.
* Compatible with http (onion addresses), https and dat.
* Support content warnings, reporting and blocking
* http signatures and basic auth
* Compatible with http (onion addresses), https and dat
* Minimal dependencies.
* Capabilities based security
* Support image blurhashes
* Data minimization principle. Configurable post expiry time.
* Data minimization principle. Configurable post expiry time
* Likes and repeats only visible to authorized viewers
* ReplyGuy mitigation - maxmimum replies per post or posts per day
* Ability to delete or hide specific conversation threads
* Commandline interface. If there's a GUI it should be a separate project.
* Designed for intermittent connectivity. Assume network disruptions.
* Commandline interface
* Simple web interface
* Designed for intermittent connectivity. Assume network disruptions
* Limited visibility of follows/followers
* Suitable for single board computers.
* Suitable for single board computers
## Install

View File

@ -44,6 +44,13 @@ from config import setConfigParam
from roles import outboxDelegate
from skills import outboxSkills
from availability import outboxAvailability
from webinterface import htmlIndividualPost
from webinterface import htmlProfile
from webinterface import htmlFollowing
from webinterface import htmlFollowers
from webinterface import htmlInbox
from webinterface import htmlOutbox
from webinterface import htmlPostReplies
import os
import sys
@ -329,7 +336,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.lastGET=currTimeGET
self.server.GETbusy=True
#print('Content-type: '+self.headers['Accept'])
#print('Accept: '+self.headers['Accept'])
if not self._permittedDir(self.path):
if self.server.debug:
@ -416,8 +423,12 @@ class PubServer(BaseHTTPRequestHandler):
if not self._isAuthorized():
if postJsonObject.get('likes'):
postJsonObject['likes']={}
self._set_headers('application/json')
self.wfile.write(json.dumps(postJsonObject).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlIndividualPost(postJsonObject).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(postJsonObject).encode('utf-8'))
self.server.GETbusy=False
return
else:
@ -453,8 +464,12 @@ class PubServer(BaseHTTPRequestHandler):
'last': self.server.httpPrefix+'://'+domainFull+'/users/'+nickname+'/statuses/'+statusNumber+'/replies?page=true',
'totalItems': 0,
'type': 'OrderedCollection'}
self._set_headers('application/json')
self.wfile.write(json.dumps(repliesJson).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlPostReplies(repliesJson).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(repliesJson).encode('utf-8'))
self.server.GETbusy=False
return
else:
@ -521,8 +536,12 @@ class PubServer(BaseHTTPRequestHandler):
'https://www.w3.org/ns/activitystreams#Public' in postJsonObject['object']['to']:
repliesJson['orderedItems'].append(postJsonObject)
# send the replies json
self._set_headers('application/json')
self.wfile.write(json.dumps(repliesJson).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlPostReplies(repliesJson).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(repliesJson).encode('utf-8'))
self.server.GETbusy=False
return
@ -550,8 +569,12 @@ class PubServer(BaseHTTPRequestHandler):
if not self._isAuthorized():
if postJsonObject.get('likes'):
postJsonObject['likes']={}
self._set_headers('application/json')
self.wfile.write(json.dumps(postJsonObject).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlIndividualPost(postJsonObject).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(postJsonObject).encode('utf-8'))
self.server.GETbusy=False
return
else:
@ -570,8 +593,12 @@ class PubServer(BaseHTTPRequestHandler):
maxPostsInFeed, 'inbox', \
True,self.server.ocapAlways)
if inboxFeed:
self._set_headers('application/json')
self.wfile.write(json.dumps(inboxFeed).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlInbox(inboxFeed).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(inboxFeed).encode('utf-8'))
self.server.GETbusy=False
return
else:
@ -593,8 +620,12 @@ class PubServer(BaseHTTPRequestHandler):
self._isAuthorized(), \
self.server.ocapAlways)
if outboxFeed:
self._set_headers('application/json')
self.wfile.write(json.dumps(outboxFeed).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlOutbox(outboxFeed).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(outboxFeed).encode('utf-8'))
self.server.GETbusy=False
return
authorized=self._isAuthorized()
@ -603,8 +634,12 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix,
authorized,followsPerPage)
if following:
self._set_headers('application/json')
self.wfile.write(json.dumps(following).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlFollowing(following).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(following).encode('utf-8'))
self.server.GETbusy=False
return
followers=getFollowingFeed(self.server.baseDir,self.server.domain, \
@ -612,16 +647,24 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix, \
authorized,followsPerPage,'followers')
if followers:
self._set_headers('application/json')
self.wfile.write(json.dumps(followers).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlFollowers(followers).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(followers).encode('utf-8'))
self.server.GETbusy=False
return
# look up a person
getPerson = personLookup(self.server.domain,self.path, \
self.server.baseDir)
if getPerson:
self._set_headers('application/json')
self.wfile.write(json.dumps(getPerson).encode('utf-8'))
if 'text/html' in self.headers['Accept']:
self._set_headers('text/html')
self.wfile.write(htmlProfile(getPerson).encode('utf-8'))
else:
self._set_headers('application/json')
self.wfile.write(json.dumps(getPerson).encode('utf-8'))
self.server.GETbusy=False
return
# check that a json file was requested

61
webinterface.py 100644
View File

@ -0,0 +1,61 @@
__filename__ = "webinterface.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "0.0.1"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
import json
def htmlHeader(lang='en') -> str:
htmlStr= \
'<!DOCTYPE html>\n' \
'<html lang="'+lang+'">\n' \
' <meta charset="utf-8">\n' \
' <style>\n' \
' @import url("epicyon.css");\n' \
' </style>\n' \
' <body>\n'
return htmlStr
def htmlFooter() -> str:
htmlStr= \
' </body>\n' \
'</html>\n'
return htmlStr
def htmlProfile(profileJson: {}) -> str:
"""Show the profile page as html
"""
return htmlHeader()+"<h1>Profile page</h1>"+htmlFooter()
def htmlFollowing(followingJson: {}) -> str:
"""Show the following collection as html
"""
return htmlHeader()+"<h1>Following collection</h1>"+htmlFooter()
def htmlFollowers(followersJson: {}) -> str:
"""Show the followers collection as html
"""
return htmlHeader()+"<h1>Followers collection</h1>"+htmlFooter()
def htmlInbox(inboxJson: {}) -> str:
"""Show the inbox as html
"""
return htmlHeader()+"<h1>Inbox</h1>"+htmlFooter()
def htmlOutbox(outboxJson: {}) -> str:
"""Show the Outbox as html
"""
return htmlHeader()+"<h1>Outbox</h1>"+htmlFooter()
def htmlIndividualPost(postJsonObject: {}) -> str:
"""Show an individual post as html
"""
return htmlHeader()+"<h1>Post</h1>"+htmlFooter()
def htmlPostReplies(postJsonObject: {}) -> str:
"""Show the replies to an individual post as html
"""
return htmlHeader()+"<h1>Replies</h1>"+htmlFooter()