mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
commit
b754b13fd8
|
@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
|
|||
__status__ = "Production"
|
||||
|
||||
import os
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import urlPermitted
|
||||
from utils import getDomainFromActor
|
||||
|
@ -182,10 +183,7 @@ def receiveAcceptReject(session, baseDir: str,
|
|||
if debug:
|
||||
print('DEBUG: ' + messageJson['type'] + ' has no actor')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor in ' +
|
||||
messageJson['type'] + '. Assuming single user instance.')
|
||||
|
|
|
@ -6,6 +6,7 @@ __maintainer__ = "Bob Mottram"
|
|||
__email__ = "bob@freedombone.net"
|
||||
__status__ = "Production"
|
||||
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import getStatusNumber
|
||||
from utils import createOutboxDir
|
||||
|
@ -143,10 +144,7 @@ def createAnnounce(session, baseDir: str, federationList: [],
|
|||
announceNickname = None
|
||||
announceDomain = None
|
||||
announcePort = None
|
||||
if '/users/' in objectUrl or \
|
||||
'/accounts/' in objectUrl or \
|
||||
'/channel/' in objectUrl or \
|
||||
'/profile/' in objectUrl:
|
||||
if hasUsersPath(objectUrl):
|
||||
announceNickname = getNicknameFromActor(objectUrl)
|
||||
announceDomain, announcePort = getDomainFromActor(objectUrl)
|
||||
|
||||
|
|
6
auth.py
6
auth.py
|
@ -12,6 +12,7 @@ import binascii
|
|||
import os
|
||||
import secrets
|
||||
from utils import isSystemAccount
|
||||
from utils import hasUsersPath
|
||||
|
||||
|
||||
def _hashPassword(password: str) -> str:
|
||||
|
@ -89,10 +90,7 @@ def authorizeBasic(baseDir: str, path: str, authHeader: str,
|
|||
print('DEBUG: basic auth - Authorixation header does not ' +
|
||||
'contain a space character')
|
||||
return False
|
||||
if '/users/' not in path and \
|
||||
'/accounts/' not in path and \
|
||||
'/channel/' not in path and \
|
||||
'/profile/' not in path:
|
||||
if not hasUsersPath(path):
|
||||
if debug:
|
||||
print('DEBUG: basic auth - ' +
|
||||
'path for Authorization does not contain a user')
|
||||
|
|
11
blocking.py
11
blocking.py
|
@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
|
|||
__status__ = "Production"
|
||||
|
||||
import os
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import removeIdEnding
|
||||
from utils import isEvil
|
||||
|
@ -246,10 +247,7 @@ def outboxBlock(baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: c2s block object is not a status')
|
||||
return
|
||||
if '/users/' not in messageId and \
|
||||
'/accounts/' not in messageId and \
|
||||
'/channel/' not in messageId and \
|
||||
'/profile/' not in messageId:
|
||||
if not hasUsersPath(messageId):
|
||||
if debug:
|
||||
print('DEBUG: c2s block object has no nickname')
|
||||
return
|
||||
|
@ -321,10 +319,7 @@ def outboxUndoBlock(baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: c2s undo block object is not a status')
|
||||
return
|
||||
if '/users/' not in messageId and \
|
||||
'/accounts/' not in messageId and \
|
||||
'/channel/' not in messageId and \
|
||||
'/profile/' not in messageId:
|
||||
if not hasUsersPath(messageId):
|
||||
if debug:
|
||||
print('DEBUG: c2s undo block object has no nickname')
|
||||
return
|
||||
|
|
21
blog.py
21
blog.py
|
@ -158,6 +158,7 @@ def _htmlBlogPostContent(authorized: bool,
|
|||
nickname: str, domain: str, domainFull: str,
|
||||
postJsonObject: {},
|
||||
handle: str, restrictToDomain: bool,
|
||||
peertubeInstances: [],
|
||||
blogSeparator='<hr>') -> str:
|
||||
"""Returns the content for a single blog post
|
||||
"""
|
||||
|
@ -231,7 +232,8 @@ def _htmlBlogPostContent(authorized: bool,
|
|||
|
||||
if postJsonObject['object'].get('content'):
|
||||
contentStr = addEmbeddedElements(translate,
|
||||
postJsonObject['object']['content'])
|
||||
postJsonObject['object']['content'],
|
||||
peertubeInstances)
|
||||
if postJsonObject['object'].get('tag'):
|
||||
contentStr = replaceEmojiFromTags(contentStr,
|
||||
postJsonObject['object']['tag'],
|
||||
|
@ -375,7 +377,8 @@ def _htmlBlogRemoveCwButton(blogStr: str, translate: {}) -> str:
|
|||
def htmlBlogPost(authorized: bool,
|
||||
baseDir: str, httpPrefix: str, translate: {},
|
||||
nickname: str, domain: str, domainFull: str,
|
||||
postJsonObject: {}) -> str:
|
||||
postJsonObject: {},
|
||||
peertubeInstances: []) -> str:
|
||||
"""Returns a html blog post
|
||||
"""
|
||||
blogStr = ''
|
||||
|
@ -390,7 +393,8 @@ def htmlBlogPost(authorized: bool,
|
|||
httpPrefix, translate,
|
||||
nickname, domain,
|
||||
domainFull, postJsonObject,
|
||||
None, False)
|
||||
None, False,
|
||||
peertubeInstances)
|
||||
|
||||
# show rss links
|
||||
blogStr += '<p class="rssfeed">'
|
||||
|
@ -417,7 +421,8 @@ def htmlBlogPost(authorized: bool,
|
|||
def htmlBlogPage(authorized: bool, session,
|
||||
baseDir: str, httpPrefix: str, translate: {},
|
||||
nickname: str, domain: str, port: int,
|
||||
noOfItems: int, pageNumber: int) -> str:
|
||||
noOfItems: int, pageNumber: int,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Returns a html blog page containing posts
|
||||
"""
|
||||
if ' ' in nickname or '@' in nickname or \
|
||||
|
@ -477,7 +482,8 @@ def htmlBlogPage(authorized: bool, session,
|
|||
httpPrefix, translate,
|
||||
nickname, domain,
|
||||
domainFull, item,
|
||||
None, True)
|
||||
None, True,
|
||||
peertubeInstances)
|
||||
|
||||
if len(timelineJson['orderedItems']) >= noOfItems:
|
||||
blogStr += navigateStr
|
||||
|
@ -638,7 +644,8 @@ def _singleBlogAccountNickname(baseDir: str) -> str:
|
|||
def htmlBlogView(authorized: bool,
|
||||
session, baseDir: str, httpPrefix: str,
|
||||
translate: {}, domain: str, port: int,
|
||||
noOfItems: int) -> str:
|
||||
noOfItems: int,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the blog main page
|
||||
"""
|
||||
blogStr = ''
|
||||
|
@ -654,7 +661,7 @@ def htmlBlogView(authorized: bool,
|
|||
return htmlBlogPage(authorized, session,
|
||||
baseDir, httpPrefix, translate,
|
||||
nickname, domain, port,
|
||||
noOfItems, 1)
|
||||
noOfItems, 1, peertubeInstances)
|
||||
|
||||
domainFull = getFullDomain(domain, port)
|
||||
|
||||
|
|
11
bookmarks.py
11
bookmarks.py
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
|||
|
||||
import os
|
||||
from pprint import pprint
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import removeIdEnding
|
||||
from utils import removePostFromCache
|
||||
|
@ -255,10 +256,7 @@ def bookmark(recentPostsCache: {},
|
|||
bookmarkedPostNickname = getNicknameFromActor(acBm)
|
||||
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
|
||||
else:
|
||||
if '/users/' in objectUrl or \
|
||||
'/accounts/' in objectUrl or \
|
||||
'/channel/' in objectUrl or \
|
||||
'/profile/' in objectUrl:
|
||||
if hasUsersPath(objectUrl):
|
||||
ou = objectUrl
|
||||
bookmarkedPostNickname = getNicknameFromActor(ou)
|
||||
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
|
||||
|
@ -322,10 +320,7 @@ def undoBookmark(recentPostsCache: {},
|
|||
bookmarkedPostNickname = getNicknameFromActor(acBm)
|
||||
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
|
||||
else:
|
||||
if '/users/' in objectUrl or \
|
||||
'/accounts/' in objectUrl or \
|
||||
'/channel/' in objectUrl or \
|
||||
'/profile/' in objectUrl:
|
||||
if hasUsersPath(objectUrl):
|
||||
ou = objectUrl
|
||||
bookmarkedPostNickname = getNicknameFromActor(ou)
|
||||
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
__filename__ = "briar.py"
|
||||
__author__ = "Bob Mottram"
|
||||
__license__ = "AGPL3+"
|
||||
__version__ = "1.1.0"
|
||||
__maintainer__ = "Bob Mottram"
|
||||
__email__ = "bob@freedombone.net"
|
||||
__status__ = "Production"
|
||||
|
||||
|
||||
def getBriarAddress(actorJson: {}) -> str:
|
||||
"""Returns briar 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('briar'):
|
||||
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']) < 50:
|
||||
continue
|
||||
if not propertyValue['value'].startswith('briar://'):
|
||||
continue
|
||||
if propertyValue['value'].lower() != propertyValue['value']:
|
||||
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 setBriarAddress(actorJson: {}, briarAddress: str) -> None:
|
||||
"""Sets an briar address for the given actor
|
||||
"""
|
||||
notBriarAddress = False
|
||||
|
||||
if len(briarAddress) < 50:
|
||||
notBriarAddress = True
|
||||
if not briarAddress.startswith('briar://'):
|
||||
notBriarAddress = True
|
||||
if briarAddress.lower() != briarAddress:
|
||||
notBriarAddress = True
|
||||
if '"' in briarAddress:
|
||||
notBriarAddress = True
|
||||
if ' ' in briarAddress:
|
||||
notBriarAddress = True
|
||||
if '.' in briarAddress:
|
||||
notBriarAddress = True
|
||||
if ',' in briarAddress:
|
||||
notBriarAddress = True
|
||||
if '<' in briarAddress:
|
||||
notBriarAddress = 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('briar'):
|
||||
continue
|
||||
propertyFound = propertyValue
|
||||
break
|
||||
if propertyFound:
|
||||
actorJson['attachment'].remove(propertyFound)
|
||||
if notBriarAddress:
|
||||
return
|
||||
|
||||
for propertyValue in actorJson['attachment']:
|
||||
if not propertyValue.get('name'):
|
||||
continue
|
||||
if not propertyValue.get('type'):
|
||||
continue
|
||||
if not propertyValue['name'].lower().startswith('briar'):
|
||||
continue
|
||||
if propertyValue['type'] != 'PropertyValue':
|
||||
continue
|
||||
propertyValue['value'] = briarAddress
|
||||
return
|
||||
|
||||
newBriarAddress = {
|
||||
"name": "Briar",
|
||||
"type": "PropertyValue",
|
||||
"value": briarAddress
|
||||
}
|
||||
actorJson['attachment'].append(newBriarAddress)
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
|||
|
||||
import os
|
||||
from datetime import datetime
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import removeIdEnding
|
||||
from utils import getNicknameFromActor
|
||||
|
@ -139,10 +140,7 @@ def outboxDelete(baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: c2s delete object is not a status')
|
||||
return
|
||||
if '/users/' not in messageId and \
|
||||
'/accounts/' not in messageId and \
|
||||
'/channel/' not in messageId and \
|
||||
'/profile/' not in messageId:
|
||||
if not hasUsersPath(messageId):
|
||||
if debug:
|
||||
print('DEBUG: c2s delete object has no nickname')
|
||||
return
|
||||
|
|
11
epicyon.py
11
epicyon.py
|
@ -47,6 +47,7 @@ from tests import testClientToServer
|
|||
from tests import runAllTests
|
||||
from auth import storeBasicCredentials
|
||||
from auth import createPassword
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import setConfigParam
|
||||
from utils import getConfigParam
|
||||
|
@ -1318,10 +1319,7 @@ if args.actor:
|
|||
for prefix in prefixes:
|
||||
args.actor = args.actor.replace(prefix, '')
|
||||
args.actor = args.actor.replace('/@', '/users/')
|
||||
if '/users/' not in args.actor and \
|
||||
'/accounts/' not in args.actor and \
|
||||
'/channel/' not in args.actor and \
|
||||
'/profile/' not in args.actor:
|
||||
if not hasUsersPath(args.actor):
|
||||
print('Expected actor format: ' +
|
||||
'https://domain/@nick or https://domain/users/nick')
|
||||
sys.exit()
|
||||
|
@ -1391,10 +1389,7 @@ if args.actor:
|
|||
personUrl = None
|
||||
if wfRequest.get('errors'):
|
||||
print('wfRequest error: ' + str(wfRequest['errors']))
|
||||
if '/users/' in args.actor or \
|
||||
'/accounts/' in args.actor or \
|
||||
'/profile/' in args.actor or \
|
||||
'/channel/' in args.actor:
|
||||
if hasUsersPath(args.actor):
|
||||
personUrl = originalActor
|
||||
else:
|
||||
sys.exit()
|
||||
|
|
21
follow.py
21
follow.py
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
|||
|
||||
from pprint import pprint
|
||||
import os
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import isSystemAccount
|
||||
from utils import getFollowersList
|
||||
|
@ -316,10 +317,7 @@ def _getNoOfFollows(baseDir: str, nickname: str, domain: str,
|
|||
ctr += 1
|
||||
elif ((line.startswith('http') or
|
||||
line.startswith('dat')) and
|
||||
('/users/' in line or
|
||||
'/profile/' in line or
|
||||
'/accounts/' in line or
|
||||
'/channel/' in line)):
|
||||
hasUsersPath(line)):
|
||||
ctr += 1
|
||||
return ctr
|
||||
|
||||
|
@ -438,10 +436,7 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
|
|||
following['orderedItems'].append(url)
|
||||
elif ((line.startswith('http') or
|
||||
line.startswith('dat')) and
|
||||
('/users/' in line or
|
||||
'/profile/' in line or
|
||||
'/accounts/' in line or
|
||||
'/channel/' in line)):
|
||||
hasUsersPath(line)):
|
||||
# https://domain/users/nickname
|
||||
pageCtr += 1
|
||||
totalCtr += 1
|
||||
|
@ -616,10 +611,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: follow request has no actor')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: users/profile/accounts/channel missing from actor')
|
||||
return False
|
||||
|
@ -641,10 +633,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
|
|||
'nickname. Assuming single user instance.')
|
||||
if not messageJson.get('to'):
|
||||
messageJson['to'] = messageJson['object']
|
||||
if '/users/' not in messageJson['object'] and \
|
||||
'/accounts/' not in messageJson['object'] and \
|
||||
'/channel/' not in messageJson['object'] and \
|
||||
'/profile/' not in messageJson['object']:
|
||||
if not hasUsersPath(messageJson['object']):
|
||||
if debug:
|
||||
print('DEBUG: users/profile/channel/accounts ' +
|
||||
'not found within object')
|
||||
|
|
98
inbox.py
98
inbox.py
|
@ -10,6 +10,7 @@ import json
|
|||
import os
|
||||
import datetime
|
||||
import time
|
||||
from utils import hasUsersPath
|
||||
from utils import validPostDate
|
||||
from utils import getFullDomain
|
||||
from utils import isEventPost
|
||||
|
@ -145,7 +146,8 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
|||
nickname: str, domain: str, port: int,
|
||||
postJsonObject: {},
|
||||
allowDeletion: bool, boxname: str,
|
||||
showPublishedDateOnly: bool) -> None:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> None:
|
||||
"""Converts the json post into html and stores it in a cache
|
||||
This enables the post to be quickly displayed later
|
||||
"""
|
||||
|
@ -170,6 +172,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
|||
avatarUrl, True, allowDeletion,
|
||||
httpPrefix, __version__, boxname, None,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
not isDM(postJsonObject),
|
||||
True, True, False, True)
|
||||
|
||||
|
@ -604,10 +607,7 @@ def _receiveUndoFollow(session, baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: follow request has no actor within object')
|
||||
return False
|
||||
if '/users/' not in messageJson['object']['actor'] and \
|
||||
'/accounts/' not in messageJson['object']['actor'] and \
|
||||
'/channel/' not in messageJson['object']['actor'] and \
|
||||
'/profile/' not in messageJson['object']['actor']:
|
||||
if not hasUsersPath(messageJson['object']['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing ' +
|
||||
'from actor within object')
|
||||
|
@ -668,10 +668,7 @@ def _receiveUndo(session, baseDir: str, httpPrefix: str,
|
|||
if debug:
|
||||
print('DEBUG: follow request has no actor')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor')
|
||||
return False
|
||||
|
@ -735,19 +732,19 @@ def _personReceiveUpdate(baseDir: str,
|
|||
' ' + str(personJson))
|
||||
domainFull = getFullDomain(domain, port)
|
||||
updateDomainFull = getFullDomain(updateDomain, updatePort)
|
||||
actor = updateDomainFull + '/users/' + updateNickname
|
||||
if actor not in personJson['id']:
|
||||
actor = updateDomainFull + '/profile/' + updateNickname
|
||||
if actor not in personJson['id']:
|
||||
actor = updateDomainFull + '/channel/' + updateNickname
|
||||
if actor not in personJson['id']:
|
||||
actor = updateDomainFull + '/accounts/' + updateNickname
|
||||
if actor not in personJson['id']:
|
||||
if debug:
|
||||
print('actor: ' + actor)
|
||||
print('id: ' + personJson['id'])
|
||||
print('DEBUG: Actor does not match id')
|
||||
return False
|
||||
usersPaths = ('users', 'profile', 'channel', 'accounts')
|
||||
usersStrFound = False
|
||||
for usersStr in usersPaths:
|
||||
actor = updateDomainFull + '/' + usersStr + '/' + updateNickname
|
||||
if actor in personJson['id']:
|
||||
usersStrFound = True
|
||||
break
|
||||
if not usersStrFound:
|
||||
if debug:
|
||||
print('actor: ' + actor)
|
||||
print('id: ' + personJson['id'])
|
||||
print('DEBUG: Actor does not match id')
|
||||
return False
|
||||
if updateDomainFull == domainFull:
|
||||
if debug:
|
||||
print('DEBUG: You can only receive actor updates ' +
|
||||
|
@ -859,10 +856,7 @@ def _receiveUpdate(recentPostsCache: {}, session, baseDir: str,
|
|||
if debug:
|
||||
print('DEBUG: ' + messageJson['type'] + ' object has no type')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor in ' +
|
||||
messageJson['type'])
|
||||
|
@ -943,10 +937,7 @@ def _receiveLike(recentPostsCache: {},
|
|||
if debug:
|
||||
print('DEBUG: ' + messageJson['type'] + ' has no "to" list')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor in ' +
|
||||
messageJson['type'])
|
||||
|
@ -1014,10 +1005,7 @@ def _receiveUndoLike(recentPostsCache: {},
|
|||
print('DEBUG: ' + messageJson['type'] +
|
||||
' like object is not a string')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor in ' +
|
||||
messageJson['type'] + ' like')
|
||||
|
@ -1219,10 +1207,7 @@ def _receiveDelete(session, handle: str, isGroup: bool, baseDir: str,
|
|||
if debug:
|
||||
print('DEBUG: ' + messageJson['type'] + ' has no "to" list')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: ' +
|
||||
'"users" or "profile" missing from actor in ' +
|
||||
|
@ -1303,19 +1288,13 @@ def _receiveAnnounce(recentPostsCache: {},
|
|||
if debug:
|
||||
print('DEBUG: ' + messageJson['type'] + ' has no "to" list')
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: ' +
|
||||
'"users" or "profile" missing from actor in ' +
|
||||
messageJson['type'])
|
||||
return False
|
||||
if '/users/' not in messageJson['object'] and \
|
||||
'/accounts/' not in messageJson['object'] and \
|
||||
'/channel/' not in messageJson['object'] and \
|
||||
'/profile/' not in messageJson['object']:
|
||||
if not hasUsersPath(messageJson['object']):
|
||||
if debug:
|
||||
print('DEBUG: ' +
|
||||
'"users", "channel" or "profile" missing in ' +
|
||||
|
@ -1387,10 +1366,7 @@ def _receiveAnnounce(recentPostsCache: {},
|
|||
if isinstance(attrib, str):
|
||||
lookupActor = attrib
|
||||
if lookupActor:
|
||||
if '/users/' in lookupActor or \
|
||||
'/accounts/' in lookupActor or \
|
||||
'/channel/' in lookupActor or \
|
||||
'/profile/' in lookupActor:
|
||||
if hasUsersPath(lookupActor):
|
||||
if '/statuses/' in lookupActor:
|
||||
lookupActor = lookupActor.split('/statuses/')[0]
|
||||
|
||||
|
@ -1439,10 +1415,7 @@ def _receiveUndoAnnounce(recentPostsCache: {},
|
|||
return False
|
||||
if messageJson['object']['type'] != 'Announce':
|
||||
return False
|
||||
if '/users/' not in messageJson['actor'] and \
|
||||
'/accounts/' not in messageJson['actor'] and \
|
||||
'/channel/' not in messageJson['actor'] and \
|
||||
'/profile/' not in messageJson['actor']:
|
||||
if not hasUsersPath(messageJson['actor']):
|
||||
if debug:
|
||||
print('DEBUG: "users" or "profile" missing from actor in ' +
|
||||
messageJson['type'] + ' announce')
|
||||
|
@ -1688,10 +1661,7 @@ def _obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str,
|
|||
if not isinstance(lookupActor, str):
|
||||
return
|
||||
|
||||
if not ('/users/' in lookupActor or
|
||||
'/accounts/' in lookupActor or
|
||||
'/channel/' in lookupActor or
|
||||
'/profile/' in lookupActor):
|
||||
if not hasUsersPath(lookupActor):
|
||||
return
|
||||
|
||||
if '/statuses/' in lookupActor:
|
||||
|
@ -2071,7 +2041,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
|
|||
maxMentions: int, maxEmoji: int, translate: {},
|
||||
unitTest: bool, YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
allowLocalNetworkAccess: bool) -> bool:
|
||||
allowLocalNetworkAccess: bool,
|
||||
peertubeInstances: []) -> bool:
|
||||
""" Anything which needs to be done after initial checks have passed
|
||||
"""
|
||||
actor = keyId
|
||||
|
@ -2378,7 +2349,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
|
|||
postJsonObject,
|
||||
allowDeletion,
|
||||
boxname,
|
||||
showPublishedDateOnly)
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances)
|
||||
if debug:
|
||||
timeDiff = \
|
||||
str(int((time.time() - htmlCacheStartTime) *
|
||||
|
@ -2478,7 +2450,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
|||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
allowNewsFollowers: bool,
|
||||
maxFollowers: int, allowLocalNetworkAccess: bool) -> None:
|
||||
maxFollowers: int, allowLocalNetworkAccess: bool,
|
||||
peertubeInstances: []) -> None:
|
||||
"""Processes received items and moves them to the appropriate
|
||||
directories
|
||||
"""
|
||||
|
@ -2895,7 +2868,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
|||
translate, unitTest,
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
allowLocalNetworkAccess)
|
||||
allowLocalNetworkAccess,
|
||||
peertubeInstances)
|
||||
if debug:
|
||||
pprint(queueJson['post'])
|
||||
|
||||
|
|
6
like.py
6
like.py
|
@ -6,6 +6,7 @@ __maintainer__ = "Bob Mottram"
|
|||
__email__ = "bob@freedombone.net"
|
||||
__status__ = "Production"
|
||||
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import removeIdEnding
|
||||
from utils import urlPermitted
|
||||
|
@ -87,10 +88,7 @@ def _like(recentPostsCache: {},
|
|||
likedPostNickname = getNicknameFromActor(actorLiked)
|
||||
likedPostDomain, likedPostPort = getDomainFromActor(actorLiked)
|
||||
else:
|
||||
if '/users/' in objectUrl or \
|
||||
'/accounts/' in objectUrl or \
|
||||
'/channel/' in objectUrl or \
|
||||
'/profile/' in objectUrl:
|
||||
if hasUsersPath(objectUrl):
|
||||
likedPostNickname = getNicknameFromActor(objectUrl)
|
||||
likedPostDomain, likedPostPort = getDomainFromActor(objectUrl)
|
||||
|
||||
|
|
6
posts.py
6
posts.py
|
@ -30,6 +30,7 @@ from session import postJsonString
|
|||
from session import postImage
|
||||
from webfinger import webfingerHandle
|
||||
from httpsig import createSignedHeader
|
||||
from utils import hasUsersPath
|
||||
from utils import validPostDate
|
||||
from utils import getFullDomain
|
||||
from utils import getFollowersList
|
||||
|
@ -155,10 +156,7 @@ def getUserUrl(wfRequest: {}, sourceId=0) -> str:
|
|||
continue
|
||||
if link['type'] != 'application/activity+json':
|
||||
continue
|
||||
if not ('/users/' in link['href'] or
|
||||
'/accounts/' in link['href'] or
|
||||
'/profile/' in link['href'] or
|
||||
'/channel/' in link['href']):
|
||||
if not hasUsersPath(link['href']):
|
||||
print('getUserUrl webfinger activity+json ' +
|
||||
'contains single user instance actor ' +
|
||||
str(sourceId) + ' ' + str(link))
|
||||
|
|
154
tests.py
154
tests.py
|
@ -854,7 +854,7 @@ def testFollowBetweenServers():
|
|||
True, __version__, False)
|
||||
print('sendResult: ' + str(sendResult))
|
||||
|
||||
for t in range(10):
|
||||
for t in range(16):
|
||||
if os.path.isfile(bobDir + '/accounts/bob@' +
|
||||
bobDomain + '/followers.txt'):
|
||||
if os.path.isfile(aliceDir + '/accounts/alice@' +
|
||||
|
@ -2613,9 +2613,10 @@ def getFunctionCalls(name: str, lines: [], startLineCtr: int,
|
|||
callsFunctions = []
|
||||
functionContentStr = ''
|
||||
for lineCtr in range(startLineCtr + 1, len(lines)):
|
||||
if lines[lineCtr].startswith('def '):
|
||||
lineStr = lines[lineCtr].strip()
|
||||
if lineStr.startswith('def '):
|
||||
break
|
||||
if lines[lineCtr].startswith('class '):
|
||||
if lineStr.startswith('class '):
|
||||
break
|
||||
functionContentStr += lines[lineCtr]
|
||||
for funcName, properties in functionProperties.items():
|
||||
|
@ -2635,14 +2636,14 @@ def functionArgsMatch(callArgs: [], funcArgs: []):
|
|||
for a in callArgs:
|
||||
if a == 'self':
|
||||
continue
|
||||
if '=' not in a:
|
||||
if '=' not in a or a.startswith("'"):
|
||||
callArgsCtr += 1
|
||||
|
||||
funcArgsCtr = 0
|
||||
for a in funcArgs:
|
||||
if a == 'self':
|
||||
continue
|
||||
if '=' not in a:
|
||||
if '=' not in a or a.startswith("'"):
|
||||
funcArgsCtr += 1
|
||||
|
||||
return callArgsCtr >= funcArgsCtr
|
||||
|
@ -2670,7 +2671,7 @@ def testFunctions():
|
|||
lines = f.readlines()
|
||||
modules[modName]['lines'] = lines
|
||||
for line in lines:
|
||||
if not line.startswith('def '):
|
||||
if not line.strip().startswith('def '):
|
||||
continue
|
||||
methodName = line.split('def ', 1)[1].split('(')[0]
|
||||
methodArgs = \
|
||||
|
@ -2694,7 +2695,9 @@ def testFunctions():
|
|||
'pyjsonld'
|
||||
]
|
||||
excludeFuncs = [
|
||||
'link'
|
||||
'link',
|
||||
'set',
|
||||
'get'
|
||||
]
|
||||
# which modules is each function used within?
|
||||
for modName, modProperties in modules.items():
|
||||
|
@ -2702,7 +2705,11 @@ def testFunctions():
|
|||
for name, properties in functionProperties.items():
|
||||
lineCtr = 0
|
||||
for line in modules[modName]['lines']:
|
||||
if line.startswith('def '):
|
||||
lineStr = line.strip()
|
||||
if lineStr.startswith('def '):
|
||||
lineCtr += 1
|
||||
continue
|
||||
if lineStr.startswith('class '):
|
||||
lineCtr += 1
|
||||
continue
|
||||
if name + '(' in line:
|
||||
|
@ -2735,7 +2742,22 @@ def testFunctions():
|
|||
|
||||
# don't check these functions, because they are procedurally called
|
||||
exclusions = [
|
||||
'do_GET',
|
||||
'do_POST',
|
||||
'do_HEAD',
|
||||
'__run',
|
||||
'globaltrace',
|
||||
'localtrace',
|
||||
'kill',
|
||||
'clone',
|
||||
'unregister_rdf_parser',
|
||||
'set_document_loader',
|
||||
'has_property',
|
||||
'has_value',
|
||||
'add_value',
|
||||
'get_values',
|
||||
'remove_property',
|
||||
'remove_value',
|
||||
'normalize',
|
||||
'get_document_loader',
|
||||
'runInboxQueueWatchdog',
|
||||
|
@ -2764,17 +2786,26 @@ def testFunctions():
|
|||
'setOrganizationScheme'
|
||||
]
|
||||
excludeImports = [
|
||||
'link'
|
||||
'link',
|
||||
'start'
|
||||
]
|
||||
excludeLocal = [
|
||||
'pyjsonld',
|
||||
'daemon',
|
||||
'tests'
|
||||
]
|
||||
excludeMods = [
|
||||
'pyjsonld'
|
||||
]
|
||||
# check that functions are called somewhere
|
||||
for name, properties in functionProperties.items():
|
||||
if name.startswith('__'):
|
||||
if name.endswith('__'):
|
||||
continue
|
||||
if name in exclusions:
|
||||
continue
|
||||
if properties['module'] in excludeMods:
|
||||
continue
|
||||
isLocalFunction = False
|
||||
if not properties['calledInModule']:
|
||||
print('function ' + name +
|
||||
|
@ -2815,18 +2846,80 @@ def testFunctions():
|
|||
assert False
|
||||
print('Function: ' + name + ' ✓')
|
||||
|
||||
print('Constructing call graph')
|
||||
print('Constructing function call graph')
|
||||
moduleColors = ('red', 'green', 'yellow', 'orange', 'purple', 'cyan',
|
||||
'darkgoldenrod3', 'darkolivegreen1', 'darkorange1',
|
||||
'darkorchid1', 'darkseagreen', 'darkslategray4',
|
||||
'deeppink1', 'deepskyblue1', 'dimgrey', 'gold1',
|
||||
'goldenrod', 'burlywood2', 'bisque1', 'brown1',
|
||||
'chartreuse2', 'cornsilk', 'darksalmon')
|
||||
maxModuleCalls = 1
|
||||
maxFunctionCalls = 1
|
||||
colorCtr = 0
|
||||
for modName, modProperties in modules.items():
|
||||
lineCtr = 0
|
||||
modules[modName]['color'] = moduleColors[colorCtr]
|
||||
colorCtr += 1
|
||||
if colorCtr >= len(moduleColors):
|
||||
colorCtr = 0
|
||||
for line in modules[modName]['lines']:
|
||||
if line.startswith('def '):
|
||||
if line.strip().startswith('def '):
|
||||
name = line.split('def ')[1].split('(')[0]
|
||||
callsList = \
|
||||
getFunctionCalls(name, modules[modName]['lines'],
|
||||
lineCtr, functionProperties)
|
||||
functionProperties[name]['calls'] = callsList.copy()
|
||||
if len(callsList) > maxFunctionCalls:
|
||||
maxFunctionCalls = len(callsList)
|
||||
# keep track of which module calls which other module
|
||||
for fn in callsList:
|
||||
modCall = functionProperties[fn]['module']
|
||||
if modCall != modName:
|
||||
if modules[modName].get('calls'):
|
||||
if modCall not in modules[modName]['calls']:
|
||||
modules[modName]['calls'].append(modCall)
|
||||
if len(modules[modName]['calls']) > \
|
||||
maxModuleCalls:
|
||||
maxModuleCalls = \
|
||||
len(modules[modName]['calls'])
|
||||
else:
|
||||
modules[modName]['calls'] = [modCall]
|
||||
lineCtr += 1
|
||||
callGraphStr = 'digraph EpicyonModules {\n\n'
|
||||
callGraphStr += ' graph [fontsize=10 fontname="Verdana" compound=true];\n'
|
||||
callGraphStr += ' node [shape=record fontsize=10 fontname="Verdana"];\n\n'
|
||||
# colors of modules nodes
|
||||
for modName, modProperties in modules.items():
|
||||
if not modProperties.get('calls'):
|
||||
callGraphStr += ' "' + modName + \
|
||||
'" [fillcolor=yellow style=filled];\n'
|
||||
continue
|
||||
if len(modProperties['calls']) <= int(maxModuleCalls / 8):
|
||||
callGraphStr += ' "' + modName + \
|
||||
'" [fillcolor=green style=filled];\n'
|
||||
elif len(modProperties['calls']) < int(maxModuleCalls / 4):
|
||||
callGraphStr += ' "' + modName + \
|
||||
'" [fillcolor=orange style=filled];\n'
|
||||
else:
|
||||
callGraphStr += ' "' + modName + \
|
||||
'" [fillcolor=red style=filled];\n'
|
||||
callGraphStr += '\n'
|
||||
# connections between modules
|
||||
for modName, modProperties in modules.items():
|
||||
if not modProperties.get('calls'):
|
||||
continue
|
||||
for modCall in modProperties['calls']:
|
||||
callGraphStr += ' "' + modName + '" -> "' + modCall + '";\n'
|
||||
callGraphStr += '\n}\n'
|
||||
with open('epicyon_modules.dot', 'w+') as fp:
|
||||
fp.write(callGraphStr)
|
||||
print('Modules call graph saved to epicyon_modules.dot')
|
||||
print('Plot using: ' +
|
||||
'sfdp -x -Goverlap=false -Goverlap_scaling=2 ' +
|
||||
'-Gsep=+100 -Tx11 epicyon_modules.dot')
|
||||
|
||||
callGraphStr = 'digraph Epicyon {\n\n'
|
||||
callGraphStr += ' size="8,6"; ratio=fill;\n'
|
||||
callGraphStr += ' graph [fontsize=10 fontname="Verdana" compound=true];\n'
|
||||
callGraphStr += ' node [shape=record fontsize=10 fontname="Verdana"];\n\n'
|
||||
|
||||
|
@ -2834,25 +2927,52 @@ def testFunctions():
|
|||
callGraphStr += ' subgraph cluster_' + modName + ' {\n'
|
||||
callGraphStr += ' label = "' + modName + '";\n'
|
||||
callGraphStr += ' node [style=filled];\n'
|
||||
callGraphStr += ' '
|
||||
moduleFunctionsStr = ''
|
||||
for name in modProperties['functions']:
|
||||
callGraphStr += '"' + name + '" '
|
||||
callGraphStr += ';\n'
|
||||
if name.startswith('test'):
|
||||
continue
|
||||
if name not in excludeFuncs:
|
||||
if not functionProperties[name]['calls']:
|
||||
moduleFunctionsStr += \
|
||||
' "' + name + '" [fillcolor=yellow style=filled];\n'
|
||||
continue
|
||||
noOfCalls = len(functionProperties[name]['calls'])
|
||||
if noOfCalls < int(maxFunctionCalls / 4):
|
||||
moduleFunctionsStr += ' "' + name + \
|
||||
'" [fillcolor=orange style=filled];\n'
|
||||
else:
|
||||
moduleFunctionsStr += ' "' + name + \
|
||||
'" [fillcolor=red style=filled];\n'
|
||||
|
||||
if moduleFunctionsStr:
|
||||
callGraphStr += moduleFunctionsStr + '\n'
|
||||
callGraphStr += ' color=blue;\n'
|
||||
callGraphStr += ' }\n\n'
|
||||
|
||||
for name, properties in functionProperties.items():
|
||||
if not properties['calls']:
|
||||
continue
|
||||
noOfCalls = len(properties['calls'])
|
||||
if noOfCalls <= int(maxFunctionCalls / 8):
|
||||
modColor = 'blue'
|
||||
elif noOfCalls < int(maxFunctionCalls / 4):
|
||||
modColor = 'green'
|
||||
else:
|
||||
modColor = 'red'
|
||||
for calledFunc in properties['calls']:
|
||||
callGraphStr += ' "' + name + '" -> "' + calledFunc + '";\n'
|
||||
if calledFunc.startswith('test'):
|
||||
continue
|
||||
if calledFunc not in excludeFuncs:
|
||||
callGraphStr += ' "' + name + '" -> "' + calledFunc + \
|
||||
'" [color=' + modColor + '];\n'
|
||||
|
||||
callGraphStr += '\n}\n'
|
||||
with open('epicyon.dot', 'w+') as fp:
|
||||
fp.write(callGraphStr)
|
||||
print('Call graph saved to epicyon.dot')
|
||||
print('Convert to image with: ' +
|
||||
'dot -Tjpg epicyon.dot -o epicyon_diagram.jpg')
|
||||
print('Plot using: ' +
|
||||
'sfdp -x -Goverlap=prism -Goverlap_scaling=8 ' +
|
||||
'-Gsep=+120 -Tx11 epicyon.dot')
|
||||
|
||||
|
||||
def runAllTests():
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"post-separator-margin-top": "10px",
|
||||
"post-separator-margin-bottom": "10px",
|
||||
"calendar-header-font-style": "normal",
|
||||
"italic-font-style": "normal",
|
||||
"calendar-header-font": "'Orbitron'",
|
||||
|
@ -22,8 +24,6 @@
|
|||
"publish-button-at-top": "False",
|
||||
"main-visited-color": "#46eed5",
|
||||
"options-main-visited-color": "#46eed5",
|
||||
"post-separator-margin-top": "9%",
|
||||
"post-separator-margin-bottom": "9%",
|
||||
"post-separator-width": "80%",
|
||||
"post-separator-height": "10%",
|
||||
"column-left-header-background": "#6800e7",
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "تصفية الكلمات",
|
||||
"Unfilter": "غير مرشح",
|
||||
"Unfilter words": "الكلمات غير المصفاة",
|
||||
"Show Accounts": "إظهار الحسابات"
|
||||
"Show Accounts": "إظهار الحسابات",
|
||||
"Peertube Instances": "مثيلات Peertube",
|
||||
"Show video previews for the following Peertube sites.": "إظهار معاينات الفيديو لمواقع Peertube التالية."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filtra les paraules",
|
||||
"Unfilter": "Sense filtre",
|
||||
"Unfilter words": "Paraules sense filtre",
|
||||
"Show Accounts": "Mostra comptes"
|
||||
"Show Accounts": "Mostra comptes",
|
||||
"Peertube Instances": "Instàncies de Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Mostra les previsualitzacions de vídeo dels següents llocs de Peertube."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Hidlo geiriau",
|
||||
"Unfilter": "Di-hid",
|
||||
"Unfilter words": "Geiriau di-hid",
|
||||
"Show Accounts": "Dangos Cyfrifon"
|
||||
"Show Accounts": "Dangos Cyfrifon",
|
||||
"Peertube Instances": "Camau Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Dangos rhagolygon fideo ar gyfer y safleoedd Peertube canlynol."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Wörter herausfiltern",
|
||||
"Unfilter": "Filter entfernen",
|
||||
"Unfilter words": "Wörter herausfiltern",
|
||||
"Show Accounts": "Konten anzeigen"
|
||||
"Show Accounts": "Konten anzeigen",
|
||||
"Peertube Instances": "Peertube-Instanzen",
|
||||
"Show video previews for the following Peertube sites.": "Zeigen Sie eine Videovorschau für die folgenden Peertube-Websites an."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filter out words",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "Unfilter words",
|
||||
"Show Accounts": "Show Accounts"
|
||||
"Show Accounts": "Show Accounts",
|
||||
"Peertube Instances": "Peertube Instances",
|
||||
"Show video previews for the following Peertube sites.": "Show video previews for the following Peertube sites."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filtrar palabras",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "Palabras sin filtrar",
|
||||
"Show Accounts": "Mostrar cuentas"
|
||||
"Show Accounts": "Mostrar cuentas",
|
||||
"Peertube Instances": "Instancias de Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Muestre vistas previas de video para los siguientes sitios de Peertube."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filtrer les mots",
|
||||
"Unfilter": "Non filtrer",
|
||||
"Unfilter words": "Mots non filtrés",
|
||||
"Show Accounts": "Afficher les comptes"
|
||||
"Show Accounts": "Afficher les comptes",
|
||||
"Peertube Instances": "Instances Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Afficher des aperçus vidéo pour les sites Peertube suivants."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Scag focail amach",
|
||||
"Unfilter": "Neamhleithleach",
|
||||
"Unfilter words": "Focail neamhleithleacha",
|
||||
"Show Accounts": "Taispeáin Cuntais"
|
||||
"Show Accounts": "Taispeáin Cuntais",
|
||||
"Peertube Instances": "Imeachtaí Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Taispeáin réamhamharcanna físe do na suíomhanna Peertube seo a leanas."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "शब्दों को फ़िल्टर करें",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "अनफ़िल्टर शब्द",
|
||||
"Show Accounts": "खाते दिखाएं"
|
||||
"Show Accounts": "खाते दिखाएं",
|
||||
"Peertube Instances": "Peertube उदाहरण",
|
||||
"Show video previews for the following Peertube sites.": "निम्नलिखित Peertube साइटों के लिए वीडियो पूर्वावलोकन दिखाएं।"
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filtra le parole",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "Parole non filtrate",
|
||||
"Show Accounts": "Mostra account"
|
||||
"Show Accounts": "Mostra account",
|
||||
"Peertube Instances": "Istanze di Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Mostra le anteprime dei video per i seguenti siti Peertube."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "単語を除外する",
|
||||
"Unfilter": "フィルタリング解除",
|
||||
"Unfilter words": "単語のフィルタリングを解除する",
|
||||
"Show Accounts": "アカウントを表示する"
|
||||
"Show Accounts": "アカウントを表示する",
|
||||
"Peertube Instances": "Peertubeインスタンス",
|
||||
"Show video previews for the following Peertube sites.": "次のPeertubeサイトのビデオプレビューを表示します。"
|
||||
}
|
||||
|
|
|
@ -343,5 +343,7 @@
|
|||
"Filter out words": "Filter out words",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "Unfilter words",
|
||||
"Show Accounts": "Show Accounts"
|
||||
"Show Accounts": "Show Accounts",
|
||||
"Peertube Instances": "Peertube Instances",
|
||||
"Show video previews for the following Peertube sites.": "Show video previews for the following Peertube sites."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Filtrar palavras",
|
||||
"Unfilter": "Unfilter",
|
||||
"Unfilter words": "Palavras sem filtro",
|
||||
"Show Accounts": "Mostrar contas"
|
||||
"Show Accounts": "Mostrar contas",
|
||||
"Peertube Instances": "Instâncias Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Mostrar visualizações de vídeo para os seguintes sites Peertube."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "Отфильтровать слова",
|
||||
"Unfilter": "Нефильтровать",
|
||||
"Unfilter words": "Не фильтровать слова",
|
||||
"Show Accounts": "Показать счета"
|
||||
"Show Accounts": "Показать счета",
|
||||
"Peertube Instances": "Экземпляры Peertube",
|
||||
"Show video previews for the following Peertube sites.": "Показать превью видео для следующих сайтов Peertube."
|
||||
}
|
||||
|
|
|
@ -347,5 +347,7 @@
|
|||
"Filter out words": "过滤掉单词",
|
||||
"Unfilter": "取消过滤",
|
||||
"Unfilter words": "未过滤字词",
|
||||
"Show Accounts": "显示帐户"
|
||||
"Show Accounts": "显示帐户",
|
||||
"Peertube Instances": "Peertube实例",
|
||||
"Show video previews for the following Peertube sites.": "显示以下Peertube网站的视频预览。"
|
||||
}
|
||||
|
|
10
utils.py
10
utils.py
|
@ -19,6 +19,16 @@ from calendar import monthrange
|
|||
from followingCalendar import addPersonToCalendar
|
||||
|
||||
|
||||
def hasUsersPath(pathStr: str) -> bool:
|
||||
"""Whether there is a /users/ path (or equivalent) in the given string
|
||||
"""
|
||||
usersList = ('users', 'accounts', 'channel', 'profile')
|
||||
for usersStr in usersList:
|
||||
if '/' + usersStr + '/' in pathStr:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def validPostDate(published: str, maxAgeDays=7) -> bool:
|
||||
"""Returns true if the published date is recent and is not in the future
|
||||
"""
|
||||
|
|
|
@ -28,7 +28,8 @@ def htmlConfirmDelete(cssCache: {},
|
|||
wfRequest: {}, personCache: {},
|
||||
callingDomain: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Shows a screen asking to confirm the deletion of a post
|
||||
"""
|
||||
if '/statuses/' not in messageId:
|
||||
|
@ -66,6 +67,7 @@ def htmlConfirmDelete(cssCache: {},
|
|||
httpPrefix, projectVersion, 'outbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, False, False, False, False)
|
||||
deletePostStr += '<center>'
|
||||
deletePostStr += \
|
||||
|
|
|
@ -27,7 +27,8 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
session, wfRequest: {}, personCache: {},
|
||||
projectVersion: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Shows posts on the front screen of a news instance
|
||||
These should only be public blog posts from the features timeline
|
||||
which is the blog timeline of the news actor
|
||||
|
@ -65,6 +66,7 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, False, False, True, False)
|
||||
if postStr:
|
||||
profileStr += postStr + separatorStr
|
||||
|
@ -85,7 +87,9 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
|||
session, wfRequest: {}, personCache: {},
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
newswire: {}, theme: str, extraJson=None,
|
||||
newswire: {}, theme: str,
|
||||
peertubeInstances: [],
|
||||
extraJson=None,
|
||||
pageNumber=None, maxItemsPerPage=None) -> str:
|
||||
"""Show the news instance front screen
|
||||
"""
|
||||
|
@ -148,7 +152,8 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
|||
session, wfRequest, personCache,
|
||||
projectVersion,
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly) + licenseStr
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances) + licenseStr
|
||||
|
||||
# Footer which is only used for system accounts
|
||||
profileFooterStr = ' </td>\n'
|
||||
|
|
121
webapp_media.py
121
webapp_media.py
|
@ -6,8 +6,30 @@ __maintainer__ = "Bob Mottram"
|
|||
__email__ = "bob@freedombone.net"
|
||||
__status__ = "Production"
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def loadPeertubeInstances(baseDir: str, peertubeInstances: []) -> None:
|
||||
"""Loads peertube instances from file into the given list
|
||||
"""
|
||||
peertubeList = None
|
||||
peertubeInstancesFilename = baseDir + '/accounts/peertube.txt'
|
||||
if os.path.isfile(peertubeInstancesFilename):
|
||||
with open(peertubeInstancesFilename, 'r') as fp:
|
||||
peertubeStr = fp.read()
|
||||
if peertubeStr:
|
||||
peertubeStr = peertubeStr.replace('\r', '')
|
||||
peertubeList = peertubeStr.split('\n')
|
||||
if not peertubeList:
|
||||
return
|
||||
for url in peertubeList:
|
||||
if url in peertubeInstances:
|
||||
continue
|
||||
peertubeInstances.append(url)
|
||||
|
||||
|
||||
def _addEmbeddedVideoFromSites(translate: {}, content: str,
|
||||
peertubeInstances: [],
|
||||
width=400, height=300) -> str:
|
||||
"""Adds embedded videos
|
||||
"""
|
||||
|
@ -39,8 +61,14 @@ def _addEmbeddedVideoFromSites(translate: {}, content: str,
|
|||
"allowfullscreen></iframe>\n</center>\n"
|
||||
return content
|
||||
|
||||
invidiousSites = ('https://invidio.us',
|
||||
'https://invidious.snopyta.org',
|
||||
invidiousSites = ('https://invidious.snopyta.org',
|
||||
'https://yewtu.be',
|
||||
'https://tube.connect.cafe',
|
||||
'https://invidious.kavin.rocks',
|
||||
'https://invidiou.site',
|
||||
'https://invidious.tube',
|
||||
'https://invidious.xyz',
|
||||
'https://invidious.zapashcanon.fr',
|
||||
'http://c7hqkpkpemu6e7emz5b4vy' +
|
||||
'z7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion',
|
||||
'http://axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4' +
|
||||
|
@ -76,38 +104,59 @@ def _addEmbeddedVideoFromSites(translate: {}, content: str,
|
|||
return content
|
||||
|
||||
if '"https://' in content:
|
||||
# A selection of the current larger peertube sites, mostly
|
||||
# French and German language
|
||||
# These have been chosen based on reported numbers of users
|
||||
# and the content of each has not been reviewed, so mileage could vary
|
||||
peerTubeSites = ('peertube.mastodon.host', 'open.tube', 'share.tube',
|
||||
'tube.tr4sk.me', 'videos.elbinario.net',
|
||||
'hkvideo.live',
|
||||
'peertube.snargol.com', 'tube.22decembre.eu',
|
||||
'tube.fabrigli.fr', 'libretube.net', 'libre.video',
|
||||
'peertube.linuxrocks.online', 'spacepub.space',
|
||||
'video.ploud.jp', 'video.omniatv.com',
|
||||
'peertube.servebeer.com',
|
||||
'tube.tchncs.de', 'tubee.fr', 'video.alternanet.fr',
|
||||
'devtube.dev-wiki.de', 'video.samedi.pm',
|
||||
'video.irem.univ-paris-diderot.fr',
|
||||
'peertube.openstreetmap.fr', 'video.antopie.org',
|
||||
'scitech.video', 'tube.4aem.com', 'video.ploud.fr',
|
||||
'peervideo.net', 'video.valme.io',
|
||||
'videos.pair2jeux.tube',
|
||||
'vault.mle.party', 'hostyour.tv',
|
||||
'diode.zone', 'visionon.tv',
|
||||
'artitube.artifaille.fr', 'peertube.fr',
|
||||
'peertube.live', 'kolektiva.media',
|
||||
'tube.ac-lyon.fr', 'www.yiny.org', 'betamax.video',
|
||||
'tube.piweb.be', 'pe.ertu.be', 'peertube.social',
|
||||
'videos.lescommuns.org', 'peertube.nogafa.org',
|
||||
'skeptikon.fr', 'video.tedomum.net',
|
||||
'tube.p2p.legal', 'tilvids.com',
|
||||
'sikke.fi', 'exode.me', 'peertube.video')
|
||||
if peertubeInstances:
|
||||
peerTubeSites = peertubeInstances
|
||||
else:
|
||||
# A default selection of the current larger peertube sites,
|
||||
# mostly French and German language.
|
||||
# These have only been semi-vetted, and so should be under
|
||||
# continuous review.
|
||||
# Also see https://peertube_isolation.frama.io/list/ for
|
||||
# adversarial instances. Nothing in that list should be
|
||||
# in the defaults below.
|
||||
peerTubeSites = ('share.tube',
|
||||
'tube.22decembre.eu',
|
||||
'libre.video',
|
||||
'peertube.linuxrocks.online',
|
||||
'spacepub.space',
|
||||
'tube.tchncs.de',
|
||||
'video.irem.univ-paris-diderot.fr',
|
||||
'peertube.openstreetmap.fr',
|
||||
'video.antopie.org',
|
||||
'scitech.video',
|
||||
'video.ploud.fr',
|
||||
'diode.zone',
|
||||
'visionon.tv',
|
||||
'peertube.fr',
|
||||
'peertube.live',
|
||||
'kolektiva.media',
|
||||
'betamax.video',
|
||||
'peertube.social',
|
||||
'videos.lescommuns.org',
|
||||
'video.tedomum.net',
|
||||
'tilvids.com',
|
||||
'exode.me',
|
||||
'peertube.video')
|
||||
for site in peerTubeSites:
|
||||
if '"https://' + site in content:
|
||||
url = content.split('"https://' + site)[1]
|
||||
site = site.strip()
|
||||
if not site:
|
||||
continue
|
||||
if len(site) < 5:
|
||||
continue
|
||||
if '.' not in site:
|
||||
continue
|
||||
siteStr = site
|
||||
if site.startswith('http://'):
|
||||
site = site.replace('http://', '')
|
||||
elif site.startswith('https://'):
|
||||
site = site.replace('https://', '')
|
||||
if site.endswith('.onion') or site.endswith('.i2p'):
|
||||
siteStr = 'http://' + site
|
||||
else:
|
||||
siteStr = 'https://' + site
|
||||
siteStr = '"' + siteStr
|
||||
if siteStr in content:
|
||||
url = content.split(siteStr)[1]
|
||||
if '"' in url:
|
||||
url = url.split('"')[0].replace('/watch/', '/embed/')
|
||||
content = \
|
||||
|
@ -216,9 +265,11 @@ def _addEmbeddedVideo(translate: {}, content: str,
|
|||
return content
|
||||
|
||||
|
||||
def addEmbeddedElements(translate: {}, content: str) -> str:
|
||||
def addEmbeddedElements(translate: {}, content: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Adds embedded elements for various media types
|
||||
"""
|
||||
content = _addEmbeddedVideoFromSites(translate, content)
|
||||
content = _addEmbeddedVideoFromSites(translate, content,
|
||||
peertubeInstances)
|
||||
content = _addEmbeddedAudio(translate, content)
|
||||
return _addEmbeddedVideo(translate, content)
|
||||
|
|
|
@ -37,7 +37,7 @@ def htmlModeration(cssCache: {}, defaultTimeline: str,
|
|||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, moderationActionStr: str,
|
||||
theme: str) -> str:
|
||||
theme: str, peertubeInstances: []) -> str:
|
||||
"""Show the moderation feed as html
|
||||
This is what you see when selecting the "mod" timeline
|
||||
"""
|
||||
|
@ -51,7 +51,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str,
|
|||
newswire, False, False, positiveVoting,
|
||||
showPublishAsIcon, fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, moderationActionStr, theme)
|
||||
authorized, moderationActionStr, theme,
|
||||
peertubeInstances)
|
||||
|
||||
|
||||
def htmlAccountInfo(cssCache: {}, translate: {},
|
||||
|
|
|
@ -39,6 +39,7 @@ def htmlPersonOptions(defaultTimeline: str,
|
|||
ssbAddress: str,
|
||||
blogAddress: str,
|
||||
toxAddress: str,
|
||||
briarAddress: str,
|
||||
jamiAddress: str,
|
||||
PGPpubKey: str,
|
||||
PGPfingerprint: str,
|
||||
|
@ -141,6 +142,15 @@ def htmlPersonOptions(defaultTimeline: str,
|
|||
if toxAddress:
|
||||
optionsStr += \
|
||||
'<p class="imText">Tox: ' + removeHtml(toxAddress) + '</p>\n'
|
||||
if briarAddress:
|
||||
if briarAddress.startswith('briar://'):
|
||||
optionsStr += \
|
||||
'<p class="imText">' + \
|
||||
removeHtml(briarAddress) + '</p>\n'
|
||||
else:
|
||||
optionsStr += \
|
||||
'<p class="imText">briar://' + \
|
||||
removeHtml(briarAddress) + '</p>\n'
|
||||
if jamiAddress:
|
||||
optionsStr += \
|
||||
'<p class="imText">Jami: ' + removeHtml(jamiAddress) + '</p>\n'
|
||||
|
|
|
@ -1076,6 +1076,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
httpPrefix: str, projectVersion: str,
|
||||
boxName: str, YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: [],
|
||||
showRepeats=True,
|
||||
showIcons=False,
|
||||
manuallyApprovesFollowers=False,
|
||||
|
@ -1483,7 +1484,8 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
|
||||
if not postIsSensitive:
|
||||
contentStr = objectContent + attachmentStr
|
||||
contentStr = addEmbeddedElements(translate, contentStr)
|
||||
contentStr = addEmbeddedElements(translate, contentStr,
|
||||
peertubeInstances)
|
||||
contentStr = insertQuestion(baseDir, translate,
|
||||
nickname, domain, port,
|
||||
contentStr, postJsonObject,
|
||||
|
@ -1499,7 +1501,8 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
# get the content warning text
|
||||
cwContentStr = objectContent + attachmentStr
|
||||
if not isPatch:
|
||||
cwContentStr = addEmbeddedElements(translate, cwContentStr)
|
||||
cwContentStr = addEmbeddedElements(translate, cwContentStr,
|
||||
peertubeInstances)
|
||||
cwContentStr = \
|
||||
insertQuestion(baseDir, translate, nickname, domain, port,
|
||||
cwContentStr, postJsonObject, pageNumber)
|
||||
|
@ -1571,7 +1574,8 @@ def htmlIndividualPost(cssCache: {},
|
|||
postJsonObject: {}, httpPrefix: str,
|
||||
projectVersion: str, likedBy: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show an individual post as html
|
||||
"""
|
||||
postStr = ''
|
||||
|
@ -1611,6 +1615,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, authorized, False, False, False)
|
||||
messageId = removeIdEnding(postJsonObject['id'])
|
||||
|
||||
|
@ -1636,6 +1641,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, authorized,
|
||||
False, False, False) + postStr
|
||||
|
||||
|
@ -1664,6 +1670,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, authorized,
|
||||
False, False, False)
|
||||
cssFilename = baseDir + '/epicyon-profile.css'
|
||||
|
@ -1680,7 +1687,8 @@ def htmlPostReplies(cssCache: {},
|
|||
nickname: str, domain: str, port: int, repliesJson: {},
|
||||
httpPrefix: str, projectVersion: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the replies to an individual post as html
|
||||
"""
|
||||
repliesStr = ''
|
||||
|
@ -1696,6 +1704,7 @@ def htmlPostReplies(cssCache: {},
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, False, False, False, False)
|
||||
|
||||
cssFilename = baseDir + '/epicyon-profile.css'
|
||||
|
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
|||
|
||||
import os
|
||||
from pprint import pprint
|
||||
from utils import hasUsersPath
|
||||
from utils import getFullDomain
|
||||
from utils import isDormant
|
||||
from utils import getNicknameFromActor
|
||||
|
@ -33,6 +34,7 @@ from pgp import getEmailAddress
|
|||
from pgp import getPGPfingerprint
|
||||
from pgp import getPGPpubKey
|
||||
from tox import getToxAddress
|
||||
from briar import getBriarAddress
|
||||
from jami import getJamiAddress
|
||||
from filters import isFiltered
|
||||
from webapp_frontscreen import htmlFrontScreen
|
||||
|
@ -58,14 +60,11 @@ def htmlProfileAfterSearch(cssCache: {},
|
|||
debug: bool, projectVersion: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
defaultTimeline: str) -> str:
|
||||
defaultTimeline: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show a profile page after a search for a fediverse address
|
||||
"""
|
||||
if '/users/' in profileHandle or \
|
||||
'/accounts/' in profileHandle or \
|
||||
'/channel/' in profileHandle or \
|
||||
'/profile/' in profileHandle or \
|
||||
'/@' in profileHandle:
|
||||
if hasUsersPath(profileHandle) or '/@' in profileHandle:
|
||||
searchNickname = getNicknameFromActor(profileHandle)
|
||||
searchDomain, searchPort = getDomainFromActor(profileHandle)
|
||||
else:
|
||||
|
@ -279,6 +278,7 @@ def htmlProfileAfterSearch(cssCache: {},
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, False, False, False, False)
|
||||
i += 1
|
||||
if i >= 20:
|
||||
|
@ -372,6 +372,7 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
newswire: {}, theme: str, dormantMonths: int,
|
||||
peertubeInstances: [],
|
||||
extraJson=None, pageNumber=None,
|
||||
maxItemsPerPage=None) -> str:
|
||||
"""Show the profile page as html
|
||||
|
@ -443,9 +444,11 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
matrixAddress = getMatrixAddress(profileJson)
|
||||
ssbAddress = getSSBAddress(profileJson)
|
||||
toxAddress = getToxAddress(profileJson)
|
||||
briarAddress = getBriarAddress(profileJson)
|
||||
jamiAddress = getJamiAddress(profileJson)
|
||||
if donateUrl or xmppAddress or matrixAddress or \
|
||||
ssbAddress or toxAddress or jamiAddress or PGPpubKey or \
|
||||
ssbAddress or toxAddress or briarAddress or \
|
||||
jamiAddress or PGPpubKey or \
|
||||
PGPfingerprint or emailAddress:
|
||||
donateSection = '<div class="container">\n'
|
||||
donateSection += ' <center>\n'
|
||||
|
@ -473,6 +476,15 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
donateSection += \
|
||||
'<p>Tox: <label class="toxaddr">' + \
|
||||
toxAddress + '</label></p>\n'
|
||||
if briarAddress:
|
||||
if briarAddress.startswith('briar://'):
|
||||
donateSection += \
|
||||
'<p><label class="toxaddr">' + \
|
||||
briarAddress + '</label></p>\n'
|
||||
else:
|
||||
donateSection += \
|
||||
'<p>briar://<label class="toxaddr">' + \
|
||||
briarAddress + '</label></p>\n'
|
||||
if jamiAddress:
|
||||
donateSection += \
|
||||
'<p>Jami: <label class="toxaddr">' + \
|
||||
|
@ -628,7 +640,8 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
session, wfRequest, personCache,
|
||||
projectVersion,
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly) + licenseStr
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances) + licenseStr
|
||||
elif selected == 'following':
|
||||
profileStr += \
|
||||
_htmlProfileFollowing(translate, baseDir, httpPrefix,
|
||||
|
@ -674,7 +687,8 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
session, wfRequest: {}, personCache: {},
|
||||
projectVersion: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Shows posts on the profile screen
|
||||
These should only be public posts
|
||||
"""
|
||||
|
@ -712,6 +726,7 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
httpPrefix, projectVersion, 'inbox',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
False, False, False, True, False)
|
||||
if postStr:
|
||||
profileStr += postStr + separatorStr
|
||||
|
@ -833,7 +848,8 @@ def _htmlProfileShares(actor: str, translate: {},
|
|||
|
||||
def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||
domain: str, port: int, httpPrefix: str,
|
||||
defaultTimeline: str, theme: str) -> str:
|
||||
defaultTimeline: str, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Shows the edit profile screen
|
||||
"""
|
||||
imageFormats = getImageFormats()
|
||||
|
@ -873,6 +889,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
ssbAddress = ''
|
||||
blogAddress = ''
|
||||
toxAddress = ''
|
||||
briarAddress = ''
|
||||
manuallyApprovesFollowers = ''
|
||||
actorJson = loadJson(actorFilename)
|
||||
if actorJson:
|
||||
|
@ -882,6 +899,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
ssbAddress = getSSBAddress(actorJson)
|
||||
blogAddress = getBlogAddress(actorJson)
|
||||
toxAddress = getToxAddress(actorJson)
|
||||
briarAddress = getBriarAddress(actorJson)
|
||||
jamiAddress = getJamiAddress(actorJson)
|
||||
emailAddress = getEmailAddress(actorJson)
|
||||
PGPpubKey = getPGPpubKey(actorJson)
|
||||
|
@ -1029,6 +1047,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
themesDropdown = ''
|
||||
instanceStr = ''
|
||||
editorsStr = ''
|
||||
peertubeStr = ''
|
||||
|
||||
adminNickname = getConfigParam(baseDir, 'admin')
|
||||
if adminNickname:
|
||||
|
@ -1145,6 +1164,21 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
'<option value="' + themeName +
|
||||
'" selected>')
|
||||
|
||||
peertubeStr = \
|
||||
' <br><b><label class="labels">' + \
|
||||
translate['Peertube Instances'] + '</label></b>\n'
|
||||
idx = 'Show video previews for the following Peertube sites.'
|
||||
peertubeStr += \
|
||||
' <br><label class="labels">' + \
|
||||
translate[idx] + '</label>\n'
|
||||
peertubeInstancesStr = ''
|
||||
for url in peertubeInstances:
|
||||
peertubeInstancesStr += url + '\n'
|
||||
peertubeStr += \
|
||||
' <textarea id="message" name="ptInstances" ' + \
|
||||
'style="height:200px">' + peertubeInstancesStr + \
|
||||
'</textarea>\n'
|
||||
|
||||
editProfileForm = htmlHeaderWithExternalStyle(cssFilename)
|
||||
|
||||
# top banner
|
||||
|
@ -1220,6 +1254,11 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
' <input type="text" name="toxAddress" value="' + \
|
||||
toxAddress + '">\n'
|
||||
|
||||
editProfileForm += '<label class="labels">Briar</label><br>\n'
|
||||
editProfileForm += \
|
||||
' <input type="text" name="briarAddress" value="' + \
|
||||
briarAddress + '">\n'
|
||||
|
||||
editProfileForm += '<label class="labels">Jami</label><br>\n'
|
||||
editProfileForm += \
|
||||
' <input type="text" name="jamiAddress" value="' + \
|
||||
|
@ -1436,7 +1475,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
|||
editProfileForm += ' <label class="labels">' + \
|
||||
translate[idx] + '</label>\n'
|
||||
editProfileForm += skillsStr + themesDropdown
|
||||
editProfileForm += moderatorsStr + editorsStr
|
||||
editProfileForm += moderatorsStr + editorsStr + peertubeStr
|
||||
editProfileForm += ' </div>\n' + instanceStr
|
||||
editProfileForm += ' <div class="container">\n'
|
||||
editProfileForm += ' <b><label class="labels">' + \
|
||||
|
|
|
@ -506,7 +506,8 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
personCache: {},
|
||||
port: int,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show a page containing search results for your post history
|
||||
"""
|
||||
if historysearch.startswith('!'):
|
||||
|
@ -579,6 +580,7 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
'search',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
showIndividualPostIcons,
|
||||
showIndividualPostIcons,
|
||||
False, False, False)
|
||||
|
@ -599,7 +601,8 @@ def htmlHashtagSearch(cssCache: {},
|
|||
session, wfRequest: {}, personCache: {},
|
||||
httpPrefix: str, projectVersion: str,
|
||||
YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool) -> str:
|
||||
showPublishedDateOnly: bool,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show a page containing search results for a hashtag
|
||||
"""
|
||||
if hashtag.startswith('#'):
|
||||
|
@ -745,6 +748,7 @@ def htmlHashtagSearch(cssCache: {},
|
|||
'search',
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
showRepeats, showIcons,
|
||||
manuallyApprovesFollowers,
|
||||
showPublicOnly,
|
||||
|
|
|
@ -61,7 +61,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
publishButtonAtTop: bool,
|
||||
authorized: bool,
|
||||
moderationActionStr: str,
|
||||
theme: str) -> str:
|
||||
theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the timeline as html
|
||||
"""
|
||||
enableTimingLog = False
|
||||
|
@ -566,6 +567,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
boxName,
|
||||
YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
peertubeInstances,
|
||||
boxName != 'dm',
|
||||
showIndividualPostIcons,
|
||||
manuallyApproveFollowers,
|
||||
|
@ -720,7 +722,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the shares timeline as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
|
@ -739,7 +742,7 @@ def htmlShares(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInbox(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -757,7 +760,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the inbox as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
|
@ -776,7 +780,7 @@ def htmlInbox(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -794,7 +798,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the bookmarks as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
|
@ -813,7 +818,7 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlEvents(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -831,7 +836,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the events as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
|
@ -850,7 +856,7 @@ def htmlEvents(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -868,7 +874,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the DM timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -882,7 +889,7 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
|||
showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -900,7 +907,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the replies timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -915,7 +923,7 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -933,7 +941,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the media timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -948,7 +957,7 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -966,7 +975,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the blogs timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -981,7 +991,7 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -1000,7 +1010,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
|||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool,
|
||||
theme: str) -> str:
|
||||
theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the features timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -1015,7 +1026,7 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -1033,7 +1044,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the news timeline as html
|
||||
"""
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
|
@ -1048,7 +1060,7 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
|||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
||||
|
||||
def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
||||
|
@ -1066,7 +1078,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
|||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str) -> str:
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: []) -> str:
|
||||
"""Show the Outbox as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
|
@ -1082,4 +1095,4 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
|||
newswire, False, False, positiveVoting,
|
||||
showPublishAsIcon, fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme)
|
||||
authorized, None, theme, peertubeInstances)
|
||||
|
|
Loading…
Reference in New Issue