diff --git a/blog.py b/blog.py
index 0666e8677..a136d36d0 100644
--- a/blog.py
+++ b/blog.py
@@ -420,7 +420,7 @@ def htmlBlogPost(session, authorized: bool,
postJsonObject: {},
peertubeInstances: [],
systemLanguage: str, personCache: {},
- debug: bool) -> str:
+ debug: bool, contentLicenseUrl: str) -> str:
"""Returns a html blog post
"""
blogStr = ''
@@ -431,12 +431,19 @@ def htmlBlogPost(session, authorized: bool,
instanceTitle = \
getConfigParam(baseDir, 'instanceTitle')
published = postJsonObject['object']['published']
+ modified = published
+ if postJsonObject['object'].get('updated'):
+ modified = postJsonObject['object']['updated']
title = postJsonObject['object']['summary']
+ url = ''
+ if postJsonObject['object'].get('url'):
+ url = postJsonObject['object']['url']
snippet = _getSnippetFromBlogContent(postJsonObject, systemLanguage)
blogStr = htmlHeaderWithBlogMarkup(cssFilename, instanceTitle,
httpPrefix, domainFull, nickname,
- systemLanguage, published,
- title, snippet)
+ systemLanguage, published, modified,
+ title, snippet, translate, url,
+ contentLicenseUrl)
_htmlBlogRemoveCwButton(blogStr, translate)
blogStr += _htmlBlogPostContent(debug, session, authorized, baseDir,
diff --git a/daemon.py b/daemon.py
index 4a5f14d94..05795bdcf 100644
--- a/daemon.py
+++ b/daemon.py
@@ -508,7 +508,8 @@ class PubServer(BaseHTTPRequestHandler):
location, False,
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
# name field contains the answer
messageJson['object']['name'] = answer
@@ -1281,7 +1282,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.maxLikeCount,
self.server.maxRecentPosts,
self.server.CWlists,
- self.server.listsEnabled)
+ self.server.listsEnabled,
+ self.server.contentLicenseUrl)
def _getOutboxThreadIndex(self, nickname: str,
maxOutboxThreadsPerAccount: int) -> int:
@@ -4357,7 +4359,7 @@ class PubServer(BaseHTTPRequestHandler):
domain: str, domainFull: str,
onionDomain: str, i2pDomain: str,
debug: bool, allowLocalNetworkAccess: bool,
- systemLanguage: str) -> None:
+ systemLanguage: str, contentLicenseUrl: str) -> None:
"""Updates your user profile after editing via the Edit button
on the profile screen
"""
@@ -4504,7 +4506,8 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.lowBandwidth:
convertImageToLowBandwidth(filename)
processMetaData(baseDir, nickname, domain,
- filename, postImageFilename, city)
+ filename, postImageFilename, city,
+ contentLicenseUrl)
if os.path.isfile(postImageFilename):
print('profile update POST ' + mType +
' image, zip or font saved to ' +
@@ -4900,6 +4903,24 @@ class PubServer(BaseHTTPRequestHandler):
setConfigParam(baseDir,
'libretranslateApiKey', '')
+ # change instance short description
+ if fields.get('contentLicenseUrl'):
+ if fields['contentLicenseUrl'] != \
+ self.server.contentLicenseUrl:
+ licenseStr = fields['contentLicenseUrl']
+ setConfigParam(baseDir,
+ 'contentLicenseUrl',
+ licenseStr)
+ self.server.contentLicenseUrl = \
+ licenseStr
+ else:
+ licenseStr = \
+ 'https://creativecommons.org/licenses/by/4.0'
+ setConfigParam(baseDir,
+ 'contentLicenseUrl',
+ licenseStr)
+ self.server.contentLicenseUrl = licenseStr
+
# change instance short description
currInstanceDescriptionShort = \
getConfigParam(baseDir,
@@ -6049,9 +6070,14 @@ class PubServer(BaseHTTPRequestHandler):
"sizes": "144x144"
},
{
- "src": "/logo152.png",
+ "src": "/logo150.png",
"type": "image/png",
- "sizes": "152x152"
+ "sizes": "150x150"
+ },
+ {
+ "src": "/apple-touch-icon.png",
+ "type": "image/png",
+ "sizes": "180x180"
},
{
"src": "/logo192.png",
@@ -6092,6 +6118,33 @@ class PubServer(BaseHTTPRequestHandler):
'_GET', '_progressiveWebAppManifest',
self.server.debug)
+ def _browserConfig(self, callingDomain: str, GETstartTime) -> None:
+ """Used by MS Windows to put an icon on the desktop if you
+ link to a website
+ """
+ xmlStr = \
+ '\n' + \
+ '\n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' #eeeeee \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' '
+
+ msg = json.dumps(xmlStr,
+ ensure_ascii=False).encode('utf-8')
+ msglen = len(msg)
+ self._set_headers('application/xrd+xml', msglen,
+ None, callingDomain, False)
+ self._write(msg)
+ if self.server.debug:
+ print('Sent browserconfig: ' + callingDomain)
+ fitnessPerformance(GETstartTime, self.server.fitness,
+ '_GET', '_browserConfig',
+ self.server.debug)
+
def _getFavicon(self, callingDomain: str,
baseDir: str, debug: bool,
favFilename: str) -> None:
@@ -8726,7 +8779,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.sharedItemsFederatedDomains,
rolesList,
None, None, self.server.CWlists,
- self.server.listsEnabled)
+ self.server.listsEnabled,
+ self.server.contentLicenseUrl)
msg = msg.encode('utf-8')
msglen = len(msg)
self._set_headers('text/html', msglen,
@@ -8841,7 +8895,8 @@ class PubServer(BaseHTTPRequestHandler):
skills,
None, None,
self.server.CWlists,
- self.server.listsEnabled)
+ self.server.listsEnabled,
+ self.server.contentLicenseUrl)
msg = msg.encode('utf-8')
msglen = len(msg)
self._set_headers('text/html', msglen,
@@ -10834,7 +10889,8 @@ class PubServer(BaseHTTPRequestHandler):
shares,
pageNumber, sharesPerPage,
self.server.CWlists,
- self.server.listsEnabled)
+ self.server.listsEnabled,
+ self.server.contentLicenseUrl)
msg = msg.encode('utf-8')
msglen = len(msg)
self._set_headers('text/html', msglen,
@@ -10926,6 +10982,8 @@ class PubServer(BaseHTTPRequestHandler):
city = getSpoofedCity(self.server.city,
baseDir, nickname, domain)
+ contentLicenseUrl = \
+ self.server.contentLicenseUrl
msg = \
htmlProfile(self.server.signingPrivateKeyPem,
self.server.rssIconAtTop,
@@ -10960,7 +11018,8 @@ class PubServer(BaseHTTPRequestHandler):
pageNumber,
followsPerPage,
self.server.CWlists,
- self.server.listsEnabled).encode('utf-8')
+ self.server.listsEnabled,
+ contentLicenseUrl).encode('utf-8')
msglen = len(msg)
self._set_headers('text/html',
msglen, cookie, callingDomain, False)
@@ -11050,6 +11109,8 @@ class PubServer(BaseHTTPRequestHandler):
city = getSpoofedCity(self.server.city,
baseDir, nickname, domain)
+ contentLicenseUrl = \
+ self.server.contentLicenseUrl
msg = \
htmlProfile(self.server.signingPrivateKeyPem,
self.server.rssIconAtTop,
@@ -11085,7 +11146,8 @@ class PubServer(BaseHTTPRequestHandler):
pageNumber,
followsPerPage,
self.server.CWlists,
- self.server.listsEnabled).encode('utf-8')
+ self.server.listsEnabled,
+ contentLicenseUrl).encode('utf-8')
msglen = len(msg)
self._set_headers('text/html', msglen,
cookie, callingDomain, False)
@@ -11226,7 +11288,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.sharedItemsFederatedDomains,
None, None, None,
self.server.CWlists,
- self.server.listsEnabled).encode('utf-8')
+ self.server.listsEnabled,
+ self.server.contentLicenseUrl).encode('utf-8')
msglen = len(msg)
self._set_headers('text/html', msglen,
cookie, callingDomain, False)
@@ -12239,6 +12302,17 @@ class PubServer(BaseHTTPRequestHandler):
uaStr = self.headers['User-agent']
return uaStr
+ def _permittedCrawlerPath(self, path: str) -> bool:
+ """Is the given path permitted to be crawled by a search engine?
+ this should only allow through basic information, such as nodeinfo
+ """
+ if path == '/' or path == '/about' or path == '/login' or \
+ path.startswith('/api/') or \
+ path.startswith('/nodeinfo/') or \
+ path.startswith('/blog/'):
+ return True
+ return False
+
def do_GET(self):
callingDomain = self.server.domainFull
@@ -12267,9 +12341,10 @@ class PubServer(BaseHTTPRequestHandler):
uaStr = self._getUserAgent()
- if self._blockedUserAgent(callingDomain, uaStr):
- self._400()
- return
+ if not self._permittedCrawlerPath(self.path):
+ if self._blockedUserAgent(callingDomain, uaStr):
+ self._400()
+ return
refererDomain = self._getRefererDomain(uaStr)
@@ -12401,6 +12476,11 @@ class PubServer(BaseHTTPRequestHandler):
else:
self.path = '/'
+ if '/browserconfig.xml' in self.path:
+ if self._hasAccept(callingDomain):
+ self._browserConfig(callingDomain, GETstartTime)
+ return
+
# default newswire favicon, for links to sites which
# have no favicon
if 'newswire_favicon.ico' in self.path:
@@ -13089,7 +13169,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.peertubeInstances,
self.server.systemLanguage,
self.server.personCache,
- self.server.debug)
+ self.server.debug,
+ self.server.contentLicenseUrl)
if msg is not None:
msg = msg.encode('utf-8')
msglen = len(msg)
@@ -13482,10 +13563,11 @@ class PubServer(BaseHTTPRequestHandler):
self.path == '/logo96.png' or \
self.path == '/logo128.png' or \
self.path == '/logo144.png' or \
- self.path == '/logo152.png' or \
+ self.path == '/logo150.png' or \
self.path == '/logo192.png' or \
self.path == '/logo256.png' or \
- self.path == '/logo512.png':
+ self.path == '/logo512.png' or \
+ self.path == '/apple-touch-icon.png':
mediaFilename = \
self.server.baseDir + '/img' + self.path
if os.path.isfile(mediaFilename):
@@ -13660,6 +13742,7 @@ class PubServer(BaseHTTPRequestHandler):
GETstartTime)
return
+ # show a background image on the login or person options page
if '-background.' in self.path:
if self._showBackgroundImage(callingDomain, self.path,
self.server.baseDir,
@@ -13849,6 +13932,7 @@ class PubServer(BaseHTTPRequestHandler):
'_GET', 'login shown done',
self.server.debug)
+ # the newswire screen on mobile
if htmlGET and self.path.startswith('/users/') and \
self.path.endswith('/newswiremobile'):
if (authorized or
@@ -14618,6 +14702,7 @@ class PubServer(BaseHTTPRequestHandler):
'_GET', 'post replies done',
self.server.debug)
+ # roles on profile screen
if self.path.endswith('/roles') and usersInPath:
if self._showRoles(authorized,
callingDomain, self.path,
@@ -15195,7 +15280,8 @@ class PubServer(BaseHTTPRequestHandler):
def _receiveNewPostProcess(self, postType: str, path: str, headers: {},
length: int, postBytes, boundary: str,
callingDomain: str, cookie: str,
- authorized: bool) -> int:
+ authorized: bool,
+ contentLicenseUrl: str) -> int:
# Note: this needs to happen synchronously
# 0=this is not a new post
# 1=new post success
@@ -15272,7 +15358,8 @@ class PubServer(BaseHTTPRequestHandler):
convertImageToLowBandwidth(filename)
processMetaData(self.server.baseDir,
nickname, self.server.domain,
- filename, postImageFilename, city)
+ filename, postImageFilename, city,
+ contentLicenseUrl)
if os.path.isfile(postImageFilename):
print('POST media saved to ' + postImageFilename)
else:
@@ -15399,7 +15486,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'], False,
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15481,7 +15569,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'],
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15573,7 +15662,8 @@ class PubServer(BaseHTTPRequestHandler):
attachmentMediaType,
imgDescription,
city,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
replaceYouTube(postJsonObject,
self.server.YTReplacementDomain,
@@ -15631,7 +15721,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'],
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15682,7 +15773,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'],
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15737,7 +15829,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'],
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15790,7 +15883,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['location'],
self.server.systemLanguage,
conversationId,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if fields['schedulePost']:
return 1
@@ -15826,7 +15920,8 @@ class PubServer(BaseHTTPRequestHandler):
city,
self.server.debug, fields['subject'],
self.server.systemLanguage,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if self._postToOutbox(messageJson,
self.server.projectVersion,
@@ -15867,7 +15962,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['subject'],
intDuration,
self.server.systemLanguage,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if messageJson:
if self.server.debug:
print('DEBUG: new Question')
@@ -15939,7 +16035,8 @@ class PubServer(BaseHTTPRequestHandler):
city, itemPrice, itemCurrency,
self.server.systemLanguage,
self.server.translate, sharesFileType,
- self.server.lowBandwidth)
+ self.server.lowBandwidth,
+ self.server.contentLicenseUrl)
if filename:
if os.path.isfile(filename):
try:
@@ -15954,7 +16051,8 @@ class PubServer(BaseHTTPRequestHandler):
def _receiveNewPost(self, postType: str, path: str,
callingDomain: str, cookie: str,
- authorized: bool) -> int:
+ authorized: bool,
+ contentLicenseUrl: str) -> int:
"""A new post has been created
This creates a thread to send the new post
"""
@@ -16056,7 +16154,8 @@ class PubServer(BaseHTTPRequestHandler):
path, headers, length,
postBytes, boundary,
callingDomain, cookie,
- authorized)
+ authorized,
+ contentLicenseUrl)
return pageNumber
def _cryptoAPIreadHandle(self):
@@ -16353,7 +16452,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.onionDomain,
self.server.i2pDomain, self.server.debug,
self.server.allowLocalNetworkAccess,
- self.server.systemLanguage)
+ self.server.systemLanguage,
+ self.server.contentLicenseUrl)
return
if authorized and self.path.endswith('/linksdata'):
@@ -16713,7 +16813,8 @@ class PubServer(BaseHTTPRequestHandler):
pageNumber = \
self._receiveNewPost(currPostType, self.path,
callingDomain, cookie,
- authorized)
+ authorized,
+ self.server.contentLicenseUrl)
if pageNumber:
print(currPostType + ' post received')
nickname = self.path.split('/users/')[1]
@@ -17126,7 +17227,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None:
break
-def runDaemon(listsEnabled: str,
+def runDaemon(contentLicenseUrl: str,
+ listsEnabled: str,
defaultReplyIntervalHours: int,
lowBandwidth: bool,
maxLikeCount: int,
@@ -17214,6 +17316,11 @@ def runDaemon(listsEnabled: str,
# scan the theme directory for any svg files containing scripts
assert not scanThemesForScripts(baseDir)
+ # license for content of the instance
+ if not contentLicenseUrl:
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
+ httpd.contentLicenseUrl = contentLicenseUrl
+
# fitness metrics
fitnessFilename = baseDir + '/accounts/fitness.json'
httpd.fitness = {}
diff --git a/desktop_client.py b/desktop_client.py
index 93603f5ca..054f8b835 100644
--- a/desktop_client.py
+++ b/desktop_client.py
@@ -419,6 +419,7 @@ def _desktopReplyToPost(session, postId: str,
screenreader: str, systemLanguage: str,
espeak, conversationId: str,
lowBandwidth: bool,
+ contentLicenseUrl: str,
signingPrivateKeyPem: str) -> None:
"""Use the desktop client to send a reply to the most recent post
"""
@@ -473,6 +474,7 @@ def _desktopReplyToPost(session, postId: str,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
systemLanguage, lowBandwidth,
+ contentLicenseUrl,
debug, postId, postId,
conversationId, subject) == 0:
sayStr = 'Reply sent'
@@ -488,6 +490,7 @@ def _desktopNewPost(session,
debug: bool,
screenreader: str, systemLanguage: str,
espeak, lowBandwidth: bool,
+ contentLicenseUrl: str,
signingPrivateKeyPem: str) -> None:
"""Use the desktop client to create a new post
"""
@@ -538,6 +541,7 @@ def _desktopNewPost(session,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
systemLanguage, lowBandwidth,
+ contentLicenseUrl,
debug, None, None,
conversationId, subject) == 0:
sayStr = 'Post sent'
@@ -1124,6 +1128,7 @@ def _desktopNewDM(session, toHandle: str,
debug: bool,
screenreader: str, systemLanguage: str,
espeak, lowBandwidth: bool,
+ contentLicenseUrl: str,
signingPrivateKeyPem: str) -> None:
"""Use the desktop client to create a new direct message
which can include multiple destination handles
@@ -1146,6 +1151,7 @@ def _desktopNewDM(session, toHandle: str,
debug,
screenreader, systemLanguage,
espeak, lowBandwidth,
+ contentLicenseUrl,
signingPrivateKeyPem)
@@ -1156,6 +1162,7 @@ def _desktopNewDMbase(session, toHandle: str,
debug: bool,
screenreader: str, systemLanguage: str,
espeak, lowBandwidth: bool,
+ contentLicenseUrl: str,
signingPrivateKeyPem: str) -> None:
"""Use the desktop client to create a new direct message
"""
@@ -1246,6 +1253,7 @@ def _desktopNewDMbase(session, toHandle: str,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
systemLanguage, lowBandwidth,
+ contentLicenseUrl,
debug, None, None,
conversationId, subject) == 0:
sayStr = 'Direct message sent'
@@ -1319,6 +1327,8 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str,
# TODO: this should probably be retrieved somehow from the server
signingPrivateKeyPem = None
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
+
blockedCache = {}
indent = ' '
@@ -1716,6 +1726,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str,
screenreader, systemLanguage,
espeak, conversationId,
lowBandwidth,
+ contentLicenseUrl,
signingPrivateKeyPem)
refreshTimeline = True
print('')
@@ -1751,6 +1762,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str,
debug,
screenreader, systemLanguage,
espeak, lowBandwidth,
+ contentLicenseUrl,
signingPrivateKeyPem)
refreshTimeline = True
else:
@@ -1762,6 +1774,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str,
debug,
screenreader, systemLanguage,
espeak, lowBandwidth,
+ contentLicenseUrl,
signingPrivateKeyPem)
refreshTimeline = True
print('')
diff --git a/epicyon.py b/epicyon.py
index a0c9e1f64..9cf52179e 100644
--- a/epicyon.py
+++ b/epicyon.py
@@ -112,6 +112,9 @@ def str2bool(v) -> bool:
parser = argparse.ArgumentParser(description='ActivityPub Server')
+parser.add_argument('--contentLicenseUrl', type=str,
+ default='https://creativecommons.org/licenses/by/4.0',
+ help='Url of the license used for the instance content')
parser.add_argument('--listsEnabled', type=str,
default=None,
help='Names of content warning lists enabled. ' +
@@ -1281,7 +1284,8 @@ if args.message:
args.commentsEnabled, attach, mediaType,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
- args.language, args.lowBandwidth, args.debug,
+ args.language, args.lowBandwidth,
+ args.contentLicenseUrl, args.debug,
replyTo, replyTo, args.conversationId, subject)
for i in range(10):
# TODO detect send success/fail
@@ -2330,7 +2334,8 @@ if args.avatar:
sys.exit()
city = 'London, England'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
- port, args.avatar, 'avatar', '128x128', city):
+ port, args.avatar, 'avatar', '128x128', city,
+ args.contentLicenseUrl):
print('Avatar added for ' + args.nickname)
else:
print('Avatar was not added for ' + args.nickname)
@@ -2346,7 +2351,7 @@ if args.backgroundImage:
city = 'London, England'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
port, args.backgroundImage, 'background',
- '256x256', city):
+ '256x256', city, args.contentLicenseUrl):
print('Background image added for ' + args.nickname)
else:
print('Background image was not added for ' + args.nickname)
@@ -2716,7 +2721,8 @@ if args.testdata:
"mechanical",
"City", "0", "GBP",
"2 months",
- debug, city, args.language, {}, 'shares', args.lowBandwidth)
+ debug, city, args.language, {}, 'shares', args.lowBandwidth,
+ args.contentLicenseUrl)
addShare(baseDir,
httpPrefix, nickname, domain, port,
"witch hat",
@@ -2726,7 +2732,8 @@ if args.testdata:
"clothing",
"City", "0", "GBP",
"3 months",
- debug, city, args.language, {}, 'shares', args.lowBandwidth)
+ debug, city, args.language, {}, 'shares', args.lowBandwidth,
+ args.contentLicenseUrl)
deleteAllPosts(baseDir, nickname, domain, 'inbox')
deleteAllPosts(baseDir, nickname, domain, 'outbox')
@@ -2762,7 +2769,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Zoiks!!!",
testFollowersOnly,
@@ -2775,7 +2782,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Hey scoob we need like a hundred more #milkshakes",
testFollowersOnly,
@@ -2788,7 +2795,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Getting kinda spooky around here",
testFollowersOnly,
@@ -2801,7 +2808,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"And they would have gotten away with it too" +
"if it wasn't for those pesky hackers",
@@ -2815,7 +2822,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"man these centralized sites are like the worst!",
testFollowersOnly,
@@ -2828,7 +2835,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"another mystery solved #test",
testFollowersOnly,
@@ -2841,7 +2848,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"let's go bowling",
testFollowersOnly,
@@ -2854,7 +2861,7 @@ if args.testdata:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, args.language, conversationId,
- lowBandwidth)
+ lowBandwidth, args.contentLicenseUrl)
domainFull = domain + ':' + str(port)
clearFollows(baseDir, nickname, domain)
followPerson(baseDir, nickname, domain, 'maxboardroom', domainFull,
@@ -2884,6 +2891,13 @@ minimumvotes = getConfigParam(baseDir, 'minvotes')
if minimumvotes:
args.minimumvotes = int(minimumvotes)
+contentLicenseUrl = ''
+if args.contentLicenseUrl:
+ contentLicenseUrl = args.contentLicenseUrl
+ setConfigParam(baseDir, 'contentLicenseUrl', contentLicenseUrl)
+else:
+ contentLicenseUrl = getConfigParam(baseDir, 'contentLicenseUrl')
+
votingtime = getConfigParam(baseDir, 'votingtime')
if votingtime:
args.votingtime = votingtime
@@ -3078,7 +3092,8 @@ if args.defaultCurrency:
print('Default currency set to ' + args.defaultCurrency)
if __name__ == "__main__":
- runDaemon(listsEnabled,
+ runDaemon(contentLicenseUrl,
+ listsEnabled,
args.defaultReplyIntervalHours,
args.lowBandwidth, args.maxLikeCount,
sharedItemsFederatedDomains,
diff --git a/follow.py b/follow.py
index 4343d60b7..b8953131f 100644
--- a/follow.py
+++ b/follow.py
@@ -209,6 +209,29 @@ def followerOfPerson(baseDir: str, nickname: str, domain: str,
federationList, debug, groupAccount, 'followers.txt')
+def getFollowerDomains(baseDir: str, nickname: str, domain: str) -> []:
+ """Returns a list of domains for followers
+ """
+ domain = removeDomainPort(domain)
+ followersFile = acctDir(baseDir, nickname, domain) + '/followers.txt'
+ if not os.path.isfile(followersFile):
+ return []
+
+ lines = []
+ with open(followersFile, 'r') as fpFollowers:
+ lines = fpFollowers.readlines()
+
+ domainsList = []
+ for handle in lines:
+ handle = handle.replace('\n', '')
+ followerDomain, _ = getDomainFromActor(handle)
+ if not followerDomain:
+ continue
+ if followerDomain not in domainsList:
+ domainsList.append(followerDomain)
+ return domainsList
+
+
def isFollowerOfPerson(baseDir: str, nickname: str, domain: str,
followerNickname: str, followerDomain: str) -> bool:
"""is the given nickname a follower of followerNickname?
diff --git a/img/apple-touch-icon.png b/img/apple-touch-icon.png
new file mode 100644
index 000000000..996deaf00
Binary files /dev/null and b/img/apple-touch-icon.png differ
diff --git a/img/logo150.png b/img/logo150.png
new file mode 100644
index 000000000..5b933f90f
Binary files /dev/null and b/img/logo150.png differ
diff --git a/img/logo152.png b/img/logo152.png
deleted file mode 100644
index 011235ee4..000000000
Binary files a/img/logo152.png and /dev/null differ
diff --git a/inbox.py b/inbox.py
index 0d336a0c0..fab4fca6e 100644
--- a/inbox.py
+++ b/inbox.py
@@ -2374,7 +2374,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
cachedWebfingers: {}, personCache: {},
translate: {}, debug: bool,
lastBounceMessage: [], systemLanguage: str,
- signingPrivateKeyPem: str) -> bool:
+ signingPrivateKeyPem: str,
+ contentLicenseUrl: str) -> bool:
"""Sends a bounce message back to the sending handle
if a DM has been rejected
"""
@@ -2433,7 +2434,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
inReplyTo, inReplyToAtomUri,
subject, debug, schedulePost,
eventDate, eventTime, location,
- systemLanguage, conversationId, lowBandwidth)
+ systemLanguage, conversationId, lowBandwidth,
+ contentLicenseUrl)
if not postJsonObject:
print('WARN: unable to create bounce message to ' + sendingHandle)
return False
@@ -2459,7 +2461,8 @@ def _isValidDM(baseDir: str, nickname: str, domain: str, port: int,
translate: {}, debug: bool,
lastBounceMessage: [],
handle: str, systemLanguage: str,
- signingPrivateKeyPem: str) -> bool:
+ signingPrivateKeyPem: str,
+ contentLicenseUrl: str) -> bool:
"""Is the given message a valid DM?
"""
if nickname == 'inbox':
@@ -2537,7 +2540,8 @@ def _isValidDM(baseDir: str, nickname: str, domain: str, port: int,
translate, debug,
lastBounceMessage,
systemLanguage,
- signingPrivateKeyPem)
+ signingPrivateKeyPem,
+ contentLicenseUrl)
return False
# dm index will be updated
@@ -2772,7 +2776,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
maxLikeCount: int,
signingPrivateKeyPem: str,
defaultReplyIntervalHours: int,
- CWlists: {}, listsEnabled: str) -> bool:
+ CWlists: {}, listsEnabled: str,
+ contentLicenseUrl: str) -> bool:
""" Anything which needs to be done after initial checks have passed
"""
actor = keyId
@@ -3004,7 +3009,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
translate, debug,
lastBounceMessage,
handle, systemLanguage,
- signingPrivateKeyPem):
+ signingPrivateKeyPem,
+ contentLicenseUrl):
return False
# get the actor being replied to
@@ -3786,6 +3792,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
saveJson(queueJson['post'], sharedInboxPostFilename)
listsEnabled = getConfigParam(baseDir, "listsEnabled")
+ contentLicenseUrl = getConfigParam(baseDir, "contentLicenseUrl")
# for posts addressed to specific accounts
for handle, capsId in recipientsDict.items():
@@ -3818,7 +3825,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
maxLikeCount,
signingPrivateKeyPem,
defaultReplyIntervalHours,
- CWlists, listsEnabled)
+ CWlists, listsEnabled,
+ contentLicenseUrl)
if debug:
pprint(queueJson['post'])
print('Queue: Queue post accepted')
diff --git a/media.py b/media.py
index c05faca93..184c8d2af 100644
--- a/media.py
+++ b/media.py
@@ -107,7 +107,8 @@ def _removeMetaData(imageFilename: str, outputFilename: str) -> None:
def _spoofMetaData(baseDir: str, nickname: str, domain: str,
- outputFilename: str, spoofCity: str) -> None:
+ outputFilename: str, spoofCity: str,
+ contentLicenseUrl: str) -> None:
"""Spoof image metadata using a decoy model for a given city
"""
if not os.path.isfile(outputFilename):
@@ -151,6 +152,7 @@ def _spoofMetaData(baseDir: str, nickname: str, domain: str,
'-GPSLongitude=' + str(longitude) + ' ' +
'-GPSLatitudeRef=' + latitudeRef + ' ' +
'-GPSLatitude=' + str(latitude) + ' ' +
+ '-copyright="' + contentLicenseUrl + '" ' +
'-Comment="" ' +
outputFilename) != 0: # nosec
print('ERROR: exiftool failed to run')
@@ -203,7 +205,7 @@ def convertImageToLowBandwidth(imageFilename: str) -> None:
def processMetaData(baseDir: str, nickname: str, domain: str,
imageFilename: str, outputFilename: str,
- city: str) -> None:
+ city: str, contentLicenseUrl: str) -> None:
"""Handles image metadata. This tries to spoof the metadata
if possible, but otherwise just removes it
"""
@@ -211,7 +213,8 @@ def processMetaData(baseDir: str, nickname: str, domain: str,
_removeMetaData(imageFilename, outputFilename)
# now add some spoofed data to misdirect surveillance capitalists
- _spoofMetaData(baseDir, nickname, domain, outputFilename, city)
+ _spoofMetaData(baseDir, nickname, domain, outputFilename, city,
+ contentLicenseUrl)
def _isMedia(imageFilename: str) -> bool:
@@ -299,7 +302,8 @@ def attachMedia(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int,
postJson: {}, imageFilename: str,
mediaType: str, description: str,
- city: str, lowBandwidth: bool) -> {}:
+ city: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Attaches media to a json object post
The description can be None
"""
@@ -357,7 +361,8 @@ def attachMedia(baseDir: str, httpPrefix: str,
if lowBandwidth:
convertImageToLowBandwidth(imageFilename)
processMetaData(baseDir, nickname, domain,
- imageFilename, mediaFilename, city)
+ imageFilename, mediaFilename, city,
+ contentLicenseUrl)
else:
copyfile(imageFilename, mediaFilename)
_updateEtag(mediaFilename)
diff --git a/newsdaemon.py b/newsdaemon.py
index a83616cb8..80c69bbb8 100644
--- a/newsdaemon.py
+++ b/newsdaemon.py
@@ -530,7 +530,8 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
maxMirroredArticles: int,
allowLocalNetworkAccess: bool,
systemLanguage: str,
- lowBandwidth: bool) -> None:
+ lowBandwidth: bool,
+ contentLicenseUrl: str) -> None:
"""Converts rss items in a newswire into posts
"""
if not newswire:
@@ -622,7 +623,8 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
attachImageFilename, mediaType,
imageDescription, city,
rssTitle, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
if not blog:
continue
@@ -818,7 +820,8 @@ def runNewswireDaemon(baseDir: str, httpd,
httpd.maxMirroredArticles,
httpd.allowLocalNetworkAccess,
httpd.systemLanguage,
- httpd.lowBandwidth)
+ httpd.lowBandwidth,
+ httpd.contentLicenseUrl)
print('Newswire feed converted to ActivityPub')
if httpd.maxNewsPosts > 0:
diff --git a/outbox.py b/outbox.py
index 78c9f1cc9..6b0bc0583 100644
--- a/outbox.py
+++ b/outbox.py
@@ -197,7 +197,8 @@ def postMessageToOutbox(session, translate: {},
peertubeInstances: str, theme: str,
maxLikeCount: int,
maxRecentPosts: int, CWlists: {},
- listsEnabled: str) -> bool:
+ listsEnabled: str,
+ contentLicenseUrl: str) -> bool:
"""post is received by the outbox
Client to server message post
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
@@ -607,7 +608,8 @@ def postMessageToOutbox(session, translate: {},
print('DEBUG: handle share uploads')
outboxShareUpload(baseDir, httpPrefix, postToNickname, domain,
port, messageJson, debug, city,
- systemLanguage, translate, lowBandwidth)
+ systemLanguage, translate, lowBandwidth,
+ contentLicenseUrl)
if debug:
print('DEBUG: handle undo share uploads')
diff --git a/person.py b/person.py
index 79daa3158..3594dd849 100644
--- a/person.py
+++ b/person.py
@@ -88,7 +88,8 @@ def generateRSAKey() -> (str, str):
def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
port: int, imageFilename: str, imageType: str,
- resolution: str, city: str) -> bool:
+ resolution: str, city: str,
+ contentLicenseUrl: str) -> bool:
"""Saves the given image file as an avatar or background
image for the given person
"""
@@ -151,7 +152,8 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
resolution + ' -quality 50 ' + profileFilename
subprocess.call(cmd, shell=True)
processMetaData(baseDir, nickname, domain,
- profileFilename, profileFilename, city)
+ profileFilename, profileFilename, city,
+ contentLicenseUrl)
return True
return False
diff --git a/posts.py b/posts.py
index 01eca5505..38be89bd0 100644
--- a/posts.py
+++ b/posts.py
@@ -1064,7 +1064,8 @@ def _createPostS2S(baseDir: str, nickname: str, domain: str, port: int,
mediaType: str, imageDescription: str, city: str,
postObjectType: str, summary: str,
inReplyToAtomUri: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Creates a new server-to-server post
"""
actorUrl = localActorUrl(httpPrefix, nickname, domain)
@@ -1124,7 +1125,8 @@ def _createPostS2S(baseDir: str, nickname: str, domain: str, port: int,
newPost['object'] = \
attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost['object'], attachImageFilename,
- mediaType, imageDescription, city, lowBandwidth)
+ mediaType, imageDescription, city, lowBandwidth,
+ contentLicenseUrl)
return newPost
@@ -1137,7 +1139,8 @@ def _createPostC2S(baseDir: str, nickname: str, domain: str, port: int,
mediaType: str, imageDescription: str, city: str,
postObjectType: str, summary: str,
inReplyToAtomUri: str, systemLanguage: str,
- conversationId: str, lowBandwidth: str) -> {}:
+ conversationId: str, lowBandwidth: str,
+ contentLicenseUrl: str) -> {}:
"""Creates a new client-to-server post
"""
domainFull = getFullDomain(domain, port)
@@ -1187,7 +1190,8 @@ def _createPostC2S(baseDir: str, nickname: str, domain: str, port: int,
newPost = \
attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost, attachImageFilename,
- mediaType, imageDescription, city, lowBandwidth)
+ mediaType, imageDescription, city, lowBandwidth,
+ contentLicenseUrl)
return newPost
@@ -1314,7 +1318,8 @@ def _createPostBase(baseDir: str,
anonymousParticipationEnabled: bool,
eventStatus: str, ticketUrl: str,
systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Creates a message
"""
content = removeInvalidChars(content)
@@ -1439,7 +1444,8 @@ def _createPostBase(baseDir: str,
mediaType, imageDescription, city,
postObjectType, summary,
inReplyToAtomUri, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
else:
newPost = \
_createPostC2S(baseDir, nickname, domain, port,
@@ -1451,7 +1457,8 @@ def _createPostBase(baseDir: str,
mediaType, imageDescription, city,
postObjectType, summary,
inReplyToAtomUri, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
_createPostMentions(ccUrl, newPost, toRecipients, tags)
@@ -1685,7 +1692,8 @@ def createPublicPost(baseDir: str,
location: str,
isArticle: bool,
systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Public post
"""
domainFull = getFullDomain(domain, port)
@@ -1716,7 +1724,8 @@ def createPublicPost(baseDir: str,
repliesModerationOption,
anonymousParticipationEnabled,
eventStatus, ticketUrl, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
def _appendCitationsToBlogPost(baseDir: str,
@@ -1759,7 +1768,8 @@ def createBlogPost(baseDir: str,
subject: str, schedulePost: bool,
eventDate: str, eventTime: str,
location: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
blogJson = \
createPublicPost(baseDir,
nickname, domain, port, httpPrefix,
@@ -1771,7 +1781,7 @@ def createBlogPost(baseDir: str,
schedulePost,
eventDate, eventTime, location,
True, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
blogJson['object']['url'] = \
blogJson['object']['url'].replace('/@', '/users/')
_appendCitationsToBlogPost(baseDir, nickname, domain, blogJson)
@@ -1785,7 +1795,8 @@ def createNewsPost(baseDir: str,
attachImageFilename: str, mediaType: str,
imageDescription: str, city: str,
subject: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
clientToServer = False
inReplyTo = None
inReplyToAtomUri = None
@@ -1804,7 +1815,7 @@ def createNewsPost(baseDir: str,
schedulePost,
eventDate, eventTime, location,
True, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
blog['object']['type'] = 'Article'
return blog
@@ -1817,7 +1828,8 @@ def createQuestionPost(baseDir: str,
attachImageFilename: str, mediaType: str,
imageDescription: str, city: str,
subject: str, durationDays: int,
- systemLanguage: str, lowBandwidth: bool) -> {}:
+ systemLanguage: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Question post with multiple choice options
"""
domainFull = getFullDomain(domain, port)
@@ -1834,7 +1846,7 @@ def createQuestionPost(baseDir: str,
False, None, None, None, None, None,
None, None, None,
None, None, None, None, None, systemLanguage,
- None, lowBandwidth)
+ None, lowBandwidth, contentLicenseUrl)
messageJson['object']['type'] = 'Question'
messageJson['object']['oneOf'] = []
messageJson['object']['votersCount'] = 0
@@ -1866,7 +1878,8 @@ def createUnlistedPost(baseDir: str,
subject: str, schedulePost: bool,
eventDate: str, eventTime: str,
location: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Unlisted post. This has the #Public and followers links inverted.
"""
domainFull = getFullDomain(domain, port)
@@ -1883,7 +1896,8 @@ def createUnlistedPost(baseDir: str,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
def createFollowersOnlyPost(baseDir: str,
@@ -1899,7 +1913,8 @@ def createFollowersOnlyPost(baseDir: str,
subject: str, schedulePost: bool,
eventDate: str, eventTime: str,
location: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Followers only post
"""
domainFull = getFullDomain(domain, port)
@@ -1916,7 +1931,8 @@ def createFollowersOnlyPost(baseDir: str,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
def getMentionedPeople(baseDir: str, httpPrefix: str,
@@ -1968,7 +1984,8 @@ def createDirectMessagePost(baseDir: str,
schedulePost: bool,
eventDate: str, eventTime: str,
location: str, systemLanguage: str,
- conversationId: str, lowBandwidth: bool) -> {}:
+ conversationId: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Direct Message post
"""
content = resolvePetnames(baseDir, nickname, domain, content)
@@ -1992,7 +2009,8 @@ def createDirectMessagePost(baseDir: str,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
# mentioned recipients go into To rather than Cc
messageJson['to'] = messageJson['object']['cc']
messageJson['object']['to'] = messageJson['to']
@@ -2012,7 +2030,8 @@ def createReportPost(baseDir: str,
attachImageFilename: str, mediaType: str,
imageDescription: str, city: str,
debug: bool, subject: str, systemLanguage: str,
- lowBandwidth: bool) -> {}:
+ lowBandwidth: bool,
+ contentLicenseUrl: str) -> {}:
"""Send a report to moderators
"""
domainFull = getFullDomain(domain, port)
@@ -2086,7 +2105,7 @@ def createReportPost(baseDir: str,
False, None, None, None, None, None,
None, None, None,
None, None, None, None, None, systemLanguage,
- None, lowBandwidth)
+ None, lowBandwidth, contentLicenseUrl)
if not postJsonObject:
continue
@@ -2183,7 +2202,7 @@ def sendPost(signingPrivateKeyPem: str, projectVersion: str,
isArticle: bool, systemLanguage: str,
sharedItemsFederatedDomains: [],
sharedItemFederationTokens: {},
- lowBandwidth: bool,
+ lowBandwidth: bool, contentLicenseUrl: str,
debug: bool = False, inReplyTo: str = None,
inReplyToAtomUri: str = None, subject: str = None) -> int:
"""Post to another inbox. Used by unit tests.
@@ -2249,7 +2268,8 @@ def sendPost(signingPrivateKeyPem: str, projectVersion: str,
False, None, None, None, None, None,
None, None, None,
None, None, None, None, None, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
# get the senders private key
privateKeyPem = _getPersonKey(nickname, domain, baseDir, 'private')
@@ -2331,6 +2351,7 @@ def sendPostViaServer(signingPrivateKeyPem: str, projectVersion: str,
cachedWebfingers: {}, personCache: {},
isArticle: bool, systemLanguage: str,
lowBandwidth: bool,
+ contentLicenseUrl: str,
debug: bool = False,
inReplyTo: str = None,
inReplyToAtomUri: str = None,
@@ -2416,7 +2437,8 @@ def sendPostViaServer(signingPrivateKeyPem: str, projectVersion: str,
False, None, None, None, None, None,
None, None, None,
None, None, None, None, None, systemLanguage,
- conversationId, lowBandwidth)
+ conversationId, lowBandwidth,
+ contentLicenseUrl)
authHeader = createBasicAuthHeader(fromNickname, password)
diff --git a/schedule.py b/schedule.py
index b35d11f7a..804bc16b2 100644
--- a/schedule.py
+++ b/schedule.py
@@ -128,7 +128,8 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd,
httpd.maxLikeCount,
httpd.maxRecentPosts,
httpd.CWlists,
- httpd.listsEnabled):
+ httpd.listsEnabled,
+ httpd.contentLicenseUrl):
indexLines.remove(line)
try:
os.remove(postFilename)
diff --git a/shares.py b/shares.py
index a00e47458..9df356597 100644
--- a/shares.py
+++ b/shares.py
@@ -308,7 +308,8 @@ def addShare(baseDir: str,
duration: str, debug: bool, city: str,
price: str, currency: str,
systemLanguage: str, translate: {},
- sharesFileType: str, lowBandwidth: bool) -> None:
+ sharesFileType: str, lowBandwidth: bool,
+ contentLicenseUrl: str) -> None:
"""Adds a new share
"""
if isFilteredGlobally(baseDir,
@@ -363,7 +364,7 @@ def addShare(baseDir: str,
convertImageToLowBandwidth(imageFilename)
processMetaData(baseDir, nickname, domain,
imageFilename, itemIDfile + '.' + ext,
- city)
+ city, contentLicenseUrl)
if moveImage:
try:
os.remove(imageFilename)
@@ -1033,7 +1034,8 @@ def outboxShareUpload(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int,
messageJson: {}, debug: bool, city: str,
systemLanguage: str, translate: {},
- lowBandwidth: bool) -> None:
+ lowBandwidth: bool,
+ contentLicenseUrl: str) -> None:
""" When a shared item is received by the outbox from c2s
"""
if not messageJson.get('type'):
@@ -1095,7 +1097,7 @@ def outboxShareUpload(baseDir: str, httpPrefix: str,
messageJson['object']['itemPrice'],
messageJson['object']['itemCurrency'],
systemLanguage, translate, 'shares',
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
if debug:
print('DEBUG: shared item received via c2s')
diff --git a/tests.py b/tests.py
index 876594409..616389903 100644
--- a/tests.py
+++ b/tests.py
@@ -753,6 +753,7 @@ def createServerAlice(path: str, domain: str, port: int,
testLocation = None
testIsArticle = False
conversationId = None
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
createPublicPost(path, nickname, domain, port, httpPrefix,
"No wise fish would go anywhere without a porpoise",
testFollowersOnly,
@@ -766,7 +767,7 @@ def createServerAlice(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
createPublicPost(path, nickname, domain, port, httpPrefix,
"Curiouser and curiouser!",
testFollowersOnly,
@@ -780,7 +781,7 @@ def createServerAlice(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
createPublicPost(path, nickname, domain, port, httpPrefix,
"In the gardens of memory, in the palace " +
"of dreams, that is where you and I shall meet",
@@ -795,7 +796,7 @@ def createServerAlice(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
regenerateIndexForBox(path, nickname, domain, 'outbox')
global testServerAliceRunning
testServerAliceRunning = True
@@ -818,8 +819,10 @@ def createServerAlice(path: str, domain: str, port: int,
maxLikeCount = 10
defaultReplyIntervalHours = 9999999999
listsEnabled = ''
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
print('Server running: Alice')
- runDaemon(listsEnabled, defaultReplyIntervalHours,
+ runDaemon(contentLicenseUrl,
+ listsEnabled, defaultReplyIntervalHours,
lowBandwidth, maxLikeCount,
sharedItemsFederatedDomains,
userAgentsBlocked,
@@ -892,6 +895,7 @@ def createServerBob(path: str, domain: str, port: int,
testLocation = None
testIsArticle = False
conversationId = None
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
createPublicPost(path, nickname, domain, port, httpPrefix,
"It's your life, live it your way.",
testFollowersOnly,
@@ -905,7 +909,7 @@ def createServerBob(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
createPublicPost(path, nickname, domain, port, httpPrefix,
"One of the things I've realised is that " +
"I am very simple",
@@ -920,7 +924,7 @@ def createServerBob(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
createPublicPost(path, nickname, domain, port, httpPrefix,
"Quantum physics is a bit of a passion of mine",
testFollowersOnly,
@@ -934,7 +938,7 @@ def createServerBob(path: str, domain: str, port: int,
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
regenerateIndexForBox(path, nickname, domain, 'outbox')
global testServerBobRunning
testServerBobRunning = True
@@ -957,8 +961,10 @@ def createServerBob(path: str, domain: str, port: int,
maxLikeCount = 10
defaultReplyIntervalHours = 9999999999
listsEnabled = ''
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
print('Server running: Bob')
- runDaemon(listsEnabled, defaultReplyIntervalHours,
+ runDaemon(contentLicenseUrl,
+ listsEnabled, defaultReplyIntervalHours,
lowBandwidth, maxLikeCount,
sharedItemsFederatedDomains,
userAgentsBlocked,
@@ -1025,8 +1031,10 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
lowBandwidth = True
defaultReplyIntervalHours = 9999999999
listsEnabled = ''
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
print('Server running: Eve')
- runDaemon(listsEnabled, defaultReplyIntervalHours,
+ runDaemon(contentLicenseUrl,
+ listsEnabled, defaultReplyIntervalHours,
lowBandwidth, maxLikeCount,
sharedItemsFederatedDomains,
userAgentsBlocked,
@@ -1095,8 +1103,10 @@ def createServerGroup(path: str, domain: str, port: int,
lowBandwidth = True
defaultReplyIntervalHours = 9999999999
listsEnabled = ''
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
print('Server running: Group')
- runDaemon(listsEnabled, defaultReplyIntervalHours,
+ runDaemon(contentLicenseUrl,
+ listsEnabled, defaultReplyIntervalHours,
lowBandwidth, maxLikeCount,
sharedItemsFederatedDomains,
userAgentsBlocked,
@@ -1132,6 +1142,7 @@ def testPostMessageBetweenServers(baseDir: str) -> None:
systemLanguage = 'en'
httpPrefix = 'http'
proxyType = None
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
if os.path.isdir(baseDir + '/.tests'):
shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None)
@@ -1235,6 +1246,7 @@ def testPostMessageBetweenServers(baseDir: str) -> None:
alicePersonCache, isArticle, systemLanguage,
aliceSharedItemsFederatedDomains,
aliceSharedItemFederationTokens, lowBandwidth,
+ contentLicenseUrl,
inReplyTo, inReplyToAtomUri, subject)
print('sendResult: ' + str(sendResult))
@@ -1433,6 +1445,7 @@ def testFollowBetweenServers(baseDir: str) -> None:
httpPrefix = 'http'
proxyType = None
federationList = []
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
if os.path.isdir(baseDir + '/.tests'):
shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None)
@@ -1572,6 +1585,7 @@ def testFollowBetweenServers(baseDir: str) -> None:
alicePersonCache, isArticle, systemLanguage,
aliceSharedItemsFederatedDomains,
aliceSharedItemFederationTokens, lowBandwidth,
+ contentLicenseUrl,
inReplyTo, inReplyToAtomUri, subject)
print('sendResult: ' + str(sendResult))
@@ -1620,6 +1634,7 @@ def testSharedItemsFederation(baseDir: str) -> None:
httpPrefix = 'http'
proxyType = None
federationList = []
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
if os.path.isdir(baseDir + '/.tests'):
shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None)
@@ -1920,7 +1935,8 @@ def testSharedItemsFederation(baseDir: str) -> None:
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, systemLanguage,
aliceSharedItemsFederatedDomains,
- aliceSharedItemFederationTokens, lowBandwidth, True,
+ aliceSharedItemFederationTokens, lowBandwidth,
+ contentLicenseUrl, True,
inReplyTo, inReplyToAtomUri, subject)
print('sendResult: ' + str(sendResult))
@@ -2024,6 +2040,7 @@ def testGroupFollow(baseDir: str) -> None:
httpPrefix = 'http'
proxyType = None
federationList = []
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
if os.path.isdir(baseDir + '/.tests'):
shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None)
@@ -2340,6 +2357,7 @@ def testGroupFollow(baseDir: str) -> None:
alicePersonCache, isArticle, systemLanguage,
aliceSharedItemsFederatedDomains,
aliceSharedItemFederationTokens, lowBandwidth,
+ contentLicenseUrl,
inReplyTo, inReplyToAtomUri, subject)
print('sendResult: ' + str(sendResult))
@@ -2692,6 +2710,7 @@ def _testCreatePerson(baseDir: str):
mediaType = None
conversationId = None
lowBandwidth = True
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
content, followersOnly, saveToFile, clientToServer,
commentsEnabled, attachImageFilename, mediaType,
@@ -2700,7 +2719,7 @@ def _testCreatePerson(baseDir: str):
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
os.chdir(currDir)
shutil.rmtree(baseDir, ignore_errors=False, onerror=None)
@@ -2763,6 +2782,7 @@ def testClientToServer(baseDir: str):
global testServerAliceRunning
global testServerBobRunning
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
testServerAliceRunning = False
testServerBobRunning = False
@@ -2879,6 +2899,7 @@ def testClientToServer(baseDir: str):
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
systemLanguage, lowBandwidth,
+ contentLicenseUrl,
True, None, None,
conversationId, None)
print('sendResult: ' + str(sendResult))
@@ -4185,6 +4206,7 @@ def _testReplyToPublicPost(baseDir: str) -> None:
testIsArticle = False
conversationId = None
lowBandwidth = True
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
reply = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
content, followersOnly, saveToFile,
@@ -4195,7 +4217,7 @@ def _testReplyToPublicPost(baseDir: str) -> None:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
# print(str(reply))
assert reply['object']['content'] == \
'
' + \
@@ -4717,6 +4739,7 @@ def _testLinksWithinPost(baseDir: str) -> None:
testIsArticle = False
conversationId = None
lowBandwidth = True
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
postJsonObject = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
@@ -4728,7 +4751,7 @@ def _testLinksWithinPost(baseDir: str) -> None:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
assert postJsonObject['object']['content'] == \
'This is a test post with links. ' + \
@@ -4765,7 +4788,7 @@ def _testLinksWithinPost(baseDir: str) -> None:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
assert postJsonObject['object']['content'] == content
assert postJsonObject['object']['contentMap'][systemLanguage] == content
@@ -5703,6 +5726,7 @@ def _testCanReplyTo(baseDir: str) -> None:
testIsArticle = False
conversationId = None
lowBandwidth = True
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
postJsonObject = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
@@ -5714,7 +5738,7 @@ def _testCanReplyTo(baseDir: str) -> None:
testSubject, testSchedulePost,
testEventDate, testEventTime, testLocation,
testIsArticle, systemLanguage, conversationId,
- lowBandwidth)
+ lowBandwidth, contentLicenseUrl)
# set the date on the post
currDateStr = "2021-09-08T20:45:00Z"
postJsonObject['published'] = currDateStr
diff --git a/translations/ar.json b/translations/ar.json
index f71b30e40..53e3d7da9 100644
--- a/translations/ar.json
+++ b/translations/ar.json
@@ -491,5 +491,6 @@
"System Monitor": "مراقب النظام",
"Add content warnings for the following sites": "أضف تحذيرات المحتوى للمواقع التالية",
"Known Web Crawlers": "برامج زحف الويب المعروفة",
- "Add to the calendar": "أضف إلى التقويم"
+ "Add to the calendar": "أضف إلى التقويم",
+ "Content License": "ترخيص المحتوى"
}
diff --git a/translations/ca.json b/translations/ca.json
index 07205607c..fb0b7340d 100644
--- a/translations/ca.json
+++ b/translations/ca.json
@@ -491,5 +491,6 @@
"System Monitor": "Monitor del sistema",
"Add content warnings for the following sites": "Afegiu advertiments de contingut per als llocs següents",
"Known Web Crawlers": "Exploradors web coneguts",
- "Add to the calendar": "Afegeix al calendari"
+ "Add to the calendar": "Afegeix al calendari",
+ "Content License": "Llicència de contingut"
}
diff --git a/translations/cy.json b/translations/cy.json
index 6a3715cb6..d1eaf3d76 100644
--- a/translations/cy.json
+++ b/translations/cy.json
@@ -491,5 +491,6 @@
"System Monitor": "Monitor System",
"Add content warnings for the following sites": "Ychwanegwch rybuddion cynnwys ar gyfer y gwefannau canlynol",
"Known Web Crawlers": "Crawlers Gwe Hysbys",
- "Add to the calendar": "Ychwanegwch at y calendr"
+ "Add to the calendar": "Ychwanegwch at y calendr",
+ "Content License": "Trwydded Cynnwys"
}
diff --git a/translations/de.json b/translations/de.json
index da33ff00f..a94268597 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -491,5 +491,6 @@
"System Monitor": "Systemmonitor",
"Add content warnings for the following sites": "Inhaltswarnungen für die folgenden Websites hinzufügen",
"Known Web Crawlers": "Bekannte Web-Crawler",
- "Add to the calendar": "Zum Kalender hinzufügen"
+ "Add to the calendar": "Zum Kalender hinzufügen",
+ "Content License": "Inhaltslizenz"
}
diff --git a/translations/en.json b/translations/en.json
index 551749a49..d96083f0b 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -491,5 +491,6 @@
"System Monitor": "System Monitor",
"Add content warnings for the following sites": "Add content warnings for the following sites",
"Known Web Crawlers": "Known Web Crawlers",
- "Add to the calendar": "Add to the calendar"
+ "Add to the calendar": "Add to the calendar",
+ "Content License": "Content License"
}
diff --git a/translations/es.json b/translations/es.json
index d89b835ec..00a945f28 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -491,5 +491,6 @@
"System Monitor": "Monitor del sistema",
"Add content warnings for the following sites": "Agregue advertencias de contenido para los siguientes sitios",
"Known Web Crawlers": "Rastreadores web conocidos",
- "Add to the calendar": "Agregar al calendario"
+ "Add to the calendar": "Agregar al calendario",
+ "Content License": "Licencia de contenido"
}
diff --git a/translations/fr.json b/translations/fr.json
index 73982bb9e..0d082c4a9 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -491,5 +491,6 @@
"System Monitor": "Moniteur système",
"Add content warnings for the following sites": "Ajouter des avertissements de contenu pour les sites suivants",
"Known Web Crawlers": "Crawlers Web connus",
- "Add to the calendar": "Ajouter au calendrier"
+ "Add to the calendar": "Ajouter au calendrier",
+ "Content License": "Licence de contenu"
}
diff --git a/translations/ga.json b/translations/ga.json
index 8af1069ed..1d91c0471 100644
--- a/translations/ga.json
+++ b/translations/ga.json
@@ -491,5 +491,6 @@
"System Monitor": "Monatóir Córais",
"Add content warnings for the following sites": "Cuir rabhaidh ábhair leis na suíomhanna seo a leanas",
"Known Web Crawlers": "Crawlers Gréasáin Aitheanta",
- "Add to the calendar": "Cuir leis an bhféilire"
+ "Add to the calendar": "Cuir leis an bhféilire",
+ "Content License": "Ceadúnas Ábhar"
}
diff --git a/translations/hi.json b/translations/hi.json
index e044eb261..93a81c7e6 100644
--- a/translations/hi.json
+++ b/translations/hi.json
@@ -491,5 +491,6 @@
"System Monitor": "सिस्टम मॉनिटर",
"Add content warnings for the following sites": "निम्नलिखित साइटों के लिए सामग्री चेतावनियाँ जोड़ें",
"Known Web Crawlers": "ज्ञात वेब क्रॉलर",
- "Add to the calendar": "कैलेंडर में जोड़ें"
+ "Add to the calendar": "कैलेंडर में जोड़ें",
+ "Content License": "सामग्री लाइसेंस"
}
diff --git a/translations/it.json b/translations/it.json
index c847b5dc5..64319f34a 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -491,5 +491,6 @@
"System Monitor": "Monitor di sistema",
"Add content warnings for the following sites": "Aggiungi avvisi sui contenuti per i seguenti siti",
"Known Web Crawlers": "Crawler Web conosciuti",
- "Add to the calendar": "Aggiungi al calendario"
+ "Add to the calendar": "Aggiungi al calendario",
+ "Content License": "Licenza sui contenuti"
}
diff --git a/translations/ja.json b/translations/ja.json
index 17f939fbe..89b880f99 100644
--- a/translations/ja.json
+++ b/translations/ja.json
@@ -491,5 +491,6 @@
"System Monitor": "システムモニター",
"Add content warnings for the following sites": "次のサイトのコンテンツ警告を追加します",
"Known Web Crawlers": "既知のWebクローラー",
- "Add to the calendar": "カレンダーに追加"
+ "Add to the calendar": "カレンダーに追加",
+ "Content License": "コンテンツライセンス"
}
diff --git a/translations/ku.json b/translations/ku.json
index 36698735f..54edfdbb8 100644
--- a/translations/ku.json
+++ b/translations/ku.json
@@ -491,5 +491,6 @@
"System Monitor": "System Monitor",
"Add content warnings for the following sites": "Ji bo malperên jêrîn hişyariyên naverokê zêde bikin",
"Known Web Crawlers": "Crawlerên Webê yên naskirî",
- "Add to the calendar": "Di salnameyê de zêde bike"
+ "Add to the calendar": "Di salnameyê de zêde bike",
+ "Content License": "Naverok License de"
}
diff --git a/translations/oc.json b/translations/oc.json
index dc898e1e4..8240c4a8e 100644
--- a/translations/oc.json
+++ b/translations/oc.json
@@ -487,5 +487,6 @@
"System Monitor": "System Monitor",
"Add content warnings for the following sites": "Add content warnings for the following sites",
"Known Web Crawlers": "Known Web Crawlers",
- "Add to the calendar": "Add to the calendar"
+ "Add to the calendar": "Add to the calendar",
+ "Content License": "Content License"
}
diff --git a/translations/pt.json b/translations/pt.json
index 936c7f095..958a40f6f 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -491,5 +491,6 @@
"System Monitor": "Monitor de Sistema",
"Add content warnings for the following sites": "Adicione avisos de conteúdo para os seguintes sites",
"Known Web Crawlers": "Rastreadores da Web conhecidos",
- "Add to the calendar": "Adicionar ao calendário"
+ "Add to the calendar": "Adicionar ao calendário",
+ "Content License": "Licença de Conteúdo"
}
diff --git a/translations/ru.json b/translations/ru.json
index bb92161d9..d59bf4869 100644
--- a/translations/ru.json
+++ b/translations/ru.json
@@ -491,5 +491,6 @@
"System Monitor": "Системный монитор",
"Add content warnings for the following sites": "Добавить предупреждения о содержании для следующих сайтов",
"Known Web Crawlers": "Известные веб-сканеры",
- "Add to the calendar": "Добавить в календарь"
+ "Add to the calendar": "Добавить в календарь",
+ "Content License": "Лицензия на содержание"
}
diff --git a/translations/sw.json b/translations/sw.json
index aace5f87e..d4a5ca713 100644
--- a/translations/sw.json
+++ b/translations/sw.json
@@ -491,5 +491,6 @@
"System Monitor": "Ufuatiliaji wa Mfumo",
"Add content warnings for the following sites": "Ongeza maonyo ya yaliyomo kwa wavuti zifuatazo",
"Known Web Crawlers": "Watambaji Wavuti Wanaojulikana",
- "Add to the calendar": "Ongeza kwenye kalenda"
+ "Add to the calendar": "Ongeza kwenye kalenda",
+ "Content License": "Leseni ya Maudhui"
}
diff --git a/translations/zh.json b/translations/zh.json
index bde6635db..a698fb5ce 100644
--- a/translations/zh.json
+++ b/translations/zh.json
@@ -491,5 +491,6 @@
"System Monitor": "系统监视器",
"Add content warnings for the following sites": "为以下网站添加内容警告",
"Known Web Crawlers": "已知的网络爬虫",
- "Add to the calendar": "添加到日历"
+ "Add to the calendar": "添加到日历",
+ "Content License": "内容许可"
}
diff --git a/webapp_profile.py b/webapp_profile.py
index 9d01178e0..269851597 100644
--- a/webapp_profile.py
+++ b/webapp_profile.py
@@ -53,6 +53,7 @@ from jami import getJamiAddress
from cwtch import getCwtchAddress
from filters import isFiltered
from follow import isFollowerOfPerson
+from follow import getFollowerDomains
from webapp_frontscreen import htmlFrontScreen
from webapp_utils import htmlKeyboardNavigation
from webapp_utils import htmlHideFromScreenReader
@@ -541,7 +542,8 @@ def htmlProfile(signingPrivateKeyPem: str,
sharedItemsFederatedDomains: [],
extraJson: {}, pageNumber: int,
maxItemsPerPage: int,
- CWlists: {}, listsEnabled: str) -> str:
+ CWlists: {}, listsEnabled: str,
+ contentLicenseUrl: str) -> str:
"""Show the profile page as html
"""
nickname = profileJson['preferredUsername']
@@ -716,9 +718,12 @@ def htmlProfile(signingPrivateKeyPem: str,
break
if selected == 'followers':
if followApprovals:
+ currFollowerDomains = \
+ getFollowerDomains(baseDir, nickname, domain)
with open(followRequestsFilename, 'r') as f:
for followerHandle in f:
if len(line) > 0:
+ followerHandle = followerHandle.replace('\n', '')
if '://' in followerHandle:
followerActor = followerHandle
else:
@@ -726,13 +731,25 @@ def htmlProfile(signingPrivateKeyPem: str,
dom = followerHandle.split('@')[1]
followerActor = \
localActorUrl(httpPrefix, nick, dom)
+
+ # is this a new domain?
+ # if so then append a new instance indicator
+ followerDomain, _ = \
+ getDomainFromActor(followerActor)
+ newFollowerDomain = ''
+ if followerDomain not in currFollowerDomains:
+ newFollowerDomain = ' ✨'
+
basePath = '/users/' + nickname
followApprovalsSection += '
'
followApprovalsSection += \
'
'
followApprovalsSection += \
'' + \
- followerHandle + ' '
+ followerHandle + \
+ newFollowerDomain + ''
+
+ # show Approve and Deny buttons
followApprovalsSection += \
'
'
@@ -970,7 +987,8 @@ def htmlProfile(signingPrivateKeyPem: str,
getConfigParam(baseDir, 'instanceTitle')
profileStr = \
htmlHeaderWithPersonMarkup(cssFilename, instanceTitle,
- profileJson, city) + \
+ profileJson, city,
+ contentLicenseUrl) + \
profileStr + htmlFooter()
return profileStr
@@ -1268,6 +1286,10 @@ def _htmlEditProfileInstance(baseDir: str, translate: {},
getConfigParam(baseDir, 'instanceDescriptionShort')
instanceTitle = \
getConfigParam(baseDir, 'instanceTitle')
+ contentLicenseUrl = \
+ getConfigParam(baseDir, 'contentLicenseUrl')
+ if not contentLicenseUrl:
+ contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0'
instanceStr = beginEditSection(translate['Instance Settings'])
@@ -1283,6 +1305,10 @@ def _htmlEditProfileInstance(baseDir: str, translate: {},
editTextArea(translate['Instance Description'],
'instanceDescription', instanceDescription, 200,
'', True)
+ instanceStr += \
+ editTextField(translate['Content License'],
+ 'contentLicenseUrl', contentLicenseUrl)
+ instanceStr += ' \n'
instanceStr += \
editTextField(translate['Custom post submit button text'],
'customSubmitText', customSubmitText)
diff --git a/webapp_utils.py b/webapp_utils.py
index cd68b6963..0647d899b 100644
--- a/webapp_utils.py
+++ b/webapp_utils.py
@@ -533,8 +533,15 @@ def htmlHeaderWithExternalStyle(cssFilename: str, instanceTitle: str,
'\n' + \
' \n' + \
' \n' + \
- ' \n' + \
+ ' \n' + \
' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
' \n' + \
metadata + \
' ' + instanceTitle + ' \n' + \
@@ -545,6 +552,7 @@ def htmlHeaderWithExternalStyle(cssFilename: str, instanceTitle: str,
def htmlHeaderWithPersonMarkup(cssFilename: str, instanceTitle: str,
actorJson: {}, city: str,
+ contentLicenseUrl: str,
lang='en') -> str:
"""html header which includes person markup
https://schema.org/Person
@@ -658,7 +666,6 @@ def htmlHeaderWithPersonMarkup(cssFilename: str, instanceTitle: str,
' "url": "' + actorJson['id'] + '"\n' + \
' },\n'
- licenseUrl = 'https://creativecommons.org/licenses/by/4.0'
profileMarkup = \
' \n'
@@ -788,8 +795,11 @@ def htmlHeaderWithWebsiteMarkup(cssFilename: str, instanceTitle: str,
def htmlHeaderWithBlogMarkup(cssFilename: str, instanceTitle: str,
httpPrefix: str, domain: str, nickname: str,
- systemLanguage: str, published: str,
- title: str, snippet: str) -> str:
+ systemLanguage: str,
+ published: str, modified: str,
+ title: str, snippet: str,
+ translate: {}, url: str,
+ contentLicenseUrl: str) -> str:
"""html header which includes blog post markup
https://schema.org/BlogPosting
"""
@@ -798,7 +808,6 @@ def htmlHeaderWithBlogMarkup(cssFilename: str, instanceTitle: str,
# license for content on the site may be different from
# the software license
- contentLicenseUrl = 'https://creativecommons.org/licenses/by/3.0'
blogMarkup = \
' \n'
+
+ ogMetadata = \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n' + \
+ ' \n'
+
htmlStr = \
- htmlHeaderWithExternalStyle(cssFilename, instanceTitle, blogMarkup,
- systemLanguage)
+ htmlHeaderWithExternalStyle(cssFilename, instanceTitle,
+ ogMetadata + blogMarkup, systemLanguage)
return htmlStr