Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
22
blog.py
|
@ -10,7 +10,6 @@ import os
|
|||
from datetime import datetime
|
||||
|
||||
from content import replaceEmojiFromTags
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_utils import getPostAttachmentsAsHtml
|
||||
|
@ -392,7 +391,6 @@ def htmlBlogPost(authorized: bool,
|
|||
None, False)
|
||||
|
||||
# show rss links
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
blogStr += '<p class="rssfeed">'
|
||||
|
||||
blogStr += '<a href="' + httpPrefix + '://' + \
|
||||
|
@ -400,14 +398,14 @@ def htmlBlogPost(authorized: bool,
|
|||
blogStr += '<img style="width:3%;min-width:50px" ' + \
|
||||
'loading="lazy" alt="RSS 2.0" ' + \
|
||||
'title="RSS 2.0" src="/' + \
|
||||
iconsPath + '/logorss.png" /></a>'
|
||||
'icons/logorss.png" /></a>'
|
||||
|
||||
# blogStr += '<a href="' + httpPrefix + '://' + \
|
||||
# domainFull + '/blog/' + nickname + '/rss.txt">'
|
||||
# blogStr += '<img style="width:3%;min-width:50px" ' + \
|
||||
# 'loading="lazy" alt="RSS 3.0" ' + \
|
||||
# 'title="RSS 3.0" src="/' + \
|
||||
# iconsPath + '/rss3.png" /></a>'
|
||||
# 'icons/rss3.png" /></a>'
|
||||
|
||||
blogStr += '</p>'
|
||||
|
||||
|
@ -452,7 +450,6 @@ def htmlBlogPage(authorized: bool, session,
|
|||
|
||||
# show previous and next buttons
|
||||
if pageNumber is not None:
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
navigateStr = '<p>'
|
||||
if pageNumber > 1:
|
||||
# show previous button
|
||||
|
@ -460,7 +457,7 @@ def htmlBlogPage(authorized: bool, session,
|
|||
domainFull + '/blog/' + \
|
||||
nickname + '?page=' + str(pageNumber-1) + '">' + \
|
||||
'<img loading="lazy" alt="<" title="<" ' + \
|
||||
'src="/' + iconsPath + \
|
||||
'src="/icons' + \
|
||||
'/prev.png" class="buttonprev"/></a>\n'
|
||||
if len(timelineJson['orderedItems']) >= noOfItems:
|
||||
# show next button
|
||||
|
@ -468,7 +465,7 @@ def htmlBlogPage(authorized: bool, session,
|
|||
domainFull + '/blog/' + nickname + \
|
||||
'?page=' + str(pageNumber + 1) + '">' + \
|
||||
'<img loading="lazy" alt=">" title=">" ' + \
|
||||
'src="/' + iconsPath + \
|
||||
'src="/icons' + \
|
||||
'/prev.png" class="buttonnext"/></a>\n'
|
||||
navigateStr += '</p>'
|
||||
blogStr += navigateStr
|
||||
|
@ -493,13 +490,13 @@ def htmlBlogPage(authorized: bool, session,
|
|||
domainFull + '/blog/' + nickname + '/rss.xml">'
|
||||
blogStr += '<img loading="lazy" alt="RSS 2.0" ' + \
|
||||
'title="RSS 2.0" src="/' + \
|
||||
iconsPath + '/logorss.png" /></a>'
|
||||
'icons/logorss.png" /></a>'
|
||||
|
||||
# blogStr += '<a href="' + httpPrefix + '://' + \
|
||||
# domainFull + '/blog/' + nickname + '/rss.txt">'
|
||||
# blogStr += '<img loading="lazy" alt="RSS 3.0" ' + \
|
||||
# 'title="RSS 3.0" src="/' + \
|
||||
# iconsPath + '/rss3.png" /></a>'
|
||||
# 'icons/rss3.png" /></a>'
|
||||
|
||||
blogStr += '</p>'
|
||||
return blogStr + htmlFooter()
|
||||
|
@ -723,8 +720,6 @@ def htmlEditBlog(mediaInstance: bool, translate: {},
|
|||
print('Edit blog: json not loaded for ' + postFilename)
|
||||
return None
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
editBlogText = '<h1">' + translate['Write your post text below.'] + '</h1>'
|
||||
|
||||
if os.path.isfile(baseDir + '/accounts/newpost.txt'):
|
||||
|
@ -765,8 +760,7 @@ def htmlEditBlog(mediaInstance: bool, translate: {},
|
|||
|
||||
dateAndLocation += \
|
||||
'<p><img loading="lazy" alt="" title="" ' + \
|
||||
'class="emojicalendar" src="/' + \
|
||||
iconsPath + '/calendar.png"/>'
|
||||
'class="emojicalendar" src="/icons/calendar.png"/>'
|
||||
dateAndLocation += \
|
||||
'<label class="labels">' + translate['Date'] + ': </label>'
|
||||
dateAndLocation += '<input type="date" name="eventDate">'
|
||||
|
@ -797,7 +791,7 @@ def htmlEditBlog(mediaInstance: bool, translate: {},
|
|||
|
||||
editBlogForm += ' <div class="dropbtn">'
|
||||
editBlogForm += \
|
||||
' <img loading="lazy" alt="" title="" src="/' + iconsPath + \
|
||||
' <img loading="lazy" alt="" title="" src="/icons' + \
|
||||
'/' + scopeIcon + '"/><b class="scope-desc">' + \
|
||||
scopeDescription + '</b>'
|
||||
editBlogForm += ' </div>'
|
||||
|
|
|
@ -651,6 +651,8 @@ def removeLongWords(content: str, maxWordLength: int,
|
|||
continue
|
||||
elif 'dat:' in wordStr:
|
||||
continue
|
||||
elif 'rad:' in wordStr:
|
||||
continue
|
||||
elif 'hyper:' in wordStr:
|
||||
continue
|
||||
elif 'briar:' in wordStr:
|
||||
|
|
73
daemon.py
|
@ -1856,7 +1856,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
baseDir,
|
||||
httpPrefix,
|
||||
reportPath, None,
|
||||
[optionsActor], None,
|
||||
[optionsActor], None, None,
|
||||
pageNumber,
|
||||
chooserNickname,
|
||||
domain,
|
||||
|
@ -1925,7 +1925,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
baseDir,
|
||||
httpPrefix,
|
||||
reportPath, None, [],
|
||||
postUrl, pageNumber,
|
||||
None, postUrl, pageNumber,
|
||||
chooserNickname,
|
||||
domain,
|
||||
domainFull,
|
||||
|
@ -2392,7 +2392,8 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
# skill search
|
||||
searchStr = searchStr.replace('*', '').strip()
|
||||
skillStr = \
|
||||
htmlSkillsSearch(self.server.cssCache,
|
||||
htmlSkillsSearch(actorStr,
|
||||
self.server.cssCache,
|
||||
self.server.translate,
|
||||
baseDir,
|
||||
httpPrefix,
|
||||
|
@ -3822,9 +3823,8 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
|
||||
# change theme
|
||||
if fields.get('themeDropdown'):
|
||||
setTheme(baseDir,
|
||||
fields['themeDropdown'],
|
||||
domain,
|
||||
self.server.themeName = fields['themeDropdown']
|
||||
setTheme(baseDir, self.server.themeName, domain,
|
||||
allowLocalNetworkAccess)
|
||||
self.server.showPublishAsIcon = \
|
||||
getConfigParam(self.server.baseDir,
|
||||
|
@ -4196,6 +4196,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
'.etag')
|
||||
currTheme = getTheme(baseDir)
|
||||
if currTheme:
|
||||
self.server.themeName = currTheme
|
||||
setTheme(baseDir, currTheme, domain,
|
||||
self.server.allowLocalNetworkAccess)
|
||||
self.server.showPublishAsIcon = \
|
||||
|
@ -4565,12 +4566,14 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if 'image/avif' in self.headers['Accept']:
|
||||
favType = 'image/avif'
|
||||
favFilename = 'favicon.avif'
|
||||
themeName = getConfigParam(baseDir, 'theme')
|
||||
if not themeName:
|
||||
themeName = 'default'
|
||||
if not self.server.themeName:
|
||||
self.themeName = getConfigParam(baseDir, 'theme')
|
||||
if not self.server.themeName:
|
||||
self.server.themeName = 'default'
|
||||
# custom favicon
|
||||
faviconFilename = \
|
||||
baseDir + '/theme/' + themeName + '/icons/' + favFilename
|
||||
baseDir + '/theme/' + self.server.themeName + \
|
||||
'/icons/' + favFilename
|
||||
if not os.path.isfile(faviconFilename):
|
||||
# default favicon
|
||||
faviconFilename = \
|
||||
|
@ -5059,7 +5062,10 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if path.endswith('.png'):
|
||||
mediaStr = path.split('/icons/')[1]
|
||||
if '/' not in mediaStr:
|
||||
theme = 'default'
|
||||
if not self.server.themeName:
|
||||
theme = 'default'
|
||||
else:
|
||||
theme = self.server.themeName
|
||||
iconFilename = mediaStr
|
||||
else:
|
||||
theme = mediaStr.split('/')[0]
|
||||
|
@ -8961,7 +8967,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
httpPrefix,
|
||||
path, inReplyToUrl,
|
||||
replyToList,
|
||||
shareDescription,
|
||||
shareDescription, None,
|
||||
replyPageNumber,
|
||||
nickname, domain,
|
||||
domainFull,
|
||||
|
@ -10538,26 +10544,41 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
# for moderation posts or the dm timeline
|
||||
if '?replydm=' in self.path:
|
||||
inReplyToUrl = self.path.split('?replydm=')[1]
|
||||
inReplyToUrl = urllib.parse.unquote_plus(inReplyToUrl)
|
||||
if '?' in inReplyToUrl:
|
||||
# multiple parameters
|
||||
mentionsList = inReplyToUrl.split('?')
|
||||
for m in mentionsList:
|
||||
if m.startswith('mention='):
|
||||
replyHandle = m.replace('mention=', '')
|
||||
if m.replace('mention=', '') not in replyToList:
|
||||
replyToList.append(m.replace('mention=', ''))
|
||||
if m.startswith('page='):
|
||||
inReplyToUrl = replyHandle
|
||||
if replyHandle not in replyToList:
|
||||
replyToList.append(replyHandle)
|
||||
elif m.startswith('page='):
|
||||
replyPageStr = m.replace('page=', '')
|
||||
if replyPageStr.isdigit():
|
||||
replyPageNumber = int(replyPageStr)
|
||||
# if m.startswith('actor='):
|
||||
# replytoActor = m.replace('actor=', '')
|
||||
inReplyToUrl = mentionsList[0]
|
||||
if inReplyToUrl.startswith('sharedesc:'):
|
||||
elif m.startswith('sharedesc:'):
|
||||
# get the title for the shared item
|
||||
shareDescription = \
|
||||
m.replace('sharedesc:', '').strip()
|
||||
shareDescription = \
|
||||
shareDescription.replace('_', ' ')
|
||||
else:
|
||||
# single parameter
|
||||
if inReplyToUrl.startswith('mention='):
|
||||
replyHandle = inReplyToUrl.replace('mention=', '')
|
||||
inReplyToUrl = replyHandle
|
||||
if replyHandle not in replyToList:
|
||||
replyToList.append(replyHandle)
|
||||
elif inReplyToUrl.startswith('sharedesc:'):
|
||||
# get the title for the shared item
|
||||
shareDescription = \
|
||||
inReplyToUrl.replace('sharedesc:', '')
|
||||
inReplyToUrl.replace('sharedesc:', '').strip()
|
||||
shareDescription = \
|
||||
urllib.parse.unquote_plus(shareDescription.strip())
|
||||
self.path = self.path.split('?replydm=')[0]+'/newdm'
|
||||
shareDescription.replace('_', ' ')
|
||||
|
||||
self.path = self.path.split('?replydm=')[0] + '/newdm'
|
||||
if self.server.debug:
|
||||
print('DEBUG: replydm path ' + self.path)
|
||||
|
||||
|
@ -13050,11 +13071,11 @@ def runDaemon(maxNewswirePosts: int,
|
|||
createNewsInbox(baseDir, domain, port, httpPrefix)
|
||||
|
||||
# set the avatar for the news account
|
||||
themeName = getConfigParam(baseDir, 'theme')
|
||||
if not themeName:
|
||||
themeName = 'default'
|
||||
httpd.themeName = getConfigParam(baseDir, 'theme')
|
||||
if not httpd.themeName:
|
||||
httpd.themeName = 'default'
|
||||
setNewsAvatar(baseDir,
|
||||
themeName,
|
||||
httpd.themeName,
|
||||
httpPrefix,
|
||||
domain,
|
||||
httpd.domainFull)
|
||||
|
|
|
@ -6,373 +6,385 @@
|
|||
<title>gafam</title>
|
||||
<description>zuckerberg apple youtube facebook amazon amazonring microsoft twitter skype degoogled google dotcoms deleteyoutube fascistbook FuckGoogle degoogle ring gafam fuckoffgoogle deletefacebook bigtech</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>places</title>
|
||||
<description>lapaz luanda asunción nouakchott conakry kyiv moscow saipan gibraltar dublin avarua hargeisa delhi niamey chișinău colombo brasília phnompenh mbabane belgrade belmopan pyongyang hannover ulaanbaatar oranjestad gaborone seattle ndjamena singapore kingedwardpoint abidjan nuuk pretoria papeete malé zagreb gitega abudhabi flyingfishcove castries georgetown hagåtña basseterre hamburg kinshasa suva valparaíso athens roseau baku charlotteamalie antananarivo pristina santiago sukhumi berlin funafuti libreville hanoi philipsburg tehran banjul prague andorralavella yerevan portauprince dakar paramaribo tifariti capetown tirana ankara ipswich managua lisbon bishkek amsterdam portonovo santodomingo bangkok bucharest kathmandu aden madrid sanjuan vienna kingston kabul damascus stockholm douglas willemstad thehague panamacity beirut amman newdelhi tórshavn nouméa oslo alofi gustavia paris video cockburntown ottawa stepanakert portofspain honiara asmara nicosia helsinki taipei tegucigalpa tokyo tashkent sarajevo algiers nairobi muscat monaco riyadh lusaka wellington bissau juba mariehamn majuro buenosaires ngerulmud dhaka guatemalacity washington vatican kuwaitcity bern mexicocity bratislava bridgetown tunis manila stanley matautu copenhagen lomé budapest ouagadougou mogadishu freetown victoria brazzaville portmoresby ashgabat kampala elaaiún vilnius bloemfontein sucre london pagopago bradesestate oakland vaduz addis nürnberg naypyidaw khartoum baghdad bandar moroni portvila kingstown reykjavík manama accra windhoek nukualofa tbilisi canberra quito maputo cetinje putrajaya ramallah bogotá dodoma harare havana warsaw valletta ljubljana bamako kualalumpur podgorica rabat cotonou plymouth seoul dushanbe bangui westisland tskhinvali palikir caracas jamestown rome munich sãotomé jakarta daressalaam sansalvador apia essex yaren cairo jerusalem brussels kigali southtarawa beijing minsk montevideo vientiane maseru hamilton doha tripoli portlouis lima adamstown abuja lilongwe nassau lobamba nyc montreal dili riga lesbos monrovia nursultan sanjosé marigot islamabad malabo tallinn sahara thimphu yaoundé praia bujumbura sofia skopje</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>food</title>
|
||||
<description>vitamind bolognese sourdough vegan soysauce bakery baking foodwaste aroma bagel batter beans beer biscuit bread broth burger butter cake candy caramel caviar cheese chili chocolate cider cobbler cocoa coffee cookie cream croissant crumble cuisine curd dessert dish drink eggs entree filet fish flour foie gras food glaze grill hamburger juice ketchup kitchen lard liquor margarine marinade mayo mayonnaise meat milk mousse muffin mushroom noodle nuts oil olive omelette pan pasta paste pastry pie pizza plate pot poutine pudding raclette recipe rice salad salsa sandwich sauce seasoning skillet soda soup soy spice steak stew syrup tartar taste tea toast vinegar waffle wheat wine wok yeast yogurt cookery cooking</description>
|
||||
<description>vitamind cake margarine dessert salsa caviar cookery food skillet liquor milk bolognese recipe yeast plate waffle biscuit glaze omelette filet pastry wine hamburger juice sourdough nuts gras toast broth batter ketchup seasoning mayo soup pan mayonnaise vegan dish spice bakery cooking yogurt spotify crumble cider butter cobbler steak pizza soda aroma oil flour cream pie cuisine tartar tea marinade mushroom entree bread salad beans syrup cookie curd soysauce pudding beer baking fish foodwaste wheat pot stew chocolate paste wok olive burger candy kitchen coffee bagel taste meat noodle raclette caramel rice eggs grill poutine lard croissant pasta cheese drink muffin foie sauce soy cocoa sandwich mousse chili vinegar</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>countries</title>
|
||||
<description>romania burma lithuania solomon chile fiji tajikistan benin paraguay senegal ukraine italy brunei nicaragua guyana zambia iceland morocco netherlands swaziland bosnian suriname elsalvador russia samoa czech belarus hayabusa2 kyrgyzstan uk sanmarino catalonia panama japan venezuela gambia kuwait barbados papua greece switzerland uae nigeria usa angola honduras djibouti laos sierraleone cambodia vietnam seychelles marshall kazakhstan estonia tonga stlucia burundi bangladesh egypt mali congo us jordan grenada israel algeria ghana bosnia russian eritrea bhutan hungary saudi slovenia bahamas australia kiribati togo koreanorth poland malawi capeverde armenia american bahrain mozambique southsudan syria micronesia maldives iran sweden ethiopia cuba liberia canada burkina somalia scotland vaticancity easttimor austria turkey yemen Bolivia denmark madagascar finland philippines ivorycoast haiti ecuador Portugal azerbaijan spain albania afghanistan europe mauritania dominica thailand belize macedonia montenegro qatar mongolia costarica latvia uzbekistan ireland iraq malaysia mexico mauritius oman chad nz georgia zimbabwe france serbia lesotho tunisia argentina cameroon namibia sudan indonesia colombia tuvalu turkmenistan tanzania germany norway comoros guatemala kosovo andorra wales pakistan belgium china antigua koreasouth newzealand rwanda luxembourg libya nauru moldova palau taiwan kenya trinidad eu botswana jamaica vanuatu cyprus malta niger unitedstates myanmar saintvincent guinea nepal peru uganda uruguay india lebanon southafrica croatia europeanunion bolivia chinese dominican srilanka bulgaria slovakia gabon stkitts liechtenstein brazil</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>cycling</title>
|
||||
<description>bicycle bike Snowbike cycling</description>
|
||||
<description>bicycle cycling bike Snowbike</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>phones</title>
|
||||
<description>mobileapp fdroid plasmamobile smartphone pinephone mobile ubuntutouch osmand vodafone postmarketos</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>software</title>
|
||||
<description>app freedombox windows libre nginx Framasoft drm kubernetes jami FuckOffZoom docker freesoftware foss nextcloud wechat ikiwiki outreachy selfhosting lyft nitter opensource diaspora cabal conferencing accessibility owncast emacs gemini email chatapps floss deltachat bittorrent zoom gpl FriendofGNOME obnam cryptpad OwnStream mumble grsync irssi mutt backup apps ffmpeg lemmy OSM win10 jitsi libreoffice dino openoffice</description>
|
||||
<description>app freedombox windows libre nginx Framasoft drm kubernetes jami FuckOffZoom docker freesoftware gimp foss nextcloud wechat ikiwiki outreachy selfhosting lyft nitter opensource diaspora cabal conferencing accessibility owncast emacs gemini email chatapps floss deltachat bittorrent zoom gpl FriendofGNOME obnam cryptpad OwnStream mumble grsync irssi mutt backup apps ffmpeg lemmy OSM win10 jitsi rsync libreoffice dino openoffice</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>security</title>
|
||||
<description>password encrypt password cryptography infosec gchq cryptowars UseAMaskUseTor cyberattack security tor vpn openssh openssl crypto opsec nsa protonvpn nitrokey openpgp gpg cybersecurity signal noscript openvpn</description>
|
||||
<description>encrypt password cryptography infosec gchq cryptowars UseAMaskUseTor cyberattack security tor vpn openssh openssl crypto opsec nsa protonvpn yubikey nitrokey openpgp gpgtools gpg cybersecurity signal noscript openvpn</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>countries</title>
|
||||
<description>wales scotland eu europe europeanunion chinese afghanistan albania algeria andorra angola antigua argentina armenia australia austria azerbaijan bahamas bahrain bangladesh barbados belarus belgium belize benin bhutan bolivia bosnia botswana brazil brunei bulgaria burkina burundi cambodia cameroon canada capeverde chad chile china colombia comoros congo costarica croatia cuba cyprus czech denmark djibouti dominica dominican easttimor ecuador egypt elsalvador guinea eritrea estonia ethiopia fiji finland france gabon gambia georgia germany ghana greece grenada guatemala guinea guyana haiti honduras hungary iceland india indonesia iran iraq ireland israel italy ivorycoast jamaica japan jordan kazakhstan kenya kiribati koreanorth koreasouth kosovo kuwait kyrgyzstan laos latvia lebanon lesotho liberia libya liechtenstein lithuania luxembourg macedonia madagascar malawi malaysia maldives mali malta marshall mauritania mauritius mexico micronesia moldova monaco mongolia montenegro morocco mozambique myanmar burma namibia nauru nepal netherlands newzealand nz nicaragua niger nigeria norway oman pakistan palau panama papua paraguay peru philippines poland Portugal qatar romania russian rwanda stkitts stlucia saintvincent samoa sanmarino saudi senegal serbia seychelles sierraleone singapore slovakia slovenia solomon somalia southafrica sudan spain srilanka sudan suriname swaziland sweden switzerland syria taiwan tajikistan tanzania thailand togo tonga trinidad tunisia turkey turkmenistan tuvalu uganda ukraine uae uk usa us unitedstates uruguay uzbekistan vanuatu vaticancity venezuela vietnam yemen zambia zimbabwe</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>politics</title>
|
||||
<description>cia wageslavery liberation fascism rojava leftists Socialism ukpol freedom anarchism DefundThePolice bjp election generalstrike digitalfreedom hatespeech fascists peerproduction corporations commons wageslave softwarefreedom socialecology politics nzpol totalitarianism TyskySour Labour decolonization surveillance elections borisjohnson mutuality whitehouse decolonize decenterwhiteness ChineseAppBan modi surveillancecapitalism leftist Revolution ukpolitics migration mutualaid fascist uselection</description>
|
||||
<description>mayday cia wageslavery liberation fascism rojava leftists Socialism ukpol freedom abolitionnow anarchism DefundThePolice bjp election generalstrike digitalfreedom hatespeech fascists peerproduction corporations commons wageslave RemoveThePolice softwarefreedom socialecology politics nzpol brexit totalitarianism TyskySour Labour decolonization surveillance elections borisjohnson mutuality whitehouse decolonize decenterwhiteness ChineseAppBan modi surveillancecapitalism leftist Revolution ukpolitics migration mutualaid fascist uselection</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>conferences</title>
|
||||
<description>schmoocon defcon C3 fossdem debconf talk FreedomBoxSummit summit minidebconf flossevent conf rC3 flossconf conference</description>
|
||||
<description>debconf talk fossdem FreedomBoxSummit schmoocon summit minidebconf defcon flossevent conf rC3 conference flossconf C3</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>photos</title>
|
||||
<description>nikon photography photo tokyocameraclub photoshop camera picture</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>programming</title>
|
||||
<description>programming css rustlang typescript adventofcode scripting fedidev sourcecode django tuskydev lisp javascript code elisp html rust clojurescript racket python</description>
|
||||
<description>git forge programming css rustlang typescript adventofcode scripting fedidev sourcecode django tuskydev lisp javascript code elisp html rust clojurescript racket python</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>activitypub</title>
|
||||
<description>activitypub pleroma fedilab mastotips misskey siskin followers pixelfed monal tusky peertubers feditips fedizens epicyon mastomagic pixeldev fediverse mastodon peertube mobilizon</description>
|
||||
<description>activitypub pleroma PeerTube fedilab mastotips misskey siskin followers pixelfed monal tusky peertubers feditips fedizens epicyon mastomagic pixeldev fediverse mastodon peertube mobilizon</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>news</title>
|
||||
<description>news</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>games</title>
|
||||
<description>mud dnd rpg minetest game chess minecraft TetrisGore gaming</description>
|
||||
<description>minecraft chess mud game TetrisGore gaming rpg minetest dnd</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>music</title>
|
||||
<description>punk rap hiphop ipod rave bandcamp musicians mp3 thecure vaporwave dubstep synthwave experimentalmusic dj newwave dorkwave producing NowPlaying libremusicproduction MusicAdvent synth music fediversemusic cyberpunkmusic BandcampFriday</description>
|
||||
<description>punk bandcamp musicians ipod rap mp3 thecure vaporwave dubstep synthwave rave hiphop experimentalmusic dj newwave dorkwave producing NowPlaying nowplaying libremusicproduction MusicAdvent synth music fediversemusic cyberpunkmusic BandcampFriday</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>retro</title>
|
||||
<description>A500 atarist commodore teletext 8bit atari floppy retrocomputing C64 80s microcomputing z80 retro amiga bbcmicro microcomputer</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>indymedia</title>
|
||||
<description>visionontv indymediaback omn 4opens</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>places</title>
|
||||
<description>hannover hamburg ipswich oakland nürnberg munich essex minsk nyc montreal lesbos sahara abidjan abudhabi abuja accra adamstown addis aden algiers alofi amman amsterdam thehague andorralavella ankara antananarivo apia ashgabat asmara asunción athens avarua baghdad baku bamako bandar bangkok bangui banjul basseterre beijing beirut belgrade belmopan berlin bern bishkek bissau bloemfontein capetown pretoria bogotá bradesestate plymouth brasília bratislava brazzaville bridgetown brussels bucharest budapest buenosaires cairo canberra caracas castries cetinje podgorica charlotteamalie chișinău cockburntown colombo conakry copenhagen cotonou portonovo dakar damascus daressalaam dodoma dhaka dili djibouti doha douglas dublin dushanbe elaaiún tifariti flyingfishcove freetown funafuti gaborone georgetown gibraltar gitega bujumbura guatemalacity gustavia hagåtña hamilton hanoi harare hargeisa havana helsinki honiara islamabad jakarta jamestown jerusalem ramallah juba kabul kampala kathmandu khartoum kigali kingedwardpoint kingston kingston kingstown kinshasa kualalumpur putrajaya kuwaitcity kyiv lapaz sucre libreville lilongwe lima lisbon ljubljana lobamba mbabane lomé london luanda lusaka luxembourg madrid majuro malabo malé managua manama manila maputo mariehamn marigot maseru matautu mexicocity minsk mogadishu monaco monrovia montevideo moroni moscow muscat nairobi nassau naypyidaw ndjamena newdelhi delhi ngerulmud niamey nicosia nouakchott nouméa nukualofa nursultan nuuk oranjestad oslo ottawa ouagadougou pagopago palikir panamacity papeete paramaribo paris philipsburg phnompenh portlouis portmoresby portvila portauprince portofspain prague praia pristina pyongyang quito rabat reykjavík riga riyadh rome roseau saipan sanjosé sanjuan sanmarino sansalvador santiago valparaíso santodomingo sãotomé sarajevo seoul singapore skopje sofia southtarawa stanley stepanakert stockholm sukhumi suva taipei tallinn tashkent tbilisi tegucigalpa tehran thimphu tirana tokyo tórshavn tripoli tskhinvali tunis ulaanbaatar vaduz valletta vatican victoria vienna vientiane vilnius warsaw washington wellington westisland willemstad windhoek yaoundé yaren yerevan zagreb</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>questions</title>
|
||||
<description>askmastodon askfosstodon</description>
|
||||
<description>askmastodon askfosstodon ask</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>birds</title>
|
||||
<description>RainbowBeeEater bird</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>ethics</title>
|
||||
<description>digitalethics ethics ethical</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>internet</title>
|
||||
<description>cyberspace www w3c redecentralize rtmp decentralization decentralize w3c torrent data icann dns openstandards oauth SmallWeb xmpp semanticweb ntp socialnetworks jabber decentralized darknet cookies darkweb server browser p2p web twitch domain browsers openculture internet openweb socialweb cloudflare</description>
|
||||
<description>redecentralize wikipedia rtmp decentralization decentralize w3c torrent data router icann dns openstandards oauth SmallWeb xmpp semanticweb ntp socialnetworks jabber decentralized darknet cookies darkweb server browser p2p www ilovewikipedia web twitch domain browsers decentralizeit openculture cyberspace internet openweb socialweb cloudflare</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>retro</title>
|
||||
<description>microcomputer microcomputing commodore C64 A500 8bit retro bbcmicro atari atarist teletext floppydisk retrocomputing 80s z80 amiga</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>years</title>
|
||||
<description>year Year2020</description>
|
||||
<description>Year2020 year</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>month</title>
|
||||
<description>month january feburary march april may june july august september october november december</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>pets</title>
|
||||
<description>dailycatpic DailyCatVid dogsofmastodon catofmastodon catbehaviour cats kittens dog caturday catsofmastodon cute dogs cat catcontent pet</description>
|
||||
<description>catofmastodon catbehaviour dogsofmastodon cats kittens pet dog caturday catsofmastodon cute dogs cat catcontent</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>podcasts</title>
|
||||
<description>IntergalacticWasabiHour podcast tilderadio</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>events</title>
|
||||
<description>meetup live followfriday livestream festival concert InternationalCheetahDay</description>
|
||||
<description>week day Day live followfriday concert festival livestream InternationalCheetahDay meetup</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>hardware</title>
|
||||
<description>cyberdeck keyboards modem keyboard cybredeck lenovo arm thinkpad</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>seasons</title>
|
||||
<description>spring autumn winter summer</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>gender</title>
|
||||
<description>transwomen transcrowdfund female trans women estradiol woman transrights</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>hardware</title>
|
||||
<description>keyboards modem keyboard cyberdeck cybredeck thinkpad lenovo arm</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>linux</title>
|
||||
<description>mobian openwrt distros wireguard linuxaudio gtk debian trisquel gentoo archlinux ubuntu xubuntu fedora systemd distro qubesos linux btrfs</description>
|
||||
<description>mobian openwrt distros wireguard linuxaudio gtk debian trisquel ubuntu xubuntu fedora gentoo systemd distro qubesos linux btrfs archlinux</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>fiction</title>
|
||||
<description>cyberpunk thehobbit fiction</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>audio</title>
|
||||
<description>audioproduction audiofeedback</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>bots</title>
|
||||
<description>bot</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>climate</title>
|
||||
<description>clouds weather climate</description>
|
||||
<description>clouds climate weather</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>books</title>
|
||||
<description>earthsea ebooks ebook epub book</description>
|
||||
<description>earthsea ebooks book ebook epub</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>scifi</title>
|
||||
<description>startrek starwars cyberpunk</description>
|
||||
<description>startrek starwars</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>pandemic</title>
|
||||
<description>CoronaWarnApp facemasks vaccines vaccine covid Lockdown codid19 COVID19 COVID</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>religion</title>
|
||||
<description>pagan</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>science</title>
|
||||
<description>supercollider paleontology</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>art</title>
|
||||
<description>art krita adultcolouring collage MastoArt digitalart mandala concretepoetry artwithopensource poetry</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>nature</title>
|
||||
<description>trees nature</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>fashion</title>
|
||||
<description>bras fashion patches</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>art</title>
|
||||
<description>krita adultcolouring collage MastoArt digitalart mandala concretepoetry artwithopensource</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>techbros</title>
|
||||
<description>hackernews reddit</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>gardening</title>
|
||||
<description>florespondence DailyFlowers flowers gardening</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>moderation</title>
|
||||
<description>fedblock</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>election</title>
|
||||
<description>voted vote election</description>
|
||||
<description>voted vote</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>#music</title>
|
||||
<description>trance</description>
|
||||
<link/>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>activism</title>
|
||||
<description>fsfe xr eff openrightsgroup fsf conservancy</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>crafts</title>
|
||||
<description>knitting makers jewelry quilt</description>
|
||||
<description>knitting jewelry makers quilt</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>gardening</title>
|
||||
<description>DailyFlowers flowers gardening</description>
|
||||
<title>radio</title>
|
||||
<description>vantaradio radio hamradio radiobroadcasting radiobroadcast</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>education</title>
|
||||
<description>education tutorial</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>seasons</title>
|
||||
<description>winter summer spring autumn</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>radio</title>
|
||||
<description>hamradio radio</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>microcontroller</title>
|
||||
<description>microcontroller arduino esp32</description>
|
||||
<description>microcontroller arduino</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>comedy</title>
|
||||
<description>satire irony</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>privacy</title>
|
||||
<description>privacymatters dataprivacy privacy</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>environment</title>
|
||||
<description>climatechange climatechaos</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>#software</title>
|
||||
<description>flatpak</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>scotland</title>
|
||||
<description>highlands</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>microcontrollers</title>
|
||||
<description>esp8266 esp32</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>health</title>
|
||||
<description>meds</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>astronomy</title>
|
||||
<description>moon milkyway</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>travel</title>
|
||||
<description>travel taxi</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>help</title>
|
||||
<description>help</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>funding</title>
|
||||
<description>patreon</description>
|
||||
<link/>
|
||||
<pubDate>Sat, 05 Dec 2020 13:30:17 UT</pubDate>
|
||||
<pubDate>Sun, 06 Dec 2020 11:33:50 UT</pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
21
epicyon.py
|
@ -326,12 +326,12 @@ parser.add_argument('--image', '--background', dest='backgroundImage',
|
|||
parser.add_argument('--archive', dest='archive', type=str,
|
||||
default=None,
|
||||
help='Archive old files to the given directory')
|
||||
parser.add_argument('--archiveweeks', dest='archiveWeeks', type=str,
|
||||
default=None,
|
||||
parser.add_argument('--archiveweeks', dest='archiveWeeks', type=int,
|
||||
default=4,
|
||||
help='Specify the number of weeks after which ' +
|
||||
'data will be archived')
|
||||
parser.add_argument('--maxposts', dest='archiveMaxPosts', type=str,
|
||||
default=None,
|
||||
'media will be archived')
|
||||
parser.add_argument('--maxposts', dest='archiveMaxPosts', type=int,
|
||||
default=32000,
|
||||
help='Maximum number of posts in in/outbox')
|
||||
parser.add_argument('--minimumvotes', dest='minimumvotes', type=int,
|
||||
default=1,
|
||||
|
@ -1574,13 +1574,6 @@ if args.changepassword:
|
|||
print('Passwords file not found')
|
||||
sys.exit()
|
||||
|
||||
archiveWeeks = 4
|
||||
if args.archiveWeeks:
|
||||
archiveWeeks = args.archiveWeeks
|
||||
archiveMaxPosts = 32000
|
||||
if args.archiveMaxPosts:
|
||||
archiveMaxPosts = args.archiveMaxPosts
|
||||
|
||||
if args.archive:
|
||||
if args.archive.lower().endswith('null') or \
|
||||
args.archive.lower().endswith('delete') or \
|
||||
|
@ -1589,8 +1582,8 @@ if args.archive:
|
|||
print('Archiving with deletion of old posts...')
|
||||
else:
|
||||
print('Archiving to ' + args.archive + '...')
|
||||
archiveMedia(baseDir, args.archive, archiveWeeks)
|
||||
archivePosts(baseDir, httpPrefix, args.archive, {}, archiveMaxPosts)
|
||||
archiveMedia(baseDir, args.archive, args.archiveWeeks)
|
||||
archivePosts(baseDir, httpPrefix, args.archive, {}, args.archiveMaxPosts)
|
||||
print('Archiving complete')
|
||||
sys.exit()
|
||||
|
||||
|
|
3
inbox.py
|
@ -58,7 +58,6 @@ from posts import isMuted
|
|||
from posts import isImageMedia
|
||||
from posts import sendSignedJson
|
||||
from posts import sendToFollowersThread
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_post import individualPostAsHtml
|
||||
from question import questionUpdateVotes
|
||||
from media import replaceYouTube
|
||||
|
@ -173,7 +172,7 @@ def inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
|||
if boxname != 'tlevents' and boxname != 'outbox':
|
||||
boxname = 'inbox'
|
||||
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||
getIconsWebPath(baseDir), translate, pageNumber,
|
||||
translate, pageNumber,
|
||||
baseDir, session, cachedWebfingers, personCache,
|
||||
nickname, domain, port, postJsonObject,
|
||||
avatarUrl, True, allowDeletion,
|
||||
|
|
5
media.py
|
@ -199,9 +199,12 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int,
|
|||
def archiveMedia(baseDir: str, archiveDirectory: str, maxWeeks=4) -> None:
|
||||
"""Any media older than the given number of weeks gets archived
|
||||
"""
|
||||
if maxWeeks == 0:
|
||||
return
|
||||
|
||||
currTime = datetime.datetime.utcnow()
|
||||
weeksSinceEpoch = int((currTime - datetime.datetime(1970, 1, 1)).days/7)
|
||||
minWeek = weeksSinceEpoch-maxWeeks
|
||||
minWeek = weeksSinceEpoch - maxWeeks
|
||||
|
||||
if archiveDirectory:
|
||||
if not os.path.isdir(archiveDirectory):
|
||||
|
|
11
newswire.py
|
@ -154,14 +154,6 @@ def parseFeedDate(pubDate: str) -> str:
|
|||
continue
|
||||
if ',' not in pubDate and ',' in dateFormat:
|
||||
continue
|
||||
if '-' in pubDate and '-' not in dateFormat:
|
||||
continue
|
||||
if '-' not in pubDate and '-' in dateFormat:
|
||||
continue
|
||||
if 'T' in pubDate and 'T' not in dateFormat:
|
||||
continue
|
||||
if 'T' not in pubDate and 'T' in dateFormat:
|
||||
continue
|
||||
if 'Z' in pubDate and 'Z' not in dateFormat:
|
||||
continue
|
||||
if 'Z' not in pubDate and 'Z' in dateFormat:
|
||||
|
@ -267,10 +259,13 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
|
|||
if '<item>' not in xmlStr:
|
||||
return {}
|
||||
result = {}
|
||||
|
||||
# is this an rss feed containing hashtag categories?
|
||||
if '<title>#categories</title>' in xmlStr:
|
||||
xml2StrToHashtagCategories(baseDir, xmlStr,
|
||||
maxCategoriesFeedItemSizeKb)
|
||||
return {}
|
||||
|
||||
rssItems = xmlStr.split('<item>')
|
||||
postCtr = 0
|
||||
maxBytes = maxFeedItemSizeKb * 1024
|
||||
|
|
4
posts.py
|
@ -3144,9 +3144,13 @@ def archivePosts(baseDir: str, httpPrefix: str, archiveDir: str,
|
|||
maxPostsInBox=32000) -> None:
|
||||
"""Archives posts for all accounts
|
||||
"""
|
||||
if maxPostsInBox == 0:
|
||||
return
|
||||
|
||||
if archiveDir:
|
||||
if not os.path.isdir(archiveDir):
|
||||
os.mkdir(archiveDir)
|
||||
|
||||
if archiveDir:
|
||||
if not os.path.isdir(archiveDir + '/accounts'):
|
||||
os.mkdir(archiveDir + '/accounts')
|
||||
|
|
26
tests.py
|
@ -547,6 +547,20 @@ def testPostMessageBetweenServers():
|
|||
break
|
||||
time.sleep(1)
|
||||
|
||||
# check that a news account exists
|
||||
newsActorDir = aliceDir + '/accounts/news@' + aliceDomain
|
||||
print("newsActorDir: " + newsActorDir)
|
||||
assert os.path.isdir(newsActorDir)
|
||||
newsActorFile = newsActorDir + '.json'
|
||||
assert os.path.isfile(newsActorFile)
|
||||
newsActorJson = loadJson(newsActorFile)
|
||||
assert newsActorJson
|
||||
assert newsActorJson.get("id")
|
||||
# check the id of the news actor
|
||||
print('News actor Id: ' + newsActorJson["id"])
|
||||
assert (newsActorJson["id"] ==
|
||||
httpPrefix + '://' + aliceAddress + '/users/news')
|
||||
|
||||
# Image attachment created
|
||||
assert len([name for name in os.listdir(mediaPath)
|
||||
if os.path.isfile(os.path.join(mediaPath, name))]) > 0
|
||||
|
@ -1747,6 +1761,13 @@ def testWebLinks():
|
|||
'<p>Test1 test2 '
|
||||
'#YetAnotherExcessivelyLongwindedAndBorin\ngHashtag</p>')
|
||||
|
||||
exampleText = \
|
||||
"<p>Don't remove a p2p link " + \
|
||||
"rad:git:hwd1yrerc3mcgn8ga9rho3dqi4w33nep7kxmqezss4topyfgmexihp" + \
|
||||
"33xcw</p>"
|
||||
resultText = removeLongWords(addWebLinks(exampleText), 40, [])
|
||||
assert resultText == exampleText
|
||||
|
||||
|
||||
def testAddEmoji():
|
||||
print('testAddEmoji')
|
||||
|
@ -2396,6 +2417,11 @@ def testFirstParagraphFromString():
|
|||
|
||||
def testParseFeedDate():
|
||||
print('testParseFeedDate')
|
||||
|
||||
pubDate = "Tue, 08 Dec 2020 06:24:38 -0600"
|
||||
publishedDate = parseFeedDate(pubDate)
|
||||
assert publishedDate == "2020-12-08 12:24:38+00:00"
|
||||
|
||||
pubDate = "2020-08-27T16:12:34+00:00"
|
||||
publishedDate = parseFeedDate(pubDate)
|
||||
assert publishedDate == "2020-08-27 16:12:34+00:00"
|
||||
|
|
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 92 KiB |
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "حدد رمز التحرير لإضافة موجز ويب لـ RSS",
|
||||
"Select the edit icon to add web links": "حدد رمز التحرير لإضافة روابط الويب",
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed",
|
||||
"Ask about a shared item.": "اسأل عن عنصر مشترك."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Seleccioneu la icona d'edició per afegir canals RSS",
|
||||
"Select the edit icon to add web links": "Seleccioneu la icona d'edició per afegir enllaços web",
|
||||
"Hashtag Categories RSS Feed": "Feed RSS de categories de hashtag"
|
||||
"Hashtag Categories RSS Feed": "Feed RSS de categories de hashtag",
|
||||
"Ask about a shared item.": "Pregunteu sobre un element compartit."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Dewiswch yr eicon golygu i ychwanegu porthwyr RSS",
|
||||
"Select the edit icon to add web links": "Dewiswch yr eicon golygu i ychwanegu dolenni gwe",
|
||||
"Hashtag Categories RSS Feed": "Categorïau Hashtag RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Categorïau Hashtag RSS Feed",
|
||||
"Ask about a shared item.": "Gofynnwch am eitem a rennir."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Wählen Sie das Bearbeitungssymbol, um RSS-Feeds hinzuzufügen",
|
||||
"Select the edit icon to add web links": "Wählen Sie das Bearbeitungssymbol, um Weblinks hinzuzufügen",
|
||||
"Hashtag Categories RSS Feed": "Hashtag Kategorien RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Hashtag Kategorien RSS Feed",
|
||||
"Ask about a shared item.": "Fragen Sie nach einem gemeinsamen Artikel."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Select the edit icon to add RSS feeds",
|
||||
"Select the edit icon to add web links": "Select the edit icon to add web links",
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed",
|
||||
"Ask about a shared item.": "Ask about a shared item."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Seleccione el icono de edición para agregar fuentes RSS",
|
||||
"Select the edit icon to add web links": "Seleccione el icono de edición para agregar enlaces web",
|
||||
"Hashtag Categories RSS Feed": "Feed RSS de categorías de hashtags"
|
||||
"Hashtag Categories RSS Feed": "Feed RSS de categorías de hashtags",
|
||||
"Ask about a shared item.": "Pregunte por un elemento compartido."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Sélectionnez l'icône d'édition pour ajouter des flux RSS",
|
||||
"Select the edit icon to add web links": "Sélectionnez l'icône de modification pour ajouter des liens Web",
|
||||
"Hashtag Categories RSS Feed": "Flux RSS des catégories Hashtag"
|
||||
"Hashtag Categories RSS Feed": "Flux RSS des catégories Hashtag",
|
||||
"Ask about a shared item.": "Renseignez-vous sur un élément partagé."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Roghnaigh an deilbhín eagar chun fothaí RSS a chur leis",
|
||||
"Select the edit icon to add web links": "Roghnaigh an deilbhín eagar chun naisc ghréasáin a chur leis",
|
||||
"Hashtag Categories RSS Feed": "Catagóirí Hashtag RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Catagóirí Hashtag RSS Feed",
|
||||
"Ask about a shared item.": "Fiafraigh faoi earra roinnte."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "RSS फ़ीड जोड़ने के लिए संपादन आइकन का चयन करें",
|
||||
"Select the edit icon to add web links": "वेब लिंक जोड़ने के लिए संपादन आइकन का चयन करें",
|
||||
"Hashtag Categories RSS Feed": "हैशटैग श्रेणियाँ आरएसएस फ़ीड"
|
||||
"Hashtag Categories RSS Feed": "हैशटैग श्रेणियाँ आरएसएस फ़ीड",
|
||||
"Ask about a shared item.": "एक साझा आइटम के बारे में पूछें।"
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Seleziona l'icona di modifica per aggiungere feed RSS",
|
||||
"Select the edit icon to add web links": "Seleziona l'icona di modifica per aggiungere link web",
|
||||
"Hashtag Categories RSS Feed": "Feed RSS delle categorie hashtag"
|
||||
"Hashtag Categories RSS Feed": "Feed RSS delle categorie hashtag",
|
||||
"Ask about a shared item.": "Chiedi informazioni su un elemento condiviso."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "編集アイコンを選択してRSSフィードを追加します",
|
||||
"Select the edit icon to add web links": "編集アイコンを選択してWebリンクを追加します",
|
||||
"Hashtag Categories RSS Feed": "ハッシュタグカテゴリRSSフィード"
|
||||
"Hashtag Categories RSS Feed": "ハッシュタグカテゴリRSSフィード",
|
||||
"Ask about a shared item.": "共有アイテムについて質問します。"
|
||||
}
|
||||
|
|
|
@ -334,5 +334,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Select the edit icon to add RSS feeds",
|
||||
"Select the edit icon to add web links": "Select the edit icon to add web links",
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed"
|
||||
"Hashtag Categories RSS Feed": "Hashtag Categories RSS Feed",
|
||||
"Ask about a shared item.": "Ask about a shared item."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Selecione o ícone de edição para adicionar feeds RSS",
|
||||
"Select the edit icon to add web links": "Selecione o ícone de edição para adicionar links da web",
|
||||
"Hashtag Categories RSS Feed": "Feed RSS das categorias de hashtag"
|
||||
"Hashtag Categories RSS Feed": "Feed RSS das categorias de hashtag",
|
||||
"Ask about a shared item.": "Pergunte sobre um item compartilhado."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "Щелкните значок редактирования, чтобы добавить RSS-каналы",
|
||||
"Select the edit icon to add web links": "Щелкните значок редактирования, чтобы добавить веб-ссылки",
|
||||
"Hashtag Categories RSS Feed": "RSS-канал категорий хэштегов"
|
||||
"Hashtag Categories RSS Feed": "RSS-канал категорий хэштегов",
|
||||
"Ask about a shared item.": "Спросите об общем элементе."
|
||||
}
|
||||
|
|
|
@ -338,5 +338,6 @@
|
|||
"Debian": "Debian",
|
||||
"Select the edit icon to add RSS feeds": "选择编辑图标以添加RSS feed",
|
||||
"Select the edit icon to add web links": "选择编辑图标以添加Web链接",
|
||||
"Hashtag Categories RSS Feed": "标签类别RSS提要"
|
||||
"Hashtag Categories RSS Feed": "标签类别RSS提要",
|
||||
"Ask about a shared item.": "询问共享项目。"
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ from happening import getCalendarEvents
|
|||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_utils import getAltPath
|
||||
from webapp_utils import getIconsWebPath
|
||||
|
||||
|
||||
def htmlCalendarDeleteConfirm(cssCache: {}, translate: {}, baseDir: str,
|
||||
|
@ -122,8 +121,6 @@ def htmlCalendarDay(cssCache: {}, translate: {},
|
|||
calendarStr += '</caption>\n'
|
||||
calendarStr += '<tbody>\n'
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
if dayEvents:
|
||||
for eventPost in dayEvents:
|
||||
eventTime = None
|
||||
|
@ -156,7 +153,7 @@ def htmlCalendarDay(cssCache: {}, translate: {},
|
|||
'">\n<img class="calendardayicon" loading="lazy" alt="' + \
|
||||
translate['Delete this event'] + ' |" title="' + \
|
||||
translate['Delete this event'] + '" src="/' + \
|
||||
iconsPath + '/delete.png" /></a></td>\n'
|
||||
'icons/delete.png" /></a></td>\n'
|
||||
|
||||
if eventTime and eventDescription and eventPlace:
|
||||
calendarStr += \
|
||||
|
@ -201,7 +198,6 @@ def htmlCalendar(cssCache: {}, translate: {},
|
|||
httpPrefix: str, domainFull: str) -> str:
|
||||
"""Show the calendar for a person
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
domain = domainFull
|
||||
if ':' in domainFull:
|
||||
domain = domainFull.split(':')[0]
|
||||
|
@ -302,7 +298,7 @@ def htmlCalendar(cssCache: {}, translate: {},
|
|||
'?month=' + str(prevMonthNumber) + '">'
|
||||
calendarStr += \
|
||||
' <img loading="lazy" alt="' + translate['Previous month'] + \
|
||||
'" title="' + translate['Previous month'] + '" src="/' + iconsPath + \
|
||||
'" title="' + translate['Previous month'] + '" src="/icons' + \
|
||||
'/prev.png" class="buttonprev"/></a>\n'
|
||||
calendarStr += ' <a href="' + calActor + '/inbox" title="'
|
||||
calendarStr += translate['Switch to timeline view'] + '">'
|
||||
|
@ -312,7 +308,7 @@ def htmlCalendar(cssCache: {}, translate: {},
|
|||
'?month=' + str(nextMonthNumber) + '">'
|
||||
calendarStr += \
|
||||
' <img loading="lazy" alt="' + translate['Next month'] + \
|
||||
'" title="' + translate['Next month'] + '" src="/' + iconsPath + \
|
||||
'" title="' + translate['Next month'] + '" src="/icons' + \
|
||||
'/prev.png" class="buttonnext"/></a>\n'
|
||||
calendarStr += '</caption>\n'
|
||||
calendarStr += '<thead>\n'
|
||||
|
|
|
@ -11,11 +11,11 @@ from shutil import copyfile
|
|||
from utils import getConfigParam
|
||||
from utils import getNicknameFromActor
|
||||
from utils import isEditor
|
||||
from webapp_utils import sharesTimelineJson
|
||||
from webapp_utils import htmlPostSeparator
|
||||
from webapp_utils import getLeftImageFile
|
||||
from webapp_utils import getImageFile
|
||||
from webapp_utils import headerButtonsFrontScreen
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_utils import getBannerFile
|
||||
|
@ -28,9 +28,46 @@ def linksExist(baseDir: str) -> bool:
|
|||
return os.path.isfile(linksFilename)
|
||||
|
||||
|
||||
def getLeftColumnShares(baseDir: str,
|
||||
httpPrefix: str, domainFull: str,
|
||||
nickname: str,
|
||||
maxSharesInLeftColumn: int,
|
||||
translate: {}) -> []:
|
||||
"""get any shares and turn them into the left column links format
|
||||
"""
|
||||
pageNumber = 1
|
||||
actor = httpPrefix + '://' + domainFull + '/users/' + nickname
|
||||
sharesJson, lastPage = \
|
||||
sharesTimelineJson(actor, pageNumber,
|
||||
maxSharesInLeftColumn,
|
||||
baseDir, maxSharesInLeftColumn)
|
||||
if not sharesJson:
|
||||
return []
|
||||
|
||||
linksList = []
|
||||
ctr = 0
|
||||
for published, item in sharesJson.items():
|
||||
sharedesc = item['displayName']
|
||||
if '<' in sharedesc or '?' in sharedesc:
|
||||
continue
|
||||
contactActor = item['actor']
|
||||
shareLink = actor + \
|
||||
'?replydm=sharedesc:' + \
|
||||
sharedesc.replace(' ', '_') + \
|
||||
'?mention=' + contactActor
|
||||
linksList.append(sharedesc + ' ' + shareLink)
|
||||
ctr += 1
|
||||
if ctr >= maxSharesInLeftColumn:
|
||||
break
|
||||
|
||||
if linksList:
|
||||
linksList = ['* ' + translate['Shares']] + linksList
|
||||
return linksList
|
||||
|
||||
|
||||
def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||
httpPrefix: str, translate: {},
|
||||
iconsPath: str, editor: bool,
|
||||
editor: bool,
|
||||
showBackButton: bool, timelinePath: str,
|
||||
rssIconAtTop: bool, showHeaderImage: bool,
|
||||
frontPage: bool) -> str:
|
||||
|
@ -98,7 +135,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'" loading="lazy" alt="' + \
|
||||
translate['Edit Links'] + '" title="' + \
|
||||
translate['Edit Links'] + '" src="/' + \
|
||||
iconsPath + '/edit.png" /></a>\n'
|
||||
'icons/edit.png" /></a>\n'
|
||||
|
||||
# RSS icon
|
||||
if nickname != 'news':
|
||||
|
@ -117,7 +154,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'<img class="' + editImageClass + \
|
||||
'" loading="lazy" alt="' + rssTitle + \
|
||||
'" title="' + rssTitle + \
|
||||
'" src="/' + iconsPath + '/logorss.png" /></a>\n'
|
||||
'" src="/icons/logorss.png" /></a>\n'
|
||||
if rssIconAtTop:
|
||||
htmlStr += rssIconStr
|
||||
htmlStr += ' </div>\n'
|
||||
|
@ -136,53 +173,64 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
|
||||
linksFilename = baseDir + '/accounts/links.txt'
|
||||
linksFileContainsEntries = False
|
||||
linksList = None
|
||||
if os.path.isfile(linksFilename):
|
||||
linksList = None
|
||||
with open(linksFilename, "r") as f:
|
||||
linksList = f.readlines()
|
||||
if linksList:
|
||||
for lineStr in linksList:
|
||||
if ' ' not in lineStr:
|
||||
if '#' not in lineStr:
|
||||
if '*' not in lineStr:
|
||||
continue
|
||||
lineStr = lineStr.strip()
|
||||
words = lineStr.split(' ')
|
||||
# get the link
|
||||
linkStr = None
|
||||
for word in words:
|
||||
if word == '#':
|
||||
|
||||
if not frontPage:
|
||||
# show a number of shares
|
||||
maxSharesInLeftColumn = 3
|
||||
sharesList = \
|
||||
getLeftColumnShares(baseDir,
|
||||
httpPrefix, domainFull, nickname,
|
||||
maxSharesInLeftColumn, translate)
|
||||
if linksList and sharesList:
|
||||
linksList = sharesList + linksList
|
||||
|
||||
if linksList:
|
||||
for lineStr in linksList:
|
||||
if ' ' not in lineStr:
|
||||
if '#' not in lineStr:
|
||||
if '*' not in lineStr:
|
||||
continue
|
||||
if word == '*':
|
||||
continue
|
||||
if '://' in word:
|
||||
linkStr = word
|
||||
break
|
||||
if linkStr:
|
||||
lineStr = lineStr.replace(linkStr, '').strip()
|
||||
# avoid any dubious scripts being added
|
||||
if '<' not in lineStr:
|
||||
# remove trailing comma if present
|
||||
if lineStr.endswith(','):
|
||||
lineStr = lineStr[:len(lineStr)-1]
|
||||
# add link to the returned html
|
||||
htmlStr += \
|
||||
' <p><a href="' + linkStr + '">' + \
|
||||
lineStr + '</a></p>\n'
|
||||
linksFileContainsEntries = True
|
||||
else:
|
||||
if lineStr.startswith('#') or lineStr.startswith('*'):
|
||||
lineStr = lineStr[1:].strip()
|
||||
if firstSeparatorAdded:
|
||||
htmlStr += separatorStr
|
||||
firstSeparatorAdded = True
|
||||
htmlStr += \
|
||||
' <h3 class="linksHeader">' + \
|
||||
lineStr + '</h3>\n'
|
||||
else:
|
||||
htmlStr += \
|
||||
' <p>' + lineStr + '</p>\n'
|
||||
lineStr = lineStr.strip()
|
||||
words = lineStr.split(' ')
|
||||
# get the link
|
||||
linkStr = None
|
||||
for word in words:
|
||||
if word == '#':
|
||||
continue
|
||||
if word == '*':
|
||||
continue
|
||||
if '://' in word:
|
||||
linkStr = word
|
||||
break
|
||||
if linkStr:
|
||||
lineStr = lineStr.replace(linkStr, '').strip()
|
||||
# avoid any dubious scripts being added
|
||||
if '<' not in lineStr:
|
||||
# remove trailing comma if present
|
||||
if lineStr.endswith(','):
|
||||
lineStr = lineStr[:len(lineStr)-1]
|
||||
# add link to the returned html
|
||||
htmlStr += \
|
||||
' <p><a href="' + linkStr + '">' + \
|
||||
lineStr + '</a></p>\n'
|
||||
linksFileContainsEntries = True
|
||||
else:
|
||||
if lineStr.startswith('#') or lineStr.startswith('*'):
|
||||
lineStr = lineStr[1:].strip()
|
||||
if firstSeparatorAdded:
|
||||
htmlStr += separatorStr
|
||||
firstSeparatorAdded = True
|
||||
htmlStr += \
|
||||
' <h3 class="linksHeader">' + \
|
||||
lineStr + '</h3>\n'
|
||||
else:
|
||||
htmlStr += \
|
||||
' <p>' + lineStr + '</p>\n'
|
||||
linksFileContainsEntries = True
|
||||
|
||||
if firstSeparatorAdded:
|
||||
htmlStr += separatorStr
|
||||
|
@ -215,8 +263,6 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
|||
if os.path.isfile(baseDir + '/epicyon.css'):
|
||||
cssFilename = baseDir + '/epicyon.css'
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
# is the user a site editor?
|
||||
if nickname == 'news':
|
||||
editor = False
|
||||
|
@ -238,12 +284,12 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
|||
htmlStr += '<center>' + \
|
||||
headerButtonsFrontScreen(translate, nickname,
|
||||
'links', authorized,
|
||||
iconsAsButtons, iconsPath) + '</center>'
|
||||
iconsAsButtons) + '</center>'
|
||||
if linksExist(baseDir):
|
||||
htmlStr += \
|
||||
getLeftColumnContent(baseDir, nickname, domainFull,
|
||||
httpPrefix, translate,
|
||||
iconsPath, editor,
|
||||
editor,
|
||||
False, timelinePath,
|
||||
rssIconAtTop, False, False)
|
||||
else:
|
||||
|
|
|
@ -25,7 +25,6 @@ from webapp_utils import htmlFooter
|
|||
from webapp_utils import getBannerFile
|
||||
from webapp_utils import htmlPostSeparator
|
||||
from webapp_utils import headerButtonsFrontScreen
|
||||
from webapp_utils import getIconsWebPath
|
||||
|
||||
|
||||
def votesIndicator(totalVotes: int, positiveVoting: bool) -> str:
|
||||
|
@ -44,7 +43,7 @@ def votesIndicator(totalVotes: int, positiveVoting: bool) -> str:
|
|||
|
||||
def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||
httpPrefix: str, translate: {},
|
||||
iconsPath: str, moderator: bool, editor: bool,
|
||||
moderator: bool, editor: bool,
|
||||
newswire: {}, positiveVoting: bool,
|
||||
showBackButton: bool, timelinePath: str,
|
||||
showPublishButton: bool,
|
||||
|
@ -143,7 +142,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'" loading="lazy" alt="' + \
|
||||
translate['Edit newswire'] + '" title="' + \
|
||||
translate['Edit newswire'] + '" src="/' + \
|
||||
iconsPath + '/edit_notify.png" /></a>\n'
|
||||
'icons/edit_notify.png" /></a>\n'
|
||||
else:
|
||||
# show the edit icon
|
||||
htmlStr += \
|
||||
|
@ -153,7 +152,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'" loading="lazy" alt="' + \
|
||||
translate['Edit newswire'] + '" title="' + \
|
||||
translate['Edit newswire'] + '" src="/' + \
|
||||
iconsPath + '/edit.png" /></a>\n'
|
||||
'icons/edit.png" /></a>\n'
|
||||
|
||||
# show the RSS icons
|
||||
rssIconStr = \
|
||||
|
@ -162,14 +161,14 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'" loading="lazy" alt="' + \
|
||||
translate['Hashtag Categories RSS Feed'] + '" title="' + \
|
||||
translate['Hashtag Categories RSS Feed'] + '" src="/' + \
|
||||
iconsPath + '/categoriesrss.png" /></a>\n'
|
||||
'icons/categoriesrss.png" /></a>\n'
|
||||
rssIconStr += \
|
||||
' <a href="/newswire.xml">' + \
|
||||
'<img class="' + editImageClass + \
|
||||
'" loading="lazy" alt="' + \
|
||||
translate['Newswire RSS Feed'] + '" title="' + \
|
||||
translate['Newswire RSS Feed'] + '" src="/' + \
|
||||
iconsPath + '/logorss.png" /></a>\n'
|
||||
'icons/logorss.png" /></a>\n'
|
||||
if rssIconAtTop:
|
||||
htmlStr += rssIconStr
|
||||
|
||||
|
@ -183,7 +182,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
'" loading="lazy" alt="' + \
|
||||
translate['Publish a news article'] + '" title="' + \
|
||||
translate['Publish a news article'] + '" src="/' + \
|
||||
iconsPath + '/publish.png" /></a>\n'
|
||||
'icons/publish.png" /></a>\n'
|
||||
|
||||
if editImageClass == 'rightColEdit':
|
||||
htmlStr += ' </center>\n'
|
||||
|
@ -197,7 +196,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
# show the newswire lines
|
||||
newswireContentStr = \
|
||||
htmlNewswire(baseDir, newswire, nickname, moderator, translate,
|
||||
positiveVoting, iconsPath)
|
||||
positiveVoting)
|
||||
htmlStr += newswireContentStr
|
||||
|
||||
# show the rss icon at the bottom, typically on the right hand side
|
||||
|
@ -207,7 +206,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
|||
|
||||
|
||||
def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||
translate: {}, positiveVoting: bool, iconsPath: str) -> str:
|
||||
translate: {}, positiveVoting: bool) -> str:
|
||||
"""Converts a newswire dict into html
|
||||
"""
|
||||
separatorStr = htmlPostSeparator(baseDir, 'right')
|
||||
|
@ -252,7 +251,7 @@ def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
|||
'/newswireunvote=' + dateStrLink + '" ' + \
|
||||
'title="' + translate['Remove Vote'] + '">'
|
||||
htmlStr += '<img loading="lazy" class="voteicon" src="/' + \
|
||||
iconsPath + '/vote.png" /></a></p>\n'
|
||||
'icons/vote.png" /></a></p>\n'
|
||||
else:
|
||||
htmlStr += ' <span class="newswireDateVotedOn">'
|
||||
htmlStr += dateShown + '</span></p>\n'
|
||||
|
@ -277,7 +276,7 @@ def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
|||
'/newswirevote=' + dateStrLink + '" ' + \
|
||||
'title="' + translate['Vote'] + '">'
|
||||
htmlStr += '<img class="voteicon" src="/' + \
|
||||
iconsPath + '/vote.png" /></a>'
|
||||
'icons/vote.png" /></a>'
|
||||
htmlStr += '</p>\n'
|
||||
else:
|
||||
htmlStr += '<p class="newswireItem">' + \
|
||||
|
@ -324,8 +323,6 @@ def htmlCitations(baseDir: str, nickname: str, domain: str,
|
|||
if os.path.isfile(baseDir + '/epicyon.css'):
|
||||
cssFilename = baseDir + '/epicyon.css'
|
||||
|
||||
# iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
htmlStr = htmlHeaderWithExternalStyle(cssFilename)
|
||||
|
||||
# top banner
|
||||
|
@ -422,8 +419,6 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
|||
if os.path.isfile(baseDir + '/epicyon.css'):
|
||||
cssFilename = baseDir + '/epicyon.css'
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
if nickname == 'news':
|
||||
editor = False
|
||||
moderator = False
|
||||
|
@ -449,12 +444,12 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
|||
htmlStr += '<center>' + \
|
||||
headerButtonsFrontScreen(translate, nickname,
|
||||
'newswire', authorized,
|
||||
iconsAsButtons, iconsPath) + '</center>'
|
||||
iconsAsButtons) + '</center>'
|
||||
if newswire:
|
||||
htmlStr += \
|
||||
getRightColumnContent(baseDir, nickname, domainFull,
|
||||
httpPrefix, translate,
|
||||
iconsPath, moderator, editor,
|
||||
moderator, editor,
|
||||
newswire, positiveVoting,
|
||||
False, timelinePath, showPublishButton,
|
||||
showPublishAsIcon, rssIconAtTop, False,
|
||||
|
|
|
@ -13,7 +13,6 @@ from utils import getDomainFromActor
|
|||
from utils import locatePost
|
||||
from utils import loadJson
|
||||
from webapp_utils import getAltPath
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_post import individualPostAsHtml
|
||||
|
@ -33,7 +32,6 @@ def htmlConfirmDelete(cssCache: {},
|
|||
"""
|
||||
if '/statuses/' not in messageId:
|
||||
return None
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
actor = messageId.split('/statuses/')[0]
|
||||
nickname = getNicknameFromActor(actor)
|
||||
domain, port = getDomainFromActor(actor)
|
||||
|
@ -63,7 +61,7 @@ def htmlConfirmDelete(cssCache: {},
|
|||
deletePostStr = htmlHeaderWithExternalStyle(cssFilename)
|
||||
deletePostStr += \
|
||||
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||
iconsPath, translate, pageNumber,
|
||||
translate, pageNumber,
|
||||
baseDir, session, wfRequest, personCache,
|
||||
nickname, domain, port, postJsonObject,
|
||||
None, True, False,
|
||||
|
|
|
@ -12,7 +12,6 @@ from utils import getNicknameFromActor
|
|||
from utils import getDomainFromActor
|
||||
from utils import getImageFormats
|
||||
from utils import getMediaFormats
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import getBannerFile
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
|
@ -61,7 +60,6 @@ def htmlFollowingDataList(baseDir: str, nickname: str,
|
|||
def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||
replyStr: str,
|
||||
translate: {},
|
||||
iconsPath: str,
|
||||
showPublicOnDropdown: bool,
|
||||
defaultTimeline: str,
|
||||
pathBase: str,
|
||||
|
@ -81,7 +79,7 @@ def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
|||
dropDownContent += ' <label for="my-newPostDropdown"\n'
|
||||
dropDownContent += ' data-toggle="newPostDropdown">\n'
|
||||
dropDownContent += ' <img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/' + scopeIcon + '"/><b>' + \
|
||||
'icons/' + scopeIcon + '"/><b>' + \
|
||||
scopeDescription + '</b></label>\n'
|
||||
dropDownContent += ' <ul>\n'
|
||||
|
||||
|
@ -89,58 +87,58 @@ def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
|||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownNewPostSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_public.png"/><b>' + \
|
||||
'icons/scope_public.png"/><b>' + \
|
||||
translate['Public'] + '</b><br>' + \
|
||||
translate['Visible to anyone'] + '</a></li>\n'
|
||||
if defaultTimeline == 'tlfeatures':
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_blog.png"/><b>' + \
|
||||
'icons/scope_blog.png"/><b>' + \
|
||||
translate['Article'] + '</b><br>' + \
|
||||
translate['Create an article'] + '</a></li>\n'
|
||||
else:
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_blog.png"/><b>' + \
|
||||
'icons/scope_blog.png"/><b>' + \
|
||||
translate['Blog'] + '</b><br>' + \
|
||||
translate['Publicly visible post'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownUnlistedSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_unlisted.png"/><b>' + \
|
||||
'icons/scope_unlisted.png"/><b>' + \
|
||||
translate['Unlisted'] + '</b><br>' + \
|
||||
translate['Not on public timeline'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownFollowersSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_followers.png"/><b>' + \
|
||||
'icons/scope_followers.png"/><b>' + \
|
||||
translate['Followers'] + '</b><br>' + \
|
||||
translate['Only to followers'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownDMSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_dm.png"/><b>' + \
|
||||
'icons/scope_dm.png"/><b>' + \
|
||||
translate['DM'] + '</b><br>' + \
|
||||
translate['Only to mentioned people'] + '</a></li>\n'
|
||||
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownReminderSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_reminder.png"/><b>' + \
|
||||
'icons/scope_reminder.png"/><b>' + \
|
||||
translate['Reminder'] + '</b><br>' + \
|
||||
translate['Scheduled note to yourself'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownEventSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_event.png"/><b>' + \
|
||||
'icons/scope_event.png"/><b>' + \
|
||||
translate['Event'] + '</b><br>' + \
|
||||
translate['Create an event'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + dropdownReportSuffix + \
|
||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_report.png"/><b>' + \
|
||||
'icons/scope_report.png"/><b>' + \
|
||||
translate['Report'] + '</b><br>' + \
|
||||
translate['Send to moderators'] + '</a></li>\n'
|
||||
|
||||
|
@ -148,13 +146,13 @@ def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
|||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + \
|
||||
'/newshare"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_share.png"/><b>' + \
|
||||
'icons/scope_share.png"/><b>' + \
|
||||
translate['Shares'] + '</b><br>' + \
|
||||
translate['Describe a shared item'] + '</a></li>\n'
|
||||
dropDownContent += \
|
||||
'<li><a href="' + pathBase + \
|
||||
'/newquestion"><img loading="lazy" alt="" title="" src="/' + \
|
||||
iconsPath + '/scope_question.png"/><b>' + \
|
||||
'icons/scope_question.png"/><b>' + \
|
||||
translate['Question'] + '</b><br>' + \
|
||||
translate['Ask a question'] + '</a></li>\n'
|
||||
|
||||
|
@ -167,13 +165,13 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
baseDir: str, httpPrefix: str,
|
||||
path: str, inReplyTo: str,
|
||||
mentions: [],
|
||||
shareDescription: str,
|
||||
reportUrl: str, pageNumber: int,
|
||||
nickname: str, domain: str,
|
||||
domainFull: str,
|
||||
defaultTimeline: str, newswire: {}) -> str:
|
||||
"""New post screen
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
replyStr = ''
|
||||
|
||||
showPublicOnDropdown = True
|
||||
|
@ -292,8 +290,11 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
|
||||
scopeIcon = 'scope_public.png'
|
||||
scopeDescription = translate['Public']
|
||||
placeholderSubject = \
|
||||
translate['Subject or Content Warning (optional)'] + '...'
|
||||
if shareDescription:
|
||||
placeholderSubject = translate['Ask about a shared item.'] + '..'
|
||||
else:
|
||||
placeholderSubject = \
|
||||
translate['Subject or Content Warning (optional)'] + '...'
|
||||
placeholderMentions = ''
|
||||
if inReplyTo:
|
||||
# mentionsAndContent = getMentionsString(content)
|
||||
|
@ -491,7 +492,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
dateAndLocation += \
|
||||
'<p><img loading="lazy" alt="" title="" ' + \
|
||||
'class="emojicalendar" src="/' + \
|
||||
iconsPath + '/calendar.png"/>\n'
|
||||
'icons/calendar.png"/>\n'
|
||||
# select a date and time for this post
|
||||
dateAndLocation += '<label class="labels">' + \
|
||||
translate['Date'] + ': </label>\n'
|
||||
|
@ -506,7 +507,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
dateAndLocation += \
|
||||
'<p><img loading="lazy" alt="" title="" ' + \
|
||||
'class="emojicalendar" src="/' + \
|
||||
iconsPath + '/calendar.png"/>\n'
|
||||
'icons/calendar.png"/>\n'
|
||||
# select start time for the event
|
||||
dateAndLocation += '<label class="labels">' + \
|
||||
translate['Start Date'] + ': </label>\n'
|
||||
|
@ -519,7 +520,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
dateAndLocation += \
|
||||
'<br><img loading="lazy" alt="" title="" ' + \
|
||||
'class="emojicalendar" src="/' + \
|
||||
iconsPath + '/calendar.png"/>\n'
|
||||
'icons/calendar.png"/>\n'
|
||||
dateAndLocation += '<label class="labels">' + \
|
||||
translate['End Date'] + ': </label>\n'
|
||||
dateAndLocation += '<input type="date" name="endDate">\n'
|
||||
|
@ -612,12 +613,11 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
dropdownReportSuffix += '?mention=' + mentionedActor
|
||||
|
||||
dropDownContent = ''
|
||||
if not reportUrl:
|
||||
if not reportUrl and not shareDescription:
|
||||
dropDownContent = \
|
||||
htmlNewPostDropDown(scopeIcon, scopeDescription,
|
||||
replyStr,
|
||||
translate,
|
||||
iconsPath,
|
||||
showPublicOnDropdown,
|
||||
defaultTimeline,
|
||||
pathBase,
|
||||
|
@ -630,7 +630,9 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
dropdownEventSuffix,
|
||||
dropdownReportSuffix)
|
||||
else:
|
||||
mentionsStr = 'Re: ' + reportUrl + '\n\n' + mentionsStr
|
||||
if not shareDescription:
|
||||
# reporting a post to moderator
|
||||
mentionsStr = 'Re: ' + reportUrl + '\n\n' + mentionsStr
|
||||
|
||||
newPostForm += \
|
||||
'<form enctype="multipart/form-data" method="POST" ' + \
|
||||
|
@ -678,7 +680,11 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
|||
|
||||
newPostForm += \
|
||||
' <label class="labels">' + placeholderSubject + '</label><br>'
|
||||
newPostForm += ' <input type="text" name="subject">'
|
||||
if not shareDescription:
|
||||
shareDescription = ''
|
||||
newPostForm += \
|
||||
' <input type="text" name="subject" value="' + \
|
||||
shareDescription + '">'
|
||||
newPostForm += ''
|
||||
|
||||
selectedStr = ' selected'
|
||||
|
|
|
@ -12,7 +12,6 @@ from utils import getDomainFromActor
|
|||
from person import personBoxJson
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import getBannerFile
|
||||
from webapp_utils import htmlPostSeparator
|
||||
from webapp_utils import headerButtonsFrontScreen
|
||||
|
@ -33,7 +32,6 @@ def htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
These should only be public blog posts from the features timeline
|
||||
which is the blog timeline of the news actor
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
separatorStr = htmlPostSeparator(baseDir, None)
|
||||
profileStr = ''
|
||||
maxItems = 4
|
||||
|
@ -57,7 +55,7 @@ def htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
postStr = \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port, item,
|
||||
|
@ -101,10 +99,9 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
|||
if port:
|
||||
domainFull = domain + ':' + str(port)
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
loginButton = headerButtonsFrontScreen(translate, nickname,
|
||||
'features', authorized,
|
||||
iconsAsButtons, iconsPath)
|
||||
iconsAsButtons)
|
||||
|
||||
# If this is the news account then show a different banner
|
||||
bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
|
||||
|
@ -123,12 +120,10 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
|||
profileHeaderStr += ' <tbody>\n'
|
||||
profileHeaderStr += ' <tr>\n'
|
||||
profileHeaderStr += ' <td valign="top" class="col-left">\n'
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
profileHeaderStr += \
|
||||
getLeftColumnContent(baseDir, 'news', domainFull,
|
||||
httpPrefix, translate,
|
||||
iconsPath, False,
|
||||
False, None, rssIconAtTop, True,
|
||||
False, False, None, rssIconAtTop, True,
|
||||
True)
|
||||
profileHeaderStr += ' </td>\n'
|
||||
profileHeaderStr += ' <td valign="top" class="col-center">\n'
|
||||
|
@ -155,12 +150,10 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
|||
# Footer which is only used for system accounts
|
||||
profileFooterStr = ' </td>\n'
|
||||
profileFooterStr += ' <td valign="top" class="col-right">\n'
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
profileFooterStr += \
|
||||
getRightColumnContent(baseDir, 'news', domainFull,
|
||||
httpPrefix, translate,
|
||||
iconsPath, False, False,
|
||||
newswire, False,
|
||||
False, False, newswire, False,
|
||||
False, None, False, False,
|
||||
False, True, authorized, True)
|
||||
profileFooterStr += ' </td>\n'
|
||||
|
|
|
@ -38,7 +38,6 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
newPostButtonStr: str,
|
||||
baseDir: str,
|
||||
nickname: str, domain: str,
|
||||
iconsPath: str,
|
||||
timelineStartTime,
|
||||
newCalendarEvent: bool,
|
||||
calendarPath: str,
|
||||
|
@ -212,7 +211,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
tlStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/search"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/search.png" title="' + \
|
||||
'icons/search.png" title="' + \
|
||||
translate['Search and follow'] + '" alt="| ' + \
|
||||
translate['Search and follow'] + \
|
||||
'" class="timelineicon"/></a>'
|
||||
|
@ -239,7 +238,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
tlStr += \
|
||||
' <a class="imageAnchor" href="' + \
|
||||
usersPath + calendarPath + \
|
||||
'"><img loading="lazy" src="/' + iconsPath + '/' + \
|
||||
'"><img loading="lazy" src="/icons/' + \
|
||||
calendarImage + '" title="' + translate['Calendar'] + \
|
||||
'" alt="| ' + calendarAltText + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -256,7 +255,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
tlStr += \
|
||||
' <a class="imageAnchor" href="' + \
|
||||
usersPath + '/minimal' + \
|
||||
'"><img loading="lazy" src="/' + iconsPath + \
|
||||
'"><img loading="lazy" src="/icons' + \
|
||||
'/showhide.png" title="' + translate['Show/Hide Buttons'] + \
|
||||
'" alt="| ' + translate['Show/Hide Buttons'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -278,7 +277,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
tlStr += \
|
||||
'<a class="imageAnchorMobile" href="' + \
|
||||
usersPath + '/newswiremobile">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/newswire.png" title="' + translate['News'] + \
|
||||
'" alt="| ' + translate['News'] + \
|
||||
'" class="timelineicon"/></a>'
|
||||
|
@ -296,7 +295,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
|||
tlStr += \
|
||||
'<a class="imageAnchorMobile" href="' + \
|
||||
usersPath + '/linksmobile">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/links.png" title="' + translate['Edit Links'] + \
|
||||
'" alt="| ' + translate['Edit Links'] + \
|
||||
'" class="timelineicon"/></a>'
|
||||
|
|
148
webapp_post.py
|
@ -53,7 +53,6 @@ from webapp_utils import addEmojiToDisplayName
|
|||
from webapp_utils import postContainsPublic
|
||||
from webapp_utils import getContentWarningButton
|
||||
from webapp_utils import getPostAttachmentsAsHtml
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_media import addEmbeddedElements
|
||||
|
@ -202,6 +201,14 @@ def getAvatarImageUrl(session,
|
|||
return avatarUrl
|
||||
|
||||
|
||||
def getBrokenLinkSubstitute() -> str:
|
||||
"""Returns html used to show a default image if the link to
|
||||
an image is broken
|
||||
"""
|
||||
return " onerror=\"this.onerror=null; this.src='" + \
|
||||
"icons/avatar_default.png'\""
|
||||
|
||||
|
||||
def getAvatarImageHtml(showAvatarOptions: bool,
|
||||
nickname: str, domainFull: str,
|
||||
avatarUrl: str, postActor: str,
|
||||
|
@ -215,7 +222,7 @@ def getAvatarImageHtml(showAvatarOptions: bool,
|
|||
avatarLink += \
|
||||
' <img loading="lazy" src="' + avatarUrl + '" title="' + \
|
||||
translate['Show profile'] + '" alt=" "' + avatarPosition + \
|
||||
'/></a>\n'
|
||||
getBrokenLinkSubstitute() + '/></a>\n'
|
||||
|
||||
if showAvatarOptions and \
|
||||
domainFull + '/users/' + nickname not in postActor:
|
||||
|
@ -227,20 +234,22 @@ def getAvatarImageHtml(showAvatarOptions: bool,
|
|||
avatarLink += \
|
||||
' <img loading="lazy" title="' + \
|
||||
translate['Show options for this person'] + \
|
||||
'" src="' + avatarUrl + '" ' + avatarPosition + '/></a>\n'
|
||||
'" src="' + avatarUrl + '" ' + avatarPosition + \
|
||||
getBrokenLinkSubstitute() + '/></a>\n'
|
||||
else:
|
||||
# don't link to the person options for the news account
|
||||
avatarLink += \
|
||||
' <img loading="lazy" title="' + \
|
||||
translate['Show options for this person'] + \
|
||||
'" src="' + avatarUrl + '" ' + avatarPosition + '/>\n'
|
||||
'" src="' + avatarUrl + '" ' + avatarPosition + \
|
||||
getBrokenLinkSubstitute() + '/>\n'
|
||||
return avatarLink.strip()
|
||||
|
||||
|
||||
def getReplyIconHtml(nickname: str, isPublicRepeat: bool,
|
||||
showIcons: bool, commentsEnabled: bool,
|
||||
postJsonObject: {}, pageNumberParam: str,
|
||||
iconsPath: str, translate: {}) -> str:
|
||||
translate: {}) -> str:
|
||||
"""Returns html for the reply icon/button
|
||||
"""
|
||||
replyStr = ''
|
||||
|
@ -292,13 +301,13 @@ def getReplyIconHtml(nickname: str, isPublicRepeat: bool,
|
|||
' ' + \
|
||||
'<img loading="lazy" title="' + \
|
||||
replyToThisPostStr + '" alt="' + replyToThisPostStr + \
|
||||
' |" src="/' + iconsPath + '/reply.png"/></a>\n'
|
||||
' |" src="/icons/reply.png"/></a>\n'
|
||||
return replyStr
|
||||
|
||||
|
||||
def getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
|
||||
postJsonObject: {}, actorNickname: str,
|
||||
translate: {}, iconsPath: str, isEvent: bool) -> str:
|
||||
translate: {}, isEvent: bool) -> str:
|
||||
"""Returns html for the edit icon/button
|
||||
"""
|
||||
editStr = ''
|
||||
|
@ -325,7 +334,7 @@ def getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
|
|||
'" title="' + editBlogPostStr + '">' + \
|
||||
'<img loading="lazy" title="' + \
|
||||
editBlogPostStr + '" alt="' + editBlogPostStr + \
|
||||
' |" src="/' + iconsPath + '/edit.png"/></a>\n'
|
||||
' |" src="/icons/edit.png"/></a>\n'
|
||||
else:
|
||||
editStr += \
|
||||
' ' + \
|
||||
|
@ -336,7 +345,7 @@ def getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
|
|||
'" title="' + editBlogPostStr + '">' + \
|
||||
'<img loading="lazy" title="' + \
|
||||
editBlogPostStr + '" alt="' + editBlogPostStr + \
|
||||
' |" src="/' + iconsPath + '/edit.png"/></a>\n'
|
||||
' |" src="/icons/edit.png"/></a>\n'
|
||||
elif isEvent:
|
||||
editEventStr = translate['Edit event']
|
||||
editStr += \
|
||||
|
@ -348,7 +357,7 @@ def getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
|
|||
'" title="' + editEventStr + '">' + \
|
||||
'<img loading="lazy" title="' + \
|
||||
editEventStr + '" alt="' + editEventStr + \
|
||||
' |" src="/' + iconsPath + '/edit.png"/></a>\n'
|
||||
' |" src="/icons/edit.png"/></a>\n'
|
||||
return editStr
|
||||
|
||||
|
||||
|
@ -360,7 +369,7 @@ def getAnnounceIconHtml(nickname: str, domainFull: str,
|
|||
translate: {},
|
||||
pageNumberParam: str,
|
||||
timelinePostBookmark: str,
|
||||
boxName: str, iconsPath: str) -> str:
|
||||
boxName: str) -> str:
|
||||
"""Returns html for announce icon/button
|
||||
"""
|
||||
announceStr = ''
|
||||
|
@ -390,7 +399,7 @@ def getAnnounceIconHtml(nickname: str, domainFull: str,
|
|||
' ' + \
|
||||
'<img loading="lazy" title="' + translate['Repeat this post'] + \
|
||||
'" alt="' + translate['Repeat this post'] + \
|
||||
' |" src="/' + iconsPath + '/' + announceIcon + '"/></a>\n'
|
||||
' |" src="/icons/' + announceIcon + '"/></a>\n'
|
||||
return announceStr
|
||||
|
||||
|
||||
|
@ -402,7 +411,7 @@ def getLikeIconHtml(nickname: str, domainFull: str,
|
|||
postStartTime,
|
||||
translate: {}, pageNumberParam: str,
|
||||
timelinePostBookmark: str,
|
||||
boxName: str, iconsPath: str) -> str:
|
||||
boxName: str) -> str:
|
||||
"""Returns html for like icon/button
|
||||
"""
|
||||
likeStr = ''
|
||||
|
@ -448,7 +457,7 @@ def getLikeIconHtml(nickname: str, domainFull: str,
|
|||
' ' + \
|
||||
'<img loading="lazy" title="' + likeTitle + likeCountStr + \
|
||||
'" alt="' + likeTitle + \
|
||||
' |" src="/' + iconsPath + '/' + likeIcon + '"/></a>\n'
|
||||
' |" src="/icons/' + likeIcon + '"/></a>\n'
|
||||
return likeStr
|
||||
|
||||
|
||||
|
@ -459,8 +468,7 @@ def getBookmarkIconHtml(nickname: str, domainFull: str,
|
|||
enableTimingLog: bool,
|
||||
postStartTime, boxName: str,
|
||||
pageNumberParam: str,
|
||||
timelinePostBookmark: str,
|
||||
iconsPath: str) -> str:
|
||||
timelinePostBookmark: str) -> str:
|
||||
"""Returns html for bookmark icon/button
|
||||
"""
|
||||
bookmarkStr = ''
|
||||
|
@ -486,7 +494,7 @@ def getBookmarkIconHtml(nickname: str, domainFull: str,
|
|||
bookmarkStr += \
|
||||
' ' + \
|
||||
'<img loading="lazy" title="' + bookmarkTitle + '" alt="' + \
|
||||
bookmarkTitle + ' |" src="/' + iconsPath + \
|
||||
bookmarkTitle + ' |" src="/icons' + \
|
||||
'/' + bookmarkIcon + '"/></a>\n'
|
||||
return bookmarkStr
|
||||
|
||||
|
@ -497,7 +505,6 @@ def getMuteIconHtml(isMuted: bool,
|
|||
nickname: str, domainFull: str,
|
||||
allowDeletion: bool,
|
||||
pageNumberParam: str,
|
||||
iconsPath: str,
|
||||
boxName: str,
|
||||
timelinePostBookmark: str,
|
||||
translate: {}) -> str:
|
||||
|
@ -520,7 +527,7 @@ def getMuteIconHtml(isMuted: bool,
|
|||
'<img loading="lazy" alt="' + \
|
||||
translate['Mute this post'] + \
|
||||
' |" title="' + translate['Mute this post'] + \
|
||||
'" src="/' + iconsPath + '/mute.png"/></a>\n'
|
||||
'" src="/icons/mute.png"/></a>\n'
|
||||
else:
|
||||
muteStr = \
|
||||
' <a class="imageAnchor" href="/users/' + \
|
||||
|
@ -532,7 +539,7 @@ def getMuteIconHtml(isMuted: bool,
|
|||
' ' + \
|
||||
'<img loading="lazy" alt="' + translate['Undo mute'] + \
|
||||
' |" title="' + translate['Undo mute'] + \
|
||||
'" src="/' + iconsPath + '/unmute.png"/></a>\n'
|
||||
'" src="/icons/unmute.png"/></a>\n'
|
||||
return muteStr
|
||||
|
||||
|
||||
|
@ -542,7 +549,6 @@ def getDeleteIconHtml(nickname: str, domainFull: str,
|
|||
messageId: str,
|
||||
postJsonObject: {},
|
||||
pageNumberParam: str,
|
||||
iconsPath: str,
|
||||
translate: {}) -> str:
|
||||
"""Returns html for delete icon/button
|
||||
"""
|
||||
|
@ -562,7 +568,7 @@ def getDeleteIconHtml(nickname: str, domainFull: str,
|
|||
'<img loading="lazy" alt="' + \
|
||||
translate['Delete this post'] + \
|
||||
' |" title="' + translate['Delete this post'] + \
|
||||
'" src="/' + iconsPath + '/delete.png"/></a>\n'
|
||||
'" src="/icons/delete.png"/></a>\n'
|
||||
return deleteStr
|
||||
|
||||
|
||||
|
@ -634,24 +640,24 @@ def getBlogCitationsHtml(boxName: str,
|
|||
return citationsStr
|
||||
|
||||
|
||||
def boostOwnTootHtml(translate: {}, iconsPath) -> str:
|
||||
def boostOwnTootHtml(translate: {}) -> str:
|
||||
"""The html title for announcing your own post
|
||||
"""
|
||||
return ' <img loading="lazy" title="' + \
|
||||
translate['announces'] + \
|
||||
'" alt="' + translate['announces'] + \
|
||||
'" src="/' + iconsPath + \
|
||||
'" src="/icons' + \
|
||||
'/repeat_inactive.png" class="announceOrReply"/>\n'
|
||||
|
||||
|
||||
def announceUnattributedHtml(translate: {}, iconsPath: str,
|
||||
def announceUnattributedHtml(translate: {},
|
||||
postJsonObject: {}) -> str:
|
||||
"""Returns the html for an announce title where there
|
||||
is no attribution on the announced post
|
||||
"""
|
||||
return ' <img loading="lazy" title="' + \
|
||||
translate['announces'] + '" alt="' + \
|
||||
translate['announces'] + '" src="/' + iconsPath + \
|
||||
translate['announces'] + '" src="/icons' + \
|
||||
'/repeat_inactive.png" ' + \
|
||||
'class="announceOrReply"/>\n' + \
|
||||
' <a href="' + \
|
||||
|
@ -659,7 +665,7 @@ def announceUnattributedHtml(translate: {}, iconsPath: str,
|
|||
'" class="announceOrReply">@unattributed</a>\n'
|
||||
|
||||
|
||||
def announceWithoutDisplayNameHtml(translate: {}, iconsPath: str,
|
||||
def announceWithoutDisplayNameHtml(translate: {},
|
||||
announceNickname: str,
|
||||
announceDomain: str,
|
||||
postJsonObject: {}) -> str:
|
||||
|
@ -668,7 +674,7 @@ def announceWithoutDisplayNameHtml(translate: {}, iconsPath: str,
|
|||
"""
|
||||
return ' <img loading="lazy" title="' + \
|
||||
translate['announces'] + '" alt="' + translate['announces'] + \
|
||||
'" src="/' + iconsPath + '/repeat_inactive.png" ' + \
|
||||
'" src="/icons/repeat_inactive.png" ' + \
|
||||
'class="announceOrReply"/>\n' + \
|
||||
' <a href="' + postJsonObject['object']['id'] + '" ' + \
|
||||
'class="announceOrReply">@' + \
|
||||
|
@ -676,7 +682,6 @@ def announceWithoutDisplayNameHtml(translate: {}, iconsPath: str,
|
|||
|
||||
|
||||
def announceWithDisplayNameHtml(translate: {},
|
||||
iconsPath: str,
|
||||
postJsonObject: {},
|
||||
announceDisplayName: str) -> str:
|
||||
"""Returns html for an announce having a display name
|
||||
|
@ -684,7 +689,7 @@ def announceWithDisplayNameHtml(translate: {},
|
|||
return ' <img loading="lazy" title="' + \
|
||||
translate['announces'] + '" alt="' + \
|
||||
translate['announces'] + '" src="/' + \
|
||||
iconsPath + '/repeat_inactive.png" ' + \
|
||||
'icons/repeat_inactive.png" ' + \
|
||||
'class="announceOrReply"/>\n' + \
|
||||
' <a href="' + \
|
||||
postJsonObject['object']['id'] + '" ' + \
|
||||
|
@ -699,7 +704,6 @@ def getPostTitleAnnounceHtml(baseDir: str,
|
|||
postJsonObject: {},
|
||||
postActor: str,
|
||||
translate: {},
|
||||
iconsPath: str,
|
||||
enableTimingLog: bool,
|
||||
postStartTime,
|
||||
boxName: str,
|
||||
|
@ -722,7 +726,7 @@ def getPostTitleAnnounceHtml(baseDir: str,
|
|||
attributedTo = postJsonObject['object']['attributedTo']
|
||||
|
||||
if attributedTo.startswith(postActor):
|
||||
titleStr += boostOwnTootHtml(translate, iconsPath)
|
||||
titleStr += boostOwnTootHtml(translate)
|
||||
else:
|
||||
# boosting another person's post
|
||||
logPostTiming(enableTimingLog, postStartTime, '13.2')
|
||||
|
@ -749,7 +753,6 @@ def getPostTitleAnnounceHtml(baseDir: str,
|
|||
logPostTiming(enableTimingLog, postStartTime, '13.3.1')
|
||||
titleStr += \
|
||||
announceWithDisplayNameHtml(translate,
|
||||
iconsPath,
|
||||
postJsonObject,
|
||||
announceDisplayName)
|
||||
# show avatar of person replied to
|
||||
|
@ -777,53 +780,53 @@ def getPostTitleAnnounceHtml(baseDir: str,
|
|||
';' + announceAvatarUrl + \
|
||||
messageIdStr + '">' \
|
||||
'<img loading="lazy" src="' + \
|
||||
announceAvatarUrl + '" ' \
|
||||
announceAvatarUrl + '" ' + \
|
||||
'title="' + translate[idx] + \
|
||||
'" alt=" "' + avatarPosition + \
|
||||
getBrokenLinkSubstitute() + \
|
||||
'/></a>\n </div>\n'
|
||||
else:
|
||||
titleStr += \
|
||||
announceWithoutDisplayNameHtml(translate, iconsPath,
|
||||
announceWithoutDisplayNameHtml(translate,
|
||||
announceNickname,
|
||||
announceDomain,
|
||||
postJsonObject)
|
||||
else:
|
||||
titleStr += \
|
||||
announceUnattributedHtml(translate, iconsPath,
|
||||
announceUnattributedHtml(translate,
|
||||
postJsonObject)
|
||||
else:
|
||||
titleStr += \
|
||||
announceUnattributedHtml(translate, iconsPath, postJsonObject)
|
||||
announceUnattributedHtml(translate, postJsonObject)
|
||||
|
||||
return (titleStr, replyAvatarImageInPost,
|
||||
containerClassIcons, containerClass)
|
||||
|
||||
|
||||
def replyToYourselfHtml(translate: {}, iconsPath: str) -> str:
|
||||
def replyToYourselfHtml(translate: {}, ) -> str:
|
||||
"""Returns html for a title which is a reply to yourself
|
||||
"""
|
||||
return ' <img loading="lazy" title="' + \
|
||||
translate['replying to themselves'] + \
|
||||
'" alt="' + translate['replying to themselves'] + \
|
||||
'" src="/' + iconsPath + \
|
||||
'" src="/icons' + \
|
||||
'/reply.png" class="announceOrReply"/>\n'
|
||||
|
||||
|
||||
def replyToUnknownHtml(translate: {}, iconsPath: str,
|
||||
def replyToUnknownHtml(translate: {},
|
||||
postJsonObject: {}) -> str:
|
||||
"""Returns the html title for a reply to an unknown handle
|
||||
"""
|
||||
return ' <img loading="lazy" title="' + \
|
||||
translate['replying to'] + '" alt="' + \
|
||||
translate['replying to'] + '" src="/' + \
|
||||
iconsPath + \
|
||||
translate['replying to'] + '" src="/icons' + \
|
||||
'/reply.png" class="announceOrReply"/>\n' + \
|
||||
' <a href="' + \
|
||||
postJsonObject['object']['inReplyTo'] + \
|
||||
'" class="announceOrReply">@unknown</a>\n'
|
||||
|
||||
|
||||
def replyWithUnknownPathHtml(translate: {}, iconsPath: str,
|
||||
def replyWithUnknownPathHtml(translate: {},
|
||||
postJsonObject: {},
|
||||
postDomain: str) -> str:
|
||||
"""Returns html title for a reply with an unknown path
|
||||
|
@ -832,8 +835,7 @@ def replyWithUnknownPathHtml(translate: {}, iconsPath: str,
|
|||
return ' <img loading="lazy" title="' + \
|
||||
translate['replying to'] + \
|
||||
'" alt="' + translate['replying to'] + \
|
||||
'" src="/' + \
|
||||
iconsPath + '/reply.png" ' + \
|
||||
'" src="/icons/reply.png" ' + \
|
||||
'class="announceOrReply"/>\n' + \
|
||||
' <a href="' + \
|
||||
postJsonObject['object']['inReplyTo'] + \
|
||||
|
@ -841,7 +843,7 @@ def replyWithUnknownPathHtml(translate: {}, iconsPath: str,
|
|||
postDomain + '</a>\n'
|
||||
|
||||
|
||||
def getReplyHtml(translate: {}, iconsPath: str,
|
||||
def getReplyHtml(translate: {},
|
||||
inReplyTo: str, replyDisplayName: str) -> str:
|
||||
"""Returns html title for a reply
|
||||
"""
|
||||
|
@ -849,14 +851,14 @@ def getReplyHtml(translate: {}, iconsPath: str,
|
|||
'<img loading="lazy" title="' + \
|
||||
translate['replying to'] + '" alt="' + \
|
||||
translate['replying to'] + '" src="/' + \
|
||||
iconsPath + '/reply.png" ' + \
|
||||
'icons/reply.png" ' + \
|
||||
'class="announceOrReply"/>\n' + \
|
||||
' <a href="' + inReplyTo + \
|
||||
'" class="announceOrReply">' + \
|
||||
replyDisplayName + '</a>\n'
|
||||
|
||||
|
||||
def getReplyWithoutDisplayName(translate: {}, iconsPath: str,
|
||||
def getReplyWithoutDisplayName(translate: {},
|
||||
inReplyTo: str,
|
||||
replyNickname: str, replyDomain: str) -> str:
|
||||
"""Returns html for a reply without a display name,
|
||||
|
@ -865,7 +867,7 @@ def getReplyWithoutDisplayName(translate: {}, iconsPath: str,
|
|||
return ' ' + \
|
||||
'<img loading="lazy" title="' + translate['replying to'] + \
|
||||
'" alt="' + translate['replying to'] + \
|
||||
'" src="/' + iconsPath + '/reply.png" ' + \
|
||||
'" src="/icons/reply.png" ' + \
|
||||
'class="announceOrReply"/>\n' + ' <a href="' + \
|
||||
inReplyTo + '" class="announceOrReply">@' + \
|
||||
replyNickname + '@' + replyDomain + '</a>\n'
|
||||
|
@ -879,7 +881,6 @@ def getPostTitleReplyHtml(baseDir: str,
|
|||
postJsonObject: {},
|
||||
postActor: str,
|
||||
translate: {},
|
||||
iconsPath: str,
|
||||
enableTimingLog: bool,
|
||||
postStartTime,
|
||||
boxName: str,
|
||||
|
@ -903,7 +904,7 @@ def getPostTitleReplyHtml(baseDir: str,
|
|||
containerClassIcons = 'containericons darker'
|
||||
containerClass = 'container darker'
|
||||
if postJsonObject['object']['inReplyTo'].startswith(postActor):
|
||||
titleStr += replyToYourselfHtml(translate, iconsPath)
|
||||
titleStr += replyToYourselfHtml(translate)
|
||||
return (titleStr, replyAvatarImageInPost,
|
||||
containerClassIcons, containerClass)
|
||||
|
||||
|
@ -936,8 +937,7 @@ def getPostTitleReplyHtml(baseDir: str,
|
|||
logPostTiming(enableTimingLog, postStartTime, '13.6')
|
||||
|
||||
titleStr += \
|
||||
getReplyHtml(translate, iconsPath,
|
||||
inReplyTo, replyDisplayName)
|
||||
getReplyHtml(translate, inReplyTo, replyDisplayName)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '13.7')
|
||||
|
||||
|
@ -971,18 +971,19 @@ def getPostTitleReplyHtml(baseDir: str,
|
|||
translate['Show profile']
|
||||
replyAvatarImageInPost += \
|
||||
'" alt=" "' + \
|
||||
avatarPosition + '/></a>\n' + \
|
||||
' </div>\n'
|
||||
avatarPosition + \
|
||||
getBrokenLinkSubstitute() + \
|
||||
'/></a>\n </div>\n'
|
||||
else:
|
||||
inReplyTo = \
|
||||
postJsonObject['object']['inReplyTo']
|
||||
titleStr += \
|
||||
getReplyWithoutDisplayName(translate, iconsPath,
|
||||
getReplyWithoutDisplayName(translate,
|
||||
inReplyTo,
|
||||
replyNickname, replyDomain)
|
||||
else:
|
||||
titleStr += \
|
||||
replyToUnknownHtml(translate, iconsPath, postJsonObject)
|
||||
replyToUnknownHtml(translate, postJsonObject)
|
||||
else:
|
||||
postDomain = \
|
||||
postJsonObject['object']['inReplyTo']
|
||||
|
@ -993,7 +994,7 @@ def getPostTitleReplyHtml(baseDir: str,
|
|||
postDomain = postDomain.split('/', 1)[0]
|
||||
if postDomain:
|
||||
titleStr += \
|
||||
replyWithUnknownPathHtml(translate, iconsPath,
|
||||
replyWithUnknownPathHtml(translate,
|
||||
postJsonObject, postDomain)
|
||||
|
||||
return (titleStr, replyAvatarImageInPost,
|
||||
|
@ -1008,7 +1009,6 @@ def getPostTitleHtml(baseDir: str,
|
|||
postJsonObject: {},
|
||||
postActor: str,
|
||||
translate: {},
|
||||
iconsPath: str,
|
||||
enableTimingLog: bool,
|
||||
postStartTime,
|
||||
boxName: str,
|
||||
|
@ -1037,7 +1037,6 @@ def getPostTitleHtml(baseDir: str,
|
|||
postJsonObject,
|
||||
postActor,
|
||||
translate,
|
||||
iconsPath,
|
||||
enableTimingLog,
|
||||
postStartTime,
|
||||
boxName,
|
||||
|
@ -1057,7 +1056,6 @@ def getPostTitleHtml(baseDir: str,
|
|||
postJsonObject,
|
||||
postActor,
|
||||
translate,
|
||||
iconsPath,
|
||||
enableTimingLog,
|
||||
postStartTime,
|
||||
boxName,
|
||||
|
@ -1098,7 +1096,7 @@ def getFooterWithIcons(showIcons: bool,
|
|||
|
||||
def individualPostAsHtml(allowDownloads: bool,
|
||||
recentPostsCache: {}, maxRecentPosts: int,
|
||||
iconsPath: str, translate: {},
|
||||
translate: {},
|
||||
pageNumber: int, baseDir: str,
|
||||
session, wfRequest: {}, personCache: {},
|
||||
nickname: str, domain: str, port: int,
|
||||
|
@ -1308,7 +1306,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
if showDMicon:
|
||||
titleStr = \
|
||||
titleStr + ' <img loading="lazy" src="/' + \
|
||||
iconsPath + '/dm.png" class="DMicon"/>\n'
|
||||
'icons/dm.png" class="DMicon"/>\n'
|
||||
|
||||
# check if replying is permitted
|
||||
commentsEnabled = True
|
||||
|
@ -1319,7 +1317,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
replyStr = getReplyIconHtml(nickname, isPublicRepeat,
|
||||
showIcons, commentsEnabled,
|
||||
postJsonObject, pageNumberParam,
|
||||
iconsPath, translate)
|
||||
translate)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '10')
|
||||
|
||||
|
@ -1329,7 +1327,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
|
||||
editStr = getEditIconHtml(baseDir, nickname, domainFull,
|
||||
postJsonObject, actorNickname,
|
||||
translate, iconsPath, isEvent)
|
||||
translate, isEvent)
|
||||
|
||||
announceStr = \
|
||||
getAnnounceIconHtml(nickname, domainFull,
|
||||
|
@ -1340,7 +1338,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
translate,
|
||||
pageNumberParam,
|
||||
timelinePostBookmark,
|
||||
boxName, iconsPath)
|
||||
boxName)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '12')
|
||||
|
||||
|
@ -1359,7 +1357,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
postStartTime,
|
||||
translate, pageNumberParam,
|
||||
timelinePostBookmark,
|
||||
boxName, iconsPath)
|
||||
boxName)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '12.5')
|
||||
|
||||
|
@ -1371,8 +1369,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
enableTimingLog,
|
||||
postStartTime, boxName,
|
||||
pageNumberParam,
|
||||
timelinePostBookmark,
|
||||
iconsPath)
|
||||
timelinePostBookmark)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '12.9')
|
||||
|
||||
|
@ -1387,7 +1384,6 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
nickname, domainFull,
|
||||
allowDeletion,
|
||||
pageNumberParam,
|
||||
iconsPath,
|
||||
boxName,
|
||||
timelinePostBookmark,
|
||||
translate)
|
||||
|
@ -1399,7 +1395,6 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
messageId,
|
||||
postJsonObject,
|
||||
pageNumberParam,
|
||||
iconsPath,
|
||||
translate)
|
||||
|
||||
logPostTiming(enableTimingLog, postStartTime, '13.1')
|
||||
|
@ -1416,7 +1411,6 @@ def individualPostAsHtml(allowDownloads: bool,
|
|||
postJsonObject,
|
||||
postActor,
|
||||
translate,
|
||||
iconsPath,
|
||||
enableTimingLog,
|
||||
postStartTime,
|
||||
boxName,
|
||||
|
@ -1613,7 +1607,6 @@ def htmlIndividualPost(cssCache: {},
|
|||
showPublishedDateOnly: bool) -> str:
|
||||
"""Show an individual post as html
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
postStr = ''
|
||||
if likedBy:
|
||||
likedByNickname = getNicknameFromActor(likedBy)
|
||||
|
@ -1649,7 +1642,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
|
||||
postStr += \
|
||||
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest, personCache,
|
||||
nickname, domain, port, postJsonObject,
|
||||
None, True, False,
|
||||
|
@ -1672,7 +1665,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
postStr = \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port,
|
||||
|
@ -1701,7 +1694,7 @@ def htmlIndividualPost(cssCache: {},
|
|||
postStr += \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port, item,
|
||||
|
@ -1728,14 +1721,13 @@ def htmlPostReplies(cssCache: {},
|
|||
showPublishedDateOnly: bool) -> str:
|
||||
"""Show the replies to an individual post as html
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
repliesStr = ''
|
||||
if repliesJson.get('orderedItems'):
|
||||
for item in repliesJson['orderedItems']:
|
||||
repliesStr += \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest, personCache,
|
||||
nickname, domain, port, item,
|
||||
None, True, False,
|
||||
|
|
|
@ -35,7 +35,6 @@ from jami import getJamiAddress
|
|||
from webapp_frontscreen import htmlFrontScreen
|
||||
from webapp_utils import scheduledPostsExist
|
||||
from webapp_utils import getPersonAvatarUrl
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
from webapp_utils import addEmojiToDisplayName
|
||||
|
@ -256,7 +255,6 @@ def htmlProfileAfterSearch(cssCache: {},
|
|||
profileStr += ' </form>\n'
|
||||
profileStr += '</div>\n'
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
i = 0
|
||||
for item in parseUserFeed(session, outboxUrl, asHeader,
|
||||
projectVersion, httpPrefix, domain):
|
||||
|
@ -268,7 +266,7 @@ def htmlProfileAfterSearch(cssCache: {},
|
|||
continue
|
||||
profileStr += \
|
||||
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||
iconsPath, translate, None, baseDir,
|
||||
translate, None, baseDir,
|
||||
session, cachedWebfingers, personCache,
|
||||
nickname, domain, port,
|
||||
item, avatarUrl, False, False,
|
||||
|
@ -284,7 +282,7 @@ def htmlProfileAfterSearch(cssCache: {},
|
|||
|
||||
|
||||
def getProfileHeader(baseDir: str, nickname: str, domain: str,
|
||||
domainFull: str, translate: {}, iconsPath: str,
|
||||
domainFull: str, translate: {},
|
||||
defaultTimeline: str,
|
||||
displayName: str,
|
||||
avatarDescription: str,
|
||||
|
@ -313,7 +311,7 @@ def getProfileHeader(baseDir: str, nickname: str, domain: str,
|
|||
' <a href="/users/' + nickname + \
|
||||
'/qrcode.png" alt="' + translate['QR Code'] + '" title="' + \
|
||||
translate['QR Code'] + '">' + \
|
||||
'<img class="qrcode" src="/' + iconsPath + \
|
||||
'<img class="qrcode" src="/icons' + \
|
||||
'/qrcode.png" /></a></p>\n'
|
||||
htmlStr += ' <p>' + profileDescriptionShort + '</p>\n'
|
||||
htmlStr += loginButton
|
||||
|
@ -481,17 +479,16 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
donateSection += ' </center>\n'
|
||||
donateSection += '</div>\n'
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
if authorized:
|
||||
editProfileStr = \
|
||||
'<a class="imageAnchor" href="' + usersPath + '/editprofile">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/edit.png" title="' + translate['Edit'] + \
|
||||
'" alt="| ' + translate['Edit'] + '" class="timelineicon"/></a>\n'
|
||||
|
||||
logoutStr = \
|
||||
'<a class="imageAnchor" href="/logout">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/logout.png" title="' + translate['Logout'] + \
|
||||
'" alt="| ' + translate['Logout'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -564,7 +561,7 @@ def htmlProfile(rssIconAtTop: bool,
|
|||
avatarUrl = profileJson['icon']['url']
|
||||
profileHeaderStr = \
|
||||
getProfileHeader(baseDir, nickname, domain,
|
||||
domainFull, translate, iconsPath,
|
||||
domainFull, translate,
|
||||
defaultTimeline, displayName,
|
||||
avatarDescription,
|
||||
profileDescriptionShort,
|
||||
|
@ -672,7 +669,6 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
"""Shows posts on the profile screen
|
||||
These should only be public posts
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
separatorStr = htmlPostSeparator(baseDir, None)
|
||||
profileStr = ''
|
||||
maxItems = 4
|
||||
|
@ -697,7 +693,7 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
|
|||
postStr = \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port, item,
|
||||
|
@ -728,7 +724,6 @@ def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
|
|||
"""
|
||||
profileStr = ''
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
if authorized and pageNumber:
|
||||
if authorized and pageNumber > 1:
|
||||
# page up arrow
|
||||
|
@ -737,7 +732,7 @@ def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
|
|||
' <a href="' + actor + '/' + feedName + \
|
||||
'?page=' + str(pageNumber - 1) + '#buttonheader' + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pageup.png" title="' + \
|
||||
'icons/pageup.png" title="' + \
|
||||
translate['Page up'] + '" alt="' + \
|
||||
translate['Page up'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
@ -757,7 +752,7 @@ def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
|
|||
' <a href="' + actor + '/' + feedName + \
|
||||
'?page=' + str(pageNumber + 1) + '#buttonheader' + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pagedown.png" title="' + \
|
||||
'icons/pagedown.png" title="' + \
|
||||
translate['Page down'] + '" alt="' + \
|
||||
translate['Page down'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
|
|
@ -23,7 +23,6 @@ from utils import getHashtagCategory
|
|||
from feeds import rss2TagHeader
|
||||
from feeds import rss2TagFooter
|
||||
from webapp_utils import getAltPath
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import getImageFile
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
from webapp_utils import htmlFooter
|
||||
|
@ -102,7 +101,6 @@ def htmlSearchSharedItems(cssCache: {}, translate: {},
|
|||
callingDomain: str) -> str:
|
||||
"""Search results for shared items
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
currPage = 1
|
||||
ctr = 0
|
||||
sharedItemsForm = ''
|
||||
|
@ -116,8 +114,10 @@ def htmlSearchSharedItems(cssCache: {}, translate: {},
|
|||
sharedItemsForm = \
|
||||
htmlHeaderWithExternalStyle(cssFilename)
|
||||
sharedItemsForm += \
|
||||
'<center><h1>' + translate['Shared Items Search'] + \
|
||||
'</h1></center>'
|
||||
'<center><h1>' + \
|
||||
'<a href="' + actor + '/search">' + \
|
||||
translate['Shared Items Search'] + \
|
||||
'</a></h1></center>'
|
||||
resultsExist = False
|
||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||
for handle in dirs:
|
||||
|
@ -213,14 +213,14 @@ def htmlSearchSharedItems(cssCache: {}, translate: {},
|
|||
'" type="submit" name="submitSearch">\n'
|
||||
sharedItemsForm += \
|
||||
' <img loading="lazy" ' + \
|
||||
'class="pageicon" src="/' + iconsPath + \
|
||||
'class="pageicon" src="/icons' + \
|
||||
'/pageup.png" title="' + \
|
||||
translate['Page up'] + \
|
||||
'" alt="' + translate['Page up'] + \
|
||||
'"/></a>\n'
|
||||
sharedItemsForm += ' </center>\n'
|
||||
sharedItemsForm += '</form>\n'
|
||||
resultsExist = True
|
||||
resultsExist = True
|
||||
ctr += 1
|
||||
if ctr >= resultsPerPage:
|
||||
currPage += 1
|
||||
|
@ -247,7 +247,7 @@ def htmlSearchSharedItems(cssCache: {}, translate: {},
|
|||
'" type="submit" name="submitSearch">\n'
|
||||
sharedItemsForm += \
|
||||
' <img loading="lazy" ' + \
|
||||
'class="pageicon" src="/' + iconsPath + \
|
||||
'class="pageicon" src="/icons' + \
|
||||
'/pagedown.png" title="' + \
|
||||
translate['Page down'] + \
|
||||
'" alt="' + translate['Page down'] + \
|
||||
|
@ -382,7 +382,8 @@ def htmlSearch(cssCache: {}, translate: {},
|
|||
return followStr
|
||||
|
||||
|
||||
def htmlSkillsSearch(cssCache: {}, translate: {}, baseDir: str,
|
||||
def htmlSkillsSearch(actor: str,
|
||||
cssCache: {}, translate: {}, baseDir: str,
|
||||
httpPrefix: str,
|
||||
skillsearch: str, instanceOnly: bool,
|
||||
postsPerPage: int) -> str:
|
||||
|
@ -473,8 +474,10 @@ def htmlSkillsSearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
|
||||
skillSearchForm = htmlHeaderWithExternalStyle(cssFilename)
|
||||
skillSearchForm += \
|
||||
'<center><h1>' + translate['Skills search'] + ': ' + \
|
||||
skillsearch + '</h1></center>'
|
||||
'<center><h1><a href = "' + actor + '/search">' + \
|
||||
translate['Skills search'] + ': ' + \
|
||||
skillsearch + \
|
||||
'</a></h1></center>'
|
||||
|
||||
if len(results) == 0:
|
||||
skillSearchForm += \
|
||||
|
@ -538,8 +541,15 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
htmlHeaderWithExternalStyle(cssFilename)
|
||||
|
||||
# add the page title
|
||||
domainFull = domain
|
||||
if port:
|
||||
if port != 80 and port != 443:
|
||||
domainFull = domain + ':' + str(port)
|
||||
actor = httpPrefix + '://' + domainFull + '/users/' + nickname
|
||||
historySearchForm += \
|
||||
'<center><h1>' + translate['Your Posts'] + '</h1></center>'
|
||||
'<center><h1><a href="' + actor + '/search">' + \
|
||||
translate['Your Posts'] + \
|
||||
'</a></h1></center>'
|
||||
|
||||
if len(boxFilenames) == 0:
|
||||
historySearchForm += \
|
||||
|
@ -547,7 +557,6 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
'</h5></center>'
|
||||
return historySearchForm
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
separatorStr = htmlPostSeparator(baseDir, None)
|
||||
|
||||
# ensure that the page number is in bounds
|
||||
|
@ -578,7 +587,7 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str,
|
|||
postStr = \
|
||||
individualPostAsHtml(True, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port,
|
||||
|
@ -623,7 +632,6 @@ def htmlHashtagSearch(cssCache: {},
|
|||
print('WARN: hashtag file not found ' + hashtagIndexFile)
|
||||
return None
|
||||
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
separatorStr = htmlPostSeparator(baseDir, None)
|
||||
|
||||
# check that the directory for the nickname exists
|
||||
|
@ -670,7 +678,7 @@ def htmlHashtagSearch(cssCache: {},
|
|||
hashtagSearchForm += \
|
||||
'<img style="width:3%;min-width:50px" ' + \
|
||||
'loading="lazy" alt="RSS 2.0" title="RSS 2.0" src="/' + \
|
||||
iconsPath + '/logorss.png" /></a></center>\n'
|
||||
'icons/logorss.png" /></a></center>\n'
|
||||
|
||||
# edit the category for this hashtag
|
||||
if isEditor(baseDir, nickname):
|
||||
|
@ -699,7 +707,7 @@ def htmlHashtagSearch(cssCache: {},
|
|||
' <a href="/tags/' + hashtag + '?page=' + \
|
||||
str(pageNumber - 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pageup.png" title="' + \
|
||||
'icons/pageup.png" title="' + \
|
||||
translate['Page up'] + \
|
||||
'" alt="' + translate['Page up'] + \
|
||||
'"></a>\n </center>\n'
|
||||
|
@ -744,7 +752,7 @@ def htmlHashtagSearch(cssCache: {},
|
|||
postStr = \
|
||||
individualPostAsHtml(allowDownloads, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, None,
|
||||
translate, None,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port,
|
||||
|
@ -769,7 +777,7 @@ def htmlHashtagSearch(cssCache: {},
|
|||
' <center>\n' + \
|
||||
' <a href="/tags/' + hashtag + \
|
||||
'?page=' + str(pageNumber + 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + iconsPath + \
|
||||
'"><img loading="lazy" class="pageicon" src="/icons' + \
|
||||
'/pagedown.png" title="' + translate['Page down'] + \
|
||||
'" alt="' + translate['Page down'] + '"></a>' + \
|
||||
' </center>'
|
||||
|
|
|
@ -12,7 +12,6 @@ from utils import isEditor
|
|||
from utils import removeIdEnding
|
||||
from follow import followerApprovalActive
|
||||
from person import isPersonSnoozed
|
||||
from webapp_utils import getIconsWebPath
|
||||
from webapp_utils import htmlPostSeparator
|
||||
from webapp_utils import getBannerFile
|
||||
from webapp_utils import htmlHeaderWithExternalStyle
|
||||
|
@ -112,10 +111,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
if boxName == 'moderation':
|
||||
os.remove(newReportFile)
|
||||
|
||||
# directory where icons are found
|
||||
# This changes depending upon theme
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
|
||||
separatorStr = ''
|
||||
if boxName != 'tlmedia':
|
||||
separatorStr = htmlPostSeparator(baseDir, None)
|
||||
|
@ -222,7 +217,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
'class="timelineicon" alt="' + \
|
||||
translate['Approve follow requests'] + \
|
||||
'" title="' + translate['Approve follow requests'] + \
|
||||
'" src="/' + iconsPath + '/person.png"/></a>\n'
|
||||
'" src="/icons/person.png"/></a>\n'
|
||||
break
|
||||
|
||||
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3')
|
||||
|
@ -279,7 +274,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newdm"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new DM'] + \
|
||||
'" alt="| ' + translate['Create a new DM'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -295,7 +290,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newblog"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new post'] + '" alt="| ' + \
|
||||
translate['Create a new post'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -309,7 +304,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newevent"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new event'] + '" alt="| ' + \
|
||||
translate['Create a new event'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -323,7 +318,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newshare"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new shared item'] + '" alt="| ' + \
|
||||
translate['Create a new shared item'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -338,7 +333,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newpost"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new post'] + '" alt="| ' + \
|
||||
translate['Create a new post'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -352,7 +347,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newfollowers"><img loading="lazy" src="/' + \
|
||||
iconsPath + '/newpost.png" title="' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new post'] + \
|
||||
'" alt="| ' + translate['Create a new post'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
|
@ -388,7 +383,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
sharesButtonStr, bookmarksButtonStr,
|
||||
eventsButtonStr, moderationButtonStr,
|
||||
newPostButtonStr, baseDir, nickname,
|
||||
domain, iconsPath, timelineStartTime,
|
||||
domain, timelineStartTime,
|
||||
newCalendarEvent, calendarPath,
|
||||
calendarImage, followApprovals,
|
||||
iconsAsButtons)
|
||||
|
@ -411,7 +406,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
# left column
|
||||
leftColumnStr = \
|
||||
getLeftColumnContent(baseDir, nickname, domainFull,
|
||||
httpPrefix, translate, iconsPath,
|
||||
httpPrefix, translate,
|
||||
editor, False, None, rssIconAtTop,
|
||||
True, False)
|
||||
tlStr += ' <td valign="top" class="col-left">' + \
|
||||
|
@ -430,7 +425,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
sharesButtonStr, bookmarksButtonStr,
|
||||
eventsButtonStr, moderationButtonStr,
|
||||
newPostButtonStr, baseDir, nickname,
|
||||
domain, iconsPath, timelineStartTime,
|
||||
domain, timelineStartTime,
|
||||
newCalendarEvent, calendarPath,
|
||||
calendarImage, followApprovals,
|
||||
iconsAsButtons)
|
||||
|
@ -495,7 +490,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
' <a href="' + usersPath + '/' + boxName + \
|
||||
'?page=' + str(pageNumber - 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pageup.png" title="' + \
|
||||
'icons/pageup.png" title="' + \
|
||||
translate['Page up'] + '" alt="' + \
|
||||
translate['Page up'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
@ -545,7 +540,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
currTlStr = \
|
||||
individualPostAsHtml(False, recentPostsCache,
|
||||
maxRecentPosts,
|
||||
iconsPath, translate, pageNumber,
|
||||
translate, pageNumber,
|
||||
baseDir, session, wfRequest,
|
||||
personCache,
|
||||
nickname, domain, port,
|
||||
|
@ -577,7 +572,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
' <a href="' + usersPath + '/' + boxName + '?page=' + \
|
||||
str(pageNumber + 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pagedown.png" title="' + \
|
||||
'icons/pagedown.png" title="' + \
|
||||
translate['Page down'] + '" alt="' + \
|
||||
translate['Page down'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
@ -590,7 +585,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
|
||||
# right column
|
||||
rightColumnStr = getRightColumnContent(baseDir, nickname, domainFull,
|
||||
httpPrefix, translate, iconsPath,
|
||||
httpPrefix, translate,
|
||||
moderator, editor,
|
||||
newswire, positiveVoting,
|
||||
False, None, True,
|
||||
|
@ -627,18 +622,20 @@ def htmlIndividualShare(actor: str, item: {}, translate: {},
|
|||
'<b>' + translate['Category'] + ':</b> ' + item['category'] + ' '
|
||||
profileStr += \
|
||||
'<b>' + translate['Location'] + ':</b> ' + item['location'] + '</p>\n'
|
||||
if showContact:
|
||||
contactActor = item['actor']
|
||||
profileStr += \
|
||||
'<p><a href="' + actor + \
|
||||
'?replydm=sharedesc:' + item['displayName'] + \
|
||||
'?mention=' + contactActor + '"><button class="button">' + \
|
||||
translate['Contact'] + '</button></a>\n'
|
||||
if removeButton:
|
||||
profileStr += \
|
||||
' <a href="' + actor + '?rmshare=' + item['displayName'] + \
|
||||
'"><button class="button">' + \
|
||||
translate['Remove'] + '</button></a>\n'
|
||||
sharedesc = item['displayName']
|
||||
if '<' not in sharedesc and '?' not in sharedesc:
|
||||
if showContact:
|
||||
contactActor = item['actor']
|
||||
profileStr += \
|
||||
'<p><a href="' + actor + \
|
||||
'?replydm=sharedesc:' + sharedesc + \
|
||||
'?mention=' + contactActor + '"><button class="button">' + \
|
||||
translate['Contact'] + '</button></a>\n'
|
||||
if removeButton:
|
||||
profileStr += \
|
||||
' <a href="' + actor + '?rmshare=' + sharedesc + \
|
||||
'"><button class="button">' + \
|
||||
translate['Remove'] + '</button></a>\n'
|
||||
profileStr += '</div>\n'
|
||||
return profileStr
|
||||
|
||||
|
@ -660,13 +657,12 @@ def htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
|
|||
timelineStr = ''
|
||||
|
||||
if pageNumber > 1:
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
timelineStr += \
|
||||
' <center>\n' + \
|
||||
' <a href="' + actor + '/tlshares?page=' + \
|
||||
str(pageNumber - 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pageup.png" title="' + translate['Page up'] + \
|
||||
'icons/pageup.png" title="' + translate['Page up'] + \
|
||||
'" alt="' + translate['Page up'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
||||
|
@ -684,13 +680,12 @@ def htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
|
|||
timelineStr += separatorStr
|
||||
|
||||
if not lastPage:
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
timelineStr += \
|
||||
' <center>\n' + \
|
||||
' <a href="' + actor + '/tlshares?page=' + \
|
||||
str(pageNumber + 1) + \
|
||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
||||
iconsPath + '/pagedown.png" title="' + translate['Page down'] + \
|
||||
'icons/pagedown.png" title="' + translate['Page down'] + \
|
||||
'" alt="' + translate['Page down'] + '"></a>\n' + \
|
||||
' </center>\n'
|
||||
|
||||
|
|
|
@ -68,8 +68,7 @@ def htmlHashtagBlocked(cssCache: {}, baseDir: str, translate: {}) -> str:
|
|||
def headerButtonsFrontScreen(translate: {},
|
||||
nickname: str, boxName: str,
|
||||
authorized: bool,
|
||||
iconsAsButtons: bool,
|
||||
iconsPath: bool) -> str:
|
||||
iconsAsButtons: bool) -> str:
|
||||
"""Returns the header buttons for the front page of a news instance
|
||||
"""
|
||||
headerStr = ''
|
||||
|
@ -110,13 +109,13 @@ def headerButtonsFrontScreen(translate: {},
|
|||
headerStr += \
|
||||
' <a href="' + \
|
||||
'/users/news/newswiremobile">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/newswire.png" title="' + translate['Newswire'] + \
|
||||
'" alt="| ' + translate['Newswire'] + '"/></a>\n'
|
||||
headerStr += \
|
||||
' <a href="' + \
|
||||
'/users/news/linksmobile">' + \
|
||||
'<img loading="lazy" src="/' + iconsPath + \
|
||||
'<img loading="lazy" src="/icons' + \
|
||||
'/links.png" title="' + translate['Links'] + \
|
||||
'" alt="| ' + translate['Links'] + '"/></a>\n'
|
||||
else:
|
||||
|
@ -390,17 +389,6 @@ def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
|
|||
return None
|
||||
|
||||
|
||||
def getIconsWebPath(baseDir: str) -> str:
|
||||
"""Returns the web path where icons exist
|
||||
"""
|
||||
iconsPath = 'icons'
|
||||
theme = getConfigParam(baseDir, 'theme')
|
||||
if theme:
|
||||
if os.path.isdir(baseDir + '/theme/' + theme + '/icons'):
|
||||
iconsPath = 'icons/' + theme
|
||||
return iconsPath
|
||||
|
||||
|
||||
def scheduledPostsExist(baseDir: str, nickname: str, domain: str) -> bool:
|
||||
"""Returns true if there are posts scheduled to be delivered
|
||||
"""
|
||||
|
@ -422,24 +410,26 @@ def sharesTimelineJson(actor: str, pageNumber: int, itemsPerPage: int,
|
|||
allSharesJson = {}
|
||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||
for handle in dirs:
|
||||
if '@' in handle:
|
||||
accountDir = baseDir + '/accounts/' + handle
|
||||
sharesFilename = accountDir + '/shares.json'
|
||||
if os.path.isfile(sharesFilename):
|
||||
sharesJson = loadJson(sharesFilename)
|
||||
if not sharesJson:
|
||||
continue
|
||||
nickname = handle.split('@')[0]
|
||||
# actor who owns this share
|
||||
owner = actor.split('/users/')[0] + '/users/' + nickname
|
||||
ctr = 0
|
||||
for itemID, item in sharesJson.items():
|
||||
# assign owner to the item
|
||||
item['actor'] = owner
|
||||
allSharesJson[str(item['published'])] = item
|
||||
ctr += 1
|
||||
if ctr >= maxSharesPerAccount:
|
||||
break
|
||||
if '@' not in handle:
|
||||
continue
|
||||
accountDir = baseDir + '/accounts/' + handle
|
||||
sharesFilename = accountDir + '/shares.json'
|
||||
if not os.path.isfile(sharesFilename):
|
||||
continue
|
||||
sharesJson = loadJson(sharesFilename)
|
||||
if not sharesJson:
|
||||
continue
|
||||
nickname = handle.split('@')[0]
|
||||
# actor who owns this share
|
||||
owner = actor.split('/users/')[0] + '/users/' + nickname
|
||||
ctr = 0
|
||||
for itemID, item in sharesJson.items():
|
||||
# assign owner to the item
|
||||
item['actor'] = owner
|
||||
allSharesJson[str(item['published'])] = item
|
||||
ctr += 1
|
||||
if ctr >= maxSharesPerAccount:
|
||||
break
|
||||
# sort the shared items in descending order of publication date
|
||||
sharesJson = OrderedDict(sorted(allSharesJson.items(), reverse=True))
|
||||
lastPage = False
|
||||
|
@ -835,7 +825,6 @@ def getPostAttachmentsAsHtml(postJsonObject: {}, boxName: str, translate: {},
|
|||
def htmlPostSeparator(baseDir: str, column: str) -> str:
|
||||
"""Returns the html for a timeline post separator image
|
||||
"""
|
||||
iconsPath = getIconsWebPath(baseDir)
|
||||
theme = getConfigParam(baseDir, 'theme')
|
||||
filename = 'separator.png'
|
||||
separatorClass = "postSeparatorImage"
|
||||
|
@ -847,7 +836,7 @@ def htmlPostSeparator(baseDir: str, column: str) -> str:
|
|||
if os.path.isfile(separatorImageFilename):
|
||||
separatorStr = \
|
||||
'<div class="' + separatorClass + '"><center>' + \
|
||||
'<img src="/' + iconsPath + '/' + filename + '"/>' + \
|
||||
'<img src="/icons/' + filename + '"/>' + \
|
||||
'</center></div>\n'
|
||||
return separatorStr
|
||||
|
||||
|
|