Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon

main
Bob Mottram 2021-06-27 12:57:09 +01:00
commit 3825949bab
8 changed files with 232 additions and 46 deletions

View File

@ -1,22 +1,24 @@
# Roadman
# Roadmap
## UX
* Change animation on buttons (themeable?)
* Minimize button shows different icons or highlighting
* Layout of buttons on person options screen
## Teams
## Groups
* Test groups
* Unit test for group creation
* Groups can be defined as having particular roles/skills
* Templates for different group organizations
## Events
## Questions
* Events timeline
* Events appear on calendar
* Check compatibility with Mobilizon
* Still not implemented ideally
* Instance-only questions
* Active polls screen?
* Questions more integrated into overall organization
## Code
* Modularize daemon
* Move modules out of the daemon
* Make comment notes linking daemon functions to webinterface
* More unit test coverage
* Break up large functions into smaller ones
* Architecture diagrams
* Code documentation?

92
cwtch.py 100644
View File

@ -0,0 +1,92 @@
__filename__ = "cwtch.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "Profile Metadata"
import re
def getCwtchAddress(actorJson: {}) -> str:
"""Returns cwtch address for the given actor
"""
if not actorJson.get('attachment'):
return ''
for propertyValue in actorJson['attachment']:
if not propertyValue.get('name'):
continue
if not propertyValue['name'].lower().startswith('cwtch'):
continue
if not propertyValue.get('type'):
continue
if not propertyValue.get('value'):
continue
if propertyValue['type'] != 'PropertyValue':
continue
propertyValue['value'] = propertyValue['value'].strip()
if len(propertyValue['value']) < 2:
continue
if '"' in propertyValue['value']:
continue
if ' ' in propertyValue['value']:
continue
if ',' in propertyValue['value']:
continue
if '.' in propertyValue['value']:
continue
return propertyValue['value']
return ''
def setCwtchAddress(actorJson: {}, cwtchAddress: str) -> None:
"""Sets an cwtch address for the given actor
"""
notCwtchAddress = False
if len(cwtchAddress) < 56:
notCwtchAddress = True
if cwtchAddress != cwtchAddress.lower():
notCwtchAddress = True
if not re.match("^[a-z0-9]*$", cwtchAddress):
notCwtchAddress = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
# remove any existing value
propertyFound = None
for propertyValue in actorJson['attachment']:
if not propertyValue.get('name'):
continue
if not propertyValue.get('type'):
continue
if not propertyValue['name'].lower().startswith('cwtch'):
continue
propertyFound = propertyValue
break
if propertyFound:
actorJson['attachment'].remove(propertyFound)
if notCwtchAddress:
return
for propertyValue in actorJson['attachment']:
if not propertyValue.get('name'):
continue
if not propertyValue.get('type'):
continue
if not propertyValue['name'].lower().startswith('cwtch'):
continue
if propertyValue['type'] != 'PropertyValue':
continue
propertyValue['value'] = cwtchAddress
return
newCwtchAddress = {
"name": "Cwtch",
"type": "PropertyValue",
"value": cwtchAddress
}
actorJson['attachment'].append(newCwtchAddress)

View File

@ -44,6 +44,8 @@ from briar import getBriarAddress
from briar import setBriarAddress
from jami import getJamiAddress
from jami import setJamiAddress
from cwtch import getCwtchAddress
from cwtch import setCwtchAddress
from matrix import getMatrixAddress
from matrix import setMatrixAddress
from donate import getDonationUrl
@ -4517,6 +4519,18 @@ class PubServer(BaseHTTPRequestHandler):
setJamiAddress(actorJson, '')
actorChanged = True
# change cwtch address
currentCwtchAddress = getCwtchAddress(actorJson)
if fields.get('cwtchAddress'):
if fields['cwtchAddress'] != currentCwtchAddress:
setCwtchAddress(actorJson,
fields['cwtchAddress'])
actorChanged = True
else:
if currentCwtchAddress:
setCwtchAddress(actorJson, '')
actorChanged = True
# change PGP public key
currentPGPpubKey = getPGPpubKey(actorJson)
if fields.get('pgp'):
@ -5811,6 +5825,7 @@ class PubServer(BaseHTTPRequestHandler):
toxAddress = None
briarAddress = None
jamiAddress = None
cwtchAddress = None
ssbAddress = None
emailAddress = None
lockedAccount = False
@ -5832,6 +5847,7 @@ class PubServer(BaseHTTPRequestHandler):
toxAddress = getToxAddress(actorJson)
briarAddress = getBriarAddress(actorJson)
jamiAddress = getJamiAddress(actorJson)
cwtchAddress = getCwtchAddress(actorJson)
emailAddress = getEmailAddress(actorJson)
PGPpubKey = getPGPpubKey(actorJson)
PGPfingerprint = getPGPfingerprint(actorJson)
@ -5866,7 +5882,7 @@ class PubServer(BaseHTTPRequestHandler):
xmppAddress, matrixAddress,
ssbAddress, blogAddress,
toxAddress, briarAddress,
jamiAddress,
jamiAddress, cwtchAddress,
PGPpubKey, PGPfingerprint,
emailAddress,
self.server.dormantMonths,

