Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
|
|
@ -2237,8 +2237,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.cachedWebfingers,
|
self.server.cachedWebfingers,
|
||||||
self.server.personCache,
|
self.server.personCache,
|
||||||
debug,
|
debug,
|
||||||
self.server.projectVersion,
|
self.server.projectVersion)
|
||||||
self.server.allowNewsFollowers)
|
|
||||||
if callingDomain.endswith('.onion') and onionDomain:
|
if callingDomain.endswith('.onion') and onionDomain:
|
||||||
originPathStr = 'http://' + onionDomain + usersPath
|
originPathStr = 'http://' + onionDomain + usersPath
|
||||||
elif (callingDomain.endswith('.i2p') and i2pDomain):
|
elif (callingDomain.endswith('.i2p') and i2pDomain):
|
||||||
|
|
@ -13364,7 +13363,6 @@ def runDaemon(sendThreadsTimeoutMins: int,
|
||||||
fullWidthTimelineButtonHeader: bool,
|
fullWidthTimelineButtonHeader: bool,
|
||||||
showPublishAsIcon: bool,
|
showPublishAsIcon: bool,
|
||||||
maxFollowers: int,
|
maxFollowers: int,
|
||||||
allowNewsFollowers: bool,
|
|
||||||
maxNewsPosts: int,
|
maxNewsPosts: int,
|
||||||
maxMirroredArticles: int,
|
maxMirroredArticles: int,
|
||||||
maxNewswireFeedSizeKb: int,
|
maxNewswireFeedSizeKb: int,
|
||||||
|
|
@ -13515,9 +13513,6 @@ def runDaemon(sendThreadsTimeoutMins: int,
|
||||||
# maximum number of posts in the news timeline/outbox
|
# maximum number of posts in the news timeline/outbox
|
||||||
httpd.maxNewsPosts = maxNewsPosts
|
httpd.maxNewsPosts = maxNewsPosts
|
||||||
|
|
||||||
# whether or not to allow followers of the news account
|
|
||||||
httpd.allowNewsFollowers = allowNewsFollowers
|
|
||||||
|
|
||||||
# The maximum number of tags per post which can be
|
# The maximum number of tags per post which can be
|
||||||
# attached to RSS feeds pulled in via the newswire
|
# attached to RSS feeds pulled in via the newswire
|
||||||
httpd.maxTags = 32
|
httpd.maxTags = 32
|
||||||
|
|
@ -13704,7 +13699,6 @@ def runDaemon(sendThreadsTimeoutMins: int,
|
||||||
httpd.translate, unitTest,
|
httpd.translate, unitTest,
|
||||||
httpd.YTReplacementDomain,
|
httpd.YTReplacementDomain,
|
||||||
httpd.showPublishedDateOnly,
|
httpd.showPublishedDateOnly,
|
||||||
httpd.allowNewsFollowers,
|
|
||||||
httpd.maxFollowers,
|
httpd.maxFollowers,
|
||||||
httpd.allowLocalNetworkAccess,
|
httpd.allowLocalNetworkAccess,
|
||||||
httpd.peertubeInstances), daemon=True)
|
httpd.peertubeInstances), daemon=True)
|
||||||
|
|
|
||||||
|
|
@ -999,11 +999,17 @@ div.container {
|
||||||
color: var(--column-right-fg-color);
|
color: var(--column-right-fg-color);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItem img {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
.newswireItemModerated {
|
.newswireItemModerated {
|
||||||
font-size: var(--font-size-newswire);
|
font-size: var(--font-size-newswire);
|
||||||
color: var(--newswire-item-moderated-color);
|
color: var(--newswire-item-moderated-color);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItemModerated img {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
.newswireDateModerated {
|
.newswireDateModerated {
|
||||||
font-size: var(--font-size-newswire);
|
font-size: var(--font-size-newswire);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
@ -1019,6 +1025,9 @@ div.container {
|
||||||
color: var(--column-right-fg-color-voted-on);
|
color: var(--column-right-fg-color-voted-on);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItemVotedOn img {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
.newswireDate {
|
.newswireDate {
|
||||||
font-size: var(--font-size-newswire);
|
font-size: var(--font-size-newswire);
|
||||||
color: var(--newswire-date-color);
|
color: var(--newswire-date-color);
|
||||||
|
|
@ -1685,11 +1694,17 @@ div.container {
|
||||||
color: var(--column-right-fg-color);
|
color: var(--column-right-fg-color);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItem img {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
.newswireItemModerated {
|
.newswireItemModerated {
|
||||||
font-size: var(--font-size-newswire-mobile);
|
font-size: var(--font-size-newswire-mobile);
|
||||||
color: var(--newswire-item-moderated-color);
|
color: var(--newswire-item-moderated-color);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItemModerated img {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
.newswireDateModerated {
|
.newswireDateModerated {
|
||||||
font-size: var(--font-size-newswire-mobile);
|
font-size: var(--font-size-newswire-mobile);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
@ -1705,6 +1720,9 @@ div.container {
|
||||||
color: var(--column-right-fg-color-voted-on);
|
color: var(--column-right-fg-color-voted-on);
|
||||||
line-height: var(--line-spacing-newswire);
|
line-height: var(--line-spacing-newswire);
|
||||||
}
|
}
|
||||||
|
.newswireItemVotedOn img {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
.newswireDate {
|
.newswireDate {
|
||||||
font-size: var(--font-size-newswire-mobile);
|
font-size: var(--font-size-newswire-mobile);
|
||||||
color: var(--newswire-date-color);
|
color: var(--newswire-date-color);
|
||||||
|
|
|
||||||
11
epicyon.py
|
|
@ -243,11 +243,6 @@ parser.add_argument("--fullWidthTimelineButtonHeader",
|
||||||
help="Whether to show the timeline " +
|
help="Whether to show the timeline " +
|
||||||
"button header containing inbox and outbox " +
|
"button header containing inbox and outbox " +
|
||||||
"as the full width of the screen")
|
"as the full width of the screen")
|
||||||
parser.add_argument("--allowNewsFollowers",
|
|
||||||
dest='allowNewsFollowers',
|
|
||||||
type=str2bool, nargs='?',
|
|
||||||
const=True, default=False,
|
|
||||||
help="Whether to allow the news account to be followed")
|
|
||||||
parser.add_argument("--iconsAsButtons",
|
parser.add_argument("--iconsAsButtons",
|
||||||
dest='iconsAsButtons',
|
dest='iconsAsButtons',
|
||||||
type=str2bool, nargs='?',
|
type=str2bool, nargs='?',
|
||||||
|
|
@ -2095,11 +2090,6 @@ sendThreadsTimeoutMins = \
|
||||||
if sendThreadsTimeoutMins is not None:
|
if sendThreadsTimeoutMins is not None:
|
||||||
args.sendThreadsTimeoutMins = int(sendThreadsTimeoutMins)
|
args.sendThreadsTimeoutMins = int(sendThreadsTimeoutMins)
|
||||||
|
|
||||||
allowNewsFollowers = \
|
|
||||||
getConfigParam(baseDir, 'allowNewsFollowers')
|
|
||||||
if allowNewsFollowers is not None:
|
|
||||||
args.allowNewsFollowers = bool(allowNewsFollowers)
|
|
||||||
|
|
||||||
showPublishAsIcon = \
|
showPublishAsIcon = \
|
||||||
getConfigParam(baseDir, 'showPublishAsIcon')
|
getConfigParam(baseDir, 'showPublishAsIcon')
|
||||||
if showPublishAsIcon is not None:
|
if showPublishAsIcon is not None:
|
||||||
|
|
@ -2154,7 +2144,6 @@ if __name__ == "__main__":
|
||||||
args.fullWidthTimelineButtonHeader,
|
args.fullWidthTimelineButtonHeader,
|
||||||
args.showPublishAsIcon,
|
args.showPublishAsIcon,
|
||||||
args.maxFollowers,
|
args.maxFollowers,
|
||||||
args.allowNewsFollowers,
|
|
||||||
args.maxNewsPosts,
|
args.maxNewsPosts,
|
||||||
args.maxMirroredArticles,
|
args.maxMirroredArticles,
|
||||||
args.maxNewswireFeedSizeKb,
|
args.maxNewswireFeedSizeKb,
|
||||||
|
|
|
||||||
29
follow.py
|
|
@ -68,14 +68,9 @@ def createInitialLastSeen(baseDir: str, httpPrefix: str) -> None:
|
||||||
|
|
||||||
def _preApprovedFollower(baseDir: str,
|
def _preApprovedFollower(baseDir: str,
|
||||||
nickname: str, domain: str,
|
nickname: str, domain: str,
|
||||||
approveHandle: str,
|
approveHandle: str) -> bool:
|
||||||
allowNewsFollowers: bool) -> bool:
|
|
||||||
"""Is the given handle an already manually approved follower?
|
"""Is the given handle an already manually approved follower?
|
||||||
"""
|
"""
|
||||||
# optionally allow the news account to be followed
|
|
||||||
if nickname == 'news' and allowNewsFollowers:
|
|
||||||
return True
|
|
||||||
|
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
accountDir = baseDir + '/accounts/' + handle
|
accountDir = baseDir + '/accounts/' + handle
|
||||||
approvedFilename = accountDir + '/approved.txt'
|
approvedFilename = accountDir + '/approved.txt'
|
||||||
|
|
@ -460,13 +455,12 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
|
||||||
|
|
||||||
def _followApprovalRequired(baseDir: str, nicknameToFollow: str,
|
def _followApprovalRequired(baseDir: str, nicknameToFollow: str,
|
||||||
domainToFollow: str, debug: bool,
|
domainToFollow: str, debug: bool,
|
||||||
followRequestHandle: str,
|
followRequestHandle: str) -> bool:
|
||||||
allowNewsFollowers: bool) -> bool:
|
|
||||||
""" Returns the policy for follower approvals
|
""" Returns the policy for follower approvals
|
||||||
"""
|
"""
|
||||||
# has this handle already been manually approved?
|
# has this handle already been manually approved?
|
||||||
if _preApprovedFollower(baseDir, nicknameToFollow, domainToFollow,
|
if _preApprovedFollower(baseDir, nicknameToFollow, domainToFollow,
|
||||||
followRequestHandle, allowNewsFollowers):
|
followRequestHandle):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
manuallyApproveFollows = False
|
manuallyApproveFollows = False
|
||||||
|
|
@ -600,7 +594,6 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
|
||||||
cachedWebfingers: {}, personCache: {},
|
cachedWebfingers: {}, personCache: {},
|
||||||
messageJson: {}, federationList: [],
|
messageJson: {}, federationList: [],
|
||||||
debug: bool, projectVersion: str,
|
debug: bool, projectVersion: str,
|
||||||
allowNewsFollowers: bool,
|
|
||||||
maxFollowers: int) -> bool:
|
maxFollowers: int) -> bool:
|
||||||
"""Receives a follow request within the POST section of HTTPServer
|
"""Receives a follow request within the POST section of HTTPServer
|
||||||
"""
|
"""
|
||||||
|
|
@ -651,11 +644,10 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
|
||||||
'nickname for the account followed')
|
'nickname for the account followed')
|
||||||
return True
|
return True
|
||||||
if isSystemAccount(nicknameToFollow):
|
if isSystemAccount(nicknameToFollow):
|
||||||
if not (nicknameToFollow == 'news' and allowNewsFollowers):
|
if debug:
|
||||||
if debug:
|
print('DEBUG: Cannot follow system account - ' +
|
||||||
print('DEBUG: Cannot follow system account - ' +
|
nicknameToFollow)
|
||||||
nicknameToFollow)
|
return True
|
||||||
return True
|
|
||||||
if maxFollowers > 0:
|
if maxFollowers > 0:
|
||||||
if _getNoOfFollowers(baseDir,
|
if _getNoOfFollowers(baseDir,
|
||||||
nicknameToFollow, domainToFollow,
|
nicknameToFollow, domainToFollow,
|
||||||
|
|
@ -683,8 +675,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
|
||||||
# what is the followers policy?
|
# what is the followers policy?
|
||||||
approveHandle = nickname + '@' + domainFull
|
approveHandle = nickname + '@' + domainFull
|
||||||
if _followApprovalRequired(baseDir, nicknameToFollow,
|
if _followApprovalRequired(baseDir, nicknameToFollow,
|
||||||
domainToFollow, debug, approveHandle,
|
domainToFollow, debug, approveHandle):
|
||||||
allowNewsFollowers):
|
|
||||||
print('Follow approval is required')
|
print('Follow approval is required')
|
||||||
if domain.endswith('.onion'):
|
if domain.endswith('.onion'):
|
||||||
if _noOfFollowRequests(baseDir,
|
if _noOfFollowRequests(baseDir,
|
||||||
|
|
@ -877,7 +868,7 @@ def sendFollowRequest(session, baseDir: str,
|
||||||
clientToServer: bool, federationList: [],
|
clientToServer: bool, federationList: [],
|
||||||
sendThreads: [], postLog: [], cachedWebfingers: {},
|
sendThreads: [], postLog: [], cachedWebfingers: {},
|
||||||
personCache: {}, debug: bool,
|
personCache: {}, debug: bool,
|
||||||
projectVersion: str, allowNewsFollowers: bool) -> {}:
|
projectVersion: str) -> {}:
|
||||||
"""Gets the json object for sending a follow request
|
"""Gets the json object for sending a follow request
|
||||||
"""
|
"""
|
||||||
if not domainPermitted(followDomain, federationList):
|
if not domainPermitted(followDomain, federationList):
|
||||||
|
|
@ -910,7 +901,7 @@ def sendFollowRequest(session, baseDir: str,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _followApprovalRequired(baseDir, nickname, domain, debug,
|
if _followApprovalRequired(baseDir, nickname, domain, debug,
|
||||||
followHandle, allowNewsFollowers):
|
followHandle):
|
||||||
# Remove any follow requests rejected for the account being followed.
|
# Remove any follow requests rejected for the account being followed.
|
||||||
# It's assumed that if you are following someone then you are
|
# It's assumed that if you are following someone then you are
|
||||||
# ok with them following back. If this isn't the case then a rejected
|
# ok with them following back. If this isn't the case then a rejected
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# Font Licenses
|
# Font Licenses
|
||||||
|
|
||||||
Absortile is under GPL. See https://www.ffonts.net/Absortile.font
|
Absortile is under GPL. See https://www.ffonts.net/Absortile.font
|
||||||
|
Barlow-Regular is under SIL Open Font License. See https://tribby.com/fonts/barlow
|
||||||
Bedstead is under CC0. See below and https://fontlibrary.org/en/font/bedstead
|
Bedstead is under CC0. See below and https://fontlibrary.org/en/font/bedstead
|
||||||
bgrove is under GPL. See http://www.free-fonts-download.com/basic/bloominggrove-font
|
bgrove is under GPL. See http://www.free-fonts-download.com/basic/bloominggrove-font
|
||||||
CheGuevaraTextSans-Regular is under CC0. See https://fonts2u.com/cheguevara-text-sans-regular.font
|
CheGuevaraTextSans-Regular is under CC0. See https://fonts2u.com/cheguevara-text-sans-regular.font
|
||||||
|
|
|
||||||
2
inbox.py
|
|
@ -2449,7 +2449,6 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
maxEmoji: int, translate: {}, unitTest: bool,
|
maxEmoji: int, translate: {}, unitTest: bool,
|
||||||
YTReplacementDomain: str,
|
YTReplacementDomain: str,
|
||||||
showPublishedDateOnly: bool,
|
showPublishedDateOnly: bool,
|
||||||
allowNewsFollowers: bool,
|
|
||||||
maxFollowers: int, allowLocalNetworkAccess: bool,
|
maxFollowers: int, allowLocalNetworkAccess: bool,
|
||||||
peertubeInstances: []) -> None:
|
peertubeInstances: []) -> None:
|
||||||
"""Processes received items and moves them to the appropriate
|
"""Processes received items and moves them to the appropriate
|
||||||
|
|
@ -2739,7 +2738,6 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
queueJson['post'],
|
queueJson['post'],
|
||||||
federationList,
|
federationList,
|
||||||
debug, projectVersion,
|
debug, projectVersion,
|
||||||
allowNewsFollowers,
|
|
||||||
maxFollowers):
|
maxFollowers):
|
||||||
if os.path.isfile(queueFilename):
|
if os.path.isfile(queueFilename):
|
||||||
os.remove(queueFilename)
|
os.remove(queueFilename)
|
||||||
|
|
|
||||||
11
tests.py
|
|
@ -322,11 +322,12 @@ def createServerAlice(path: str, domain: str, port: int,
|
||||||
maxNewswirePosts = 20
|
maxNewswirePosts = 20
|
||||||
dormantMonths = 3
|
dormantMonths = 3
|
||||||
sendThreadsTimeoutMins = 30
|
sendThreadsTimeoutMins = 30
|
||||||
|
maxFollowers = 10
|
||||||
print('Server running: Alice')
|
print('Server running: Alice')
|
||||||
runDaemon(sendThreadsTimeoutMins,
|
runDaemon(sendThreadsTimeoutMins,
|
||||||
dormantMonths, maxNewswirePosts,
|
dormantMonths, maxNewswirePosts,
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess,
|
||||||
2048, False, True, False, False, True, 10, False,
|
2048, False, True, False, False, True, maxFollowers,
|
||||||
0, 100, 1024, 5, False,
|
0, 100, 1024, 5, False,
|
||||||
0, False, 1, False, False, False,
|
0, False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
@ -418,11 +419,12 @@ def createServerBob(path: str, domain: str, port: int,
|
||||||
maxNewswirePosts = 20
|
maxNewswirePosts = 20
|
||||||
dormantMonths = 3
|
dormantMonths = 3
|
||||||
sendThreadsTimeoutMins = 30
|
sendThreadsTimeoutMins = 30
|
||||||
|
maxFollowers = 10
|
||||||
print('Server running: Bob')
|
print('Server running: Bob')
|
||||||
runDaemon(sendThreadsTimeoutMins,
|
runDaemon(sendThreadsTimeoutMins,
|
||||||
dormantMonths, maxNewswirePosts,
|
dormantMonths, maxNewswirePosts,
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess,
|
||||||
2048, False, True, False, False, True, 10, False,
|
2048, False, True, False, False, True, maxFollowers,
|
||||||
0, 100, 1024, 5, False, 0,
|
0, 100, 1024, 5, False, 0,
|
||||||
False, 1, False, False, False,
|
False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
@ -464,11 +466,12 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
|
||||||
maxNewswirePosts = 20
|
maxNewswirePosts = 20
|
||||||
dormantMonths = 3
|
dormantMonths = 3
|
||||||
sendThreadsTimeoutMins = 30
|
sendThreadsTimeoutMins = 30
|
||||||
|
maxFollowers = 10
|
||||||
print('Server running: Eve')
|
print('Server running: Eve')
|
||||||
runDaemon(sendThreadsTimeoutMins,
|
runDaemon(sendThreadsTimeoutMins,
|
||||||
dormantMonths, maxNewswirePosts,
|
dormantMonths, maxNewswirePosts,
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess,
|
||||||
2048, False, True, False, False, True, 10, False,
|
2048, False, True, False, False, True, maxFollowers,
|
||||||
0, 100, 1024, 5, False, 0,
|
0, 100, 1024, 5, False, 0,
|
||||||
False, 1, False, False, False,
|
False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
@ -851,7 +854,7 @@ def testFollowBetweenServers():
|
||||||
clientToServer, federationList,
|
clientToServer, federationList,
|
||||||
aliceSendThreads, alicePostLog,
|
aliceSendThreads, alicePostLog,
|
||||||
aliceCachedWebfingers, alicePersonCache,
|
aliceCachedWebfingers, alicePersonCache,
|
||||||
True, __version__, False)
|
True, __version__)
|
||||||
print('sendResult: ' + str(sendResult))
|
print('sendResult: ' + str(sendResult))
|
||||||
|
|
||||||
for t in range(16):
|
for t in range(16):
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -1,4 +1,17 @@
|
||||||
{
|
{
|
||||||
|
"dropdown-bg-color-hover": "#463b35",
|
||||||
|
"main-fg-color": "#d5c7b7",
|
||||||
|
"column-left-fg-color": "#d5c7b7",
|
||||||
|
"button-text": "#d5c7b7",
|
||||||
|
"button-selected-text": "#d5c7b7",
|
||||||
|
"login-bg-color": "#212e3f",
|
||||||
|
"lines-color": "#b6a188",
|
||||||
|
"day-number": "black",
|
||||||
|
"day-number2": "#bbb",
|
||||||
|
"column-left-header-background": "#8b674e",
|
||||||
|
"column-left-header-color": "#d5c7b7",
|
||||||
|
"post-separator-margin-top": "10px",
|
||||||
|
"post-separator-margin-bottom": "10px",
|
||||||
"newswire-publish-icon": "True",
|
"newswire-publish-icon": "True",
|
||||||
"full-width-timeline-buttons": "False",
|
"full-width-timeline-buttons": "False",
|
||||||
"icons-as-buttons": "False",
|
"icons-as-buttons": "False",
|
||||||
|
|
@ -6,9 +19,9 @@
|
||||||
"publish-button-at-top": "False",
|
"publish-button-at-top": "False",
|
||||||
"banner-height": "25vh",
|
"banner-height": "25vh",
|
||||||
"banner-height-mobile": "10vh",
|
"banner-height-mobile": "10vh",
|
||||||
"newswire-date-color": "yellow",
|
"newswire-date-color": "#ffd974",
|
||||||
"main-bg-color": "#5c4e41",
|
"main-bg-color": "#5c4e41",
|
||||||
"login-bg-color": "#5c4e41",
|
"calendar-bg-color": "#5c4e41",
|
||||||
"options-bg-color": "#5c4e41",
|
"options-bg-color": "#5c4e41",
|
||||||
"post-bg-color": "#5c4e41",
|
"post-bg-color": "#5c4e41",
|
||||||
"timeline-posts-background-color": "#5c4e41",
|
"timeline-posts-background-color": "#5c4e41",
|
||||||
|
|
@ -18,23 +31,24 @@
|
||||||
"link-bg-color": "#5c4e41",
|
"link-bg-color": "#5c4e41",
|
||||||
"main-bg-color-reply": "#5c4e41",
|
"main-bg-color-reply": "#5c4e41",
|
||||||
"main-bg-color-report": "#5c4e41",
|
"main-bg-color-report": "#5c4e41",
|
||||||
"day-number2": "#5c4e41",
|
|
||||||
"border-color": "#463b35",
|
"border-color": "#463b35",
|
||||||
"border-width": "7px",
|
"border-width": "7px",
|
||||||
"border-width-header": "7px",
|
"border-width-header": "7px",
|
||||||
"main-link-color": "#dddddd",
|
"main-link-color": "#d5c7b7",
|
||||||
"main-link-color-hover": "white",
|
"main-link-color-hover": "white",
|
||||||
"options-main-link-color": "#dddddd",
|
"options-main-link-color": "#d5c7b7",
|
||||||
"options-main-link-color-hover": "white",
|
"options-main-link-color-hover": "white",
|
||||||
"title-color": "#dddddd",
|
"title-color": "#d5c7b7",
|
||||||
"main-visited-color": "#dddddd",
|
"main-visited-color": "#d5c7b7",
|
||||||
"options-main-visited-color": "#dddddd",
|
"options-main-visited-color": "#d5c7b7",
|
||||||
"button-background-hover": "#a63b35",
|
"button-background-hover": "#5f3b00",
|
||||||
"publish-button-background": "#463b35",
|
"publish-button-background": "#463b35",
|
||||||
"button-background": "#463b35",
|
"button-background": "#463b35",
|
||||||
"button-selected": "#26201d",
|
"button-selected": "#26201d",
|
||||||
"main-bg-color-dm": "#5c4a40",
|
"main-bg-color-dm": "#5c4a40",
|
||||||
"main-header-color-roles": "#5c4e41",
|
"main-header-color-roles": "#5c4e41",
|
||||||
"dropdown-bg-color": "#504e41",
|
"dropdown-bg-color": "#504e41",
|
||||||
"dropdown-bg-color-hover": "#444"
|
"header-font": "'Barlow-Regular'",
|
||||||
|
"*font-family": "'Barlow-Regular'",
|
||||||
|
"*src": "url('fonts/Barlow-Regular.woff2') format('woff2')"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,25 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
return htmlStr
|
return htmlStr
|
||||||
|
|
||||||
|
|
||||||
|
def getBrokenFavSubstitute() -> str:
|
||||||
|
"""Substitute link used if a favicon is not available
|
||||||
|
"""
|
||||||
|
return " onerror=\"this.onerror=null; this.src=''\""
|
||||||
|
|
||||||
|
|
||||||
|
def getFavicon(url: str) -> str:
|
||||||
|
"""Returns a favicon url from the given article link
|
||||||
|
"""
|
||||||
|
if '://' not in url:
|
||||||
|
return None
|
||||||
|
domain = url.split('://')[1]
|
||||||
|
if '/' not in domain:
|
||||||
|
return url + '/favicon.ico'
|
||||||
|
else:
|
||||||
|
domain = domain.split('/')[0]
|
||||||
|
return url.split('://')[0] + '://' + domain + '/favicon.ico'
|
||||||
|
|
||||||
|
|
||||||
def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
translate: {}, positiveVoting: bool) -> str:
|
translate: {}, positiveVoting: bool) -> str:
|
||||||
"""Converts a newswire dict into html
|
"""Converts a newswire dict into html
|
||||||
|
|
@ -212,6 +231,13 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
|
|
||||||
dateStrLink = dateStr.replace('T', ' ')
|
dateStrLink = dateStr.replace('T', ' ')
|
||||||
dateStrLink = dateStrLink.replace('Z', '')
|
dateStrLink = dateStrLink.replace('Z', '')
|
||||||
|
url = item[1]
|
||||||
|
faviconUrl = getFavicon(url)
|
||||||
|
faviconLink = ''
|
||||||
|
if faviconUrl:
|
||||||
|
faviconLink = \
|
||||||
|
'<img loading="lazy" src="' + faviconUrl + '" ' + \
|
||||||
|
getBrokenFavSubstitute() + '/>'
|
||||||
moderatedItem = item[5]
|
moderatedItem = item[5]
|
||||||
htmlStr += separatorStr
|
htmlStr += separatorStr
|
||||||
if moderatedItem and 'vote:' + nickname in item[2]:
|
if moderatedItem and 'vote:' + nickname in item[2]:
|
||||||
|
|
@ -224,9 +250,10 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
|
|
||||||
title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
|
title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
|
||||||
htmlStr += '<p class="newswireItemVotedOn">' + \
|
htmlStr += '<p class="newswireItemVotedOn">' + \
|
||||||
'<a href="' + item[1] + '" target="_blank" ' + \
|
'<a href="' + url + '" target="_blank" ' + \
|
||||||
'rel="nofollow noopener noreferrer">' + \
|
'rel="nofollow noopener noreferrer">' + \
|
||||||
'<span class="newswireItemVotedOn">' + title + \
|
'<span class="newswireItemVotedOn">' + \
|
||||||
|
faviconLink + title + \
|
||||||
'</span></a>' + totalVotesStr
|
'</span></a>' + totalVotesStr
|
||||||
if moderator:
|
if moderator:
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
|
|
@ -252,9 +279,9 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
|
title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
|
||||||
if moderator and moderatedItem:
|
if moderator and moderatedItem:
|
||||||
htmlStr += '<p class="newswireItemModerated">' + \
|
htmlStr += '<p class="newswireItemModerated">' + \
|
||||||
'<a href="' + item[1] + '" target="_blank" ' + \
|
'<a href="' + url + '" target="_blank" ' + \
|
||||||
'rel="nofollow noopener noreferrer">' + \
|
'rel="nofollow noopener noreferrer">' + \
|
||||||
title + '</a>' + totalVotesStr
|
faviconLink + title + '</a>' + totalVotesStr
|
||||||
htmlStr += ' ' + dateShown
|
htmlStr += ' ' + dateShown
|
||||||
htmlStr += '<a href="/users/' + nickname + \
|
htmlStr += '<a href="/users/' + nickname + \
|
||||||
'/newswirevote=' + dateStrLink + '" ' + \
|
'/newswirevote=' + dateStrLink + '" ' + \
|
||||||
|
|
@ -264,9 +291,9 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
htmlStr += '</p>\n'
|
htmlStr += '</p>\n'
|
||||||
else:
|
else:
|
||||||
htmlStr += '<p class="newswireItem">' + \
|
htmlStr += '<p class="newswireItem">' + \
|
||||||
'<a href="' + item[1] + '" target="_blank" ' + \
|
'<a href="' + url + '" target="_blank" ' + \
|
||||||
'rel="nofollow noopener noreferrer">' + \
|
'rel="nofollow noopener noreferrer">' + \
|
||||||
title + '</a>' + \
|
faviconLink + title + '</a>' + \
|
||||||
totalVotesStr
|
totalVotesStr
|
||||||
htmlStr += ' <span class="newswireDate">'
|
htmlStr += ' <span class="newswireDate">'
|
||||||
htmlStr += dateShown + '</span></p>\n'
|
htmlStr += dateShown + '</span></p>\n'
|
||||||
|
|
|
||||||