View File

@ -852,6 +852,30 @@ def _addAutoCW(baseDir: str, nickname: str, domain: str,
return newSubject
def _createPostCWFromReply(baseDir: str, nickname: str, domain: str,
inReplyTo: str,
sensitive: bool, summary: str) -> (bool, str):
"""If this is a reply and the original post has a CW
then use the same CW
"""
if inReplyTo and not sensitive:
# locate the post which this is a reply to and check if
# it has a content warning. If it does then reproduce
# the same warning
replyPostFilename = \
locatePost(baseDir, nickname, domain, inReplyTo)
if replyPostFilename:
replyToJson = loadJson(replyPostFilename)
if replyToJson:
if replyToJson.get('object'):
if replyToJson['object'].get('sensitive'):
if replyToJson['object']['sensitive']:
sensitive = True
if replyToJson['object'].get('summary'):
summary = replyToJson['object']['summary']
return sensitive, summary
def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
toUrl: str, ccUrl: str, httpPrefix: str, content: str,
followersOnly: bool, saveToFile: bool,
@ -952,21 +976,9 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
_updateHashtagsIndex(baseDir, tag, newPostId)
# print('Content tags: ' + str(tags))
if inReplyTo and not sensitive:
# locate the post which this is a reply to and check if
# it has a content warning. If it does then reproduce
# the same warning
replyPostFilename = \
locatePost(baseDir, nickname, domain, inReplyTo)
if replyPostFilename:
replyToJson = loadJson(replyPostFilename)
if replyToJson:
if replyToJson.get('object'):
if replyToJson['object'].get('sensitive'):
if replyToJson['object']['sensitive']:
sensitive = True
if replyToJson['object'].get('summary'):
summary = replyToJson['object']['summary']
sensitive, summary = \
_createPostCWFromReply(baseDir, nickname, domain,
inReplyTo, sensitive, summary)
# get the ending date and time
endDateStr = None

View File

@ -72,6 +72,27 @@ def removeShare(baseDir: str, nickname: str, domain: str,
'" does not exist in ' + sharesFilename)
def _addShareDurationSec(duration: str, published: str) -> int:
"""Returns the duration for the shared item in seconds
"""
if ' ' not in duration:
return 0
durationList = duration.split(' ')
if not durationList[0].isdigit():
return 0
if 'hour' in durationList[1]:
return published + (int(durationList[0]) * 60 * 60)
if 'day' in durationList[1]:
return published + (int(durationList[0]) * 60 * 60 * 24)
if 'week' in durationList[1]:
return published + (int(durationList[0]) * 60 * 60 * 24 * 7)
if 'month' in durationList[1]:
return published + (int(durationList[0]) * 60 * 60 * 24 * 30)
if 'year' in durationList[1]:
return published + (int(durationList[0]) * 60 * 60 * 24 * 365)
return 0
def addShare(baseDir: str,
httpPrefix: str, nickname: str, domain: str, port: int,
displayName: str, summary: str, imageFilename: str,
@ -86,24 +107,8 @@ def addShare(baseDir: str,
sharesJson = loadJson(sharesFilename)
duration = duration.lower()
durationSec = 0
published = int(time.time())
if ' ' in duration:
durationList = duration.split(' ')
if durationList[0].isdigit():
if 'hour' in durationList[1]:
durationSec = published + (int(durationList[0]) * 60 * 60)
if 'day' in durationList[1]:
durationSec = published + (int(durationList[0]) * 60 * 60 * 24)
if 'week' in durationList[1]:
durationSec = \
published + (int(durationList[0]) * 60 * 60 * 24 * 7)
if 'month' in durationList[1]:
durationSec = \
published + (int(durationList[0]) * 60 * 60 * 24 * 30)
if 'year' in durationList[1]:
durationSec = \
published + (int(durationList[0]) * 60 * 60 * 24 * 365)
durationSec = _addShareDurationSec(duration, published)
itemID = getValidSharedItemID(displayName)

View File

@ -2981,6 +2981,7 @@ def _testFunctions():
functionProperties = {}
modules = {}
modGroups = {}
methodLOC = []
for subdir, dirs, files in os.walk('.'):
for sourceFile in files:
@ -2997,6 +2998,9 @@ def _testFunctions():
with open(sourceFile, "r") as f:
lines = f.readlines()
modules[modName]['lines'] = lines
lineCount = 0
prevLine = 'start'
methodName = ''
for line in lines:
if '__module_group__' in line:
if '=' in line:
@ -3010,7 +3014,28 @@ def _testFunctions():
if modName not in modGroups[groupName]:
modGroups[groupName].append(modName)
if not line.strip().startswith('def '):
if lineCount > 0:
lineCount += 1
# add LOC count for this function
if len(prevLine.strip()) == 0 and \
len(line.strip()) == 0 and \
lineCount > 2:
lineCount -= 2
if lineCount > 80:
locStr = str(lineCount) + ';' + methodName
if lineCount < 1000:
locStr = '0' + locStr
if lineCount < 100:
locStr = '0' + locStr
if lineCount < 10:
locStr = '0' + locStr
if locStr not in methodLOC:
methodLOC.append(locStr)
lineCount = 0
prevLine = line
continue
prevLine = line
lineCount = 1
methodName = line.split('def ', 1)[1].split('(')[0]
methodArgs = \
sourceStr.split('def ' + methodName + '(')[1]
@ -3027,8 +3052,26 @@ def _testFunctions():
"module": modName,
"calledInModule": []
}
# LOC count for the last function
if lineCount > 2:
lineCount -= 2
if lineCount > 80:
locStr = str(lineCount) + ';' + methodName
if lineCount < 1000:
locStr = '0' + locStr
if lineCount < 100:
locStr = '0' + locStr
if lineCount < 10:
locStr = '0' + locStr
if locStr not in methodLOC:
methodLOC.append(locStr)
break
print('LOC counts:')
methodLOC.sort()
for locStr in methodLOC:
print(locStr.split(';')[0] + ' ' + locStr.split(';')[1])
excludeFuncArgs = [
'pyjsonld'
]

View File

@ -45,6 +45,7 @@ def htmlPersonOptions(defaultTimeline: str,
toxAddress: str,
briarAddress: str,
jamiAddress: str,
cwtchAddress: str,
PGPpubKey: str,
PGPfingerprint: str,
emailAddress: str,
@ -214,6 +215,9 @@ def htmlPersonOptions(defaultTimeline: str,
if jamiAddress:
optionsStr += \
'<p class="imText">Jami: ' + removeHtml(jamiAddress) + '</p>\n'
if cwtchAddress:
optionsStr += \
'<p class="imText">Cwtch: ' + removeHtml(cwtchAddress) + '</p>\n'
if PGPfingerprint:
optionsStr += '<p class="pgp">PGP: ' + \
removeHtml(PGPfingerprint).replace('\n', '<br>') + '</p>\n'

View File

@ -40,6 +40,7 @@ from pgp import getPGPpubKey
from tox import getToxAddress
from briar import getBriarAddress
from jami import getJamiAddress
from cwtch import getCwtchAddress
from filters import isFiltered
from follow import isFollowerOfPerson
from webapp_frontscreen import htmlFrontScreen
@ -517,9 +518,10 @@ def htmlProfile(rssIconAtTop: bool,
toxAddress = getToxAddress(profileJson)
briarAddress = getBriarAddress(profileJson)
jamiAddress = getJamiAddress(profileJson)
cwtchAddress = getCwtchAddress(profileJson)
if donateUrl or xmppAddress or matrixAddress or \
ssbAddress or toxAddress or briarAddress or \
jamiAddress or PGPpubKey or \
jamiAddress or cwtchAddress or PGPpubKey or \
PGPfingerprint or emailAddress:
donateSection = '<div class="container">\n'
donateSection += ' <center>\n'
@ -560,6 +562,10 @@ def htmlProfile(rssIconAtTop: bool,
donateSection += \
'<p>Jami: <label class="toxaddr">' + \
jamiAddress + '</label></p>\n'
if cwtchAddress:
donateSection += \
'<p>Cwtch: <label class="toxaddr">' + \
cwtchAddress + '</label></p>\n'
if PGPfingerprint:
donateSection += \
'<p class="pgp">PGP: ' + \
@ -1063,6 +1069,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
toxAddress = getToxAddress(actorJson)
briarAddress = getBriarAddress(actorJson)
jamiAddress = getJamiAddress(actorJson)
cwtchAddress = getCwtchAddress(actorJson)
emailAddress = getEmailAddress(actorJson)
PGPpubKey = getPGPpubKey(actorJson)
PGPfingerprint = getPGPfingerprint(actorJson)
@ -1698,6 +1705,11 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
' <input type="text" name="jamiAddress" value="' + \
jamiAddress + '">\n'
editProfileForm += '<label class="labels">Cwtch</label><br>\n'
editProfileForm += \
' <input type="text" name="cwtchAddress" value="' + \
cwtchAddress + '">\n'
editProfileForm += \
'<label class="labels">' + \
translate['PGP Fingerprint'] + '</label><br>\n'