From 7387f7f5e9751c8681ddbc35bfddf609fac4e11f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 5 Jan 2021 23:09:04 +0000 Subject: [PATCH 01/16] Extra test --- tests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests.py b/tests.py index d29671e2a..e76a3b74d 100644 --- a/tests.py +++ b/tests.py @@ -3041,6 +3041,23 @@ def testLinksWithinPost() -> None: '' + \ 'freedombone.net

' + content = "

Some text

Other text

More text

" + \ + "
Errno::EOHNOES (No such file or rodent @ " + \
+        "ik_right - /tmp/blah.png)

" + \ + "(" + \ + "wuh)

Oh yeah like for sure

" + \ + "

Ground sloth tin opener

" + \ + "

#taggedthing

" + postJsonObject = \ + createPublicPost(baseDir, nickname, domain, port, httpPrefix, + content, + False, False, False, True, + None, None, False, None) + assert postJsonObject['object']['content'] == content + def runAllTests(): print('Running tests...') From a3ed814e9f2734670cd2c5efab784ae436c7e0c3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 10:38:33 +0000 Subject: [PATCH 02/16] Default favicon for newswire, if site favicon is not available --- daemon.py | 23 +++++++++++++----- theme/blue/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/debian/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/default/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/hacker/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/henge/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/indymediaclassic/icons/favicon.ico | Bin 1150 -> 766 bytes .../icons/newswire_favicon.ico | Bin 0 -> 766 bytes theme/indymediamodern/icons/favicon.ico | Bin 1150 -> 766 bytes .../icons/newswire_favicon.ico | Bin 0 -> 766 bytes theme/lcd/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/light/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/night/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/purple/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/rc3/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/solidaric/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/starlight/icons/newswire_favicon.ico | Bin 0 -> 1150 bytes theme/zen/icons/newswire_favicon.ico | Bin 0 -> 198 bytes webapp_column_right.py | 4 +-- 19 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 theme/blue/icons/newswire_favicon.ico create mode 100644 theme/debian/icons/newswire_favicon.ico create mode 100644 theme/default/icons/newswire_favicon.ico create mode 100644 theme/hacker/icons/newswire_favicon.ico create mode 100644 theme/henge/icons/newswire_favicon.ico create mode 100644 theme/indymediaclassic/icons/newswire_favicon.ico create mode 100644 theme/indymediamodern/icons/newswire_favicon.ico create mode 100644 theme/lcd/icons/newswire_favicon.ico create mode 100644 theme/light/icons/newswire_favicon.ico create mode 100644 theme/night/icons/newswire_favicon.ico create mode 100644 theme/purple/icons/newswire_favicon.ico create mode 100644 theme/rc3/icons/newswire_favicon.ico create mode 100644 theme/solidaric/icons/newswire_favicon.ico create mode 100644 theme/starlight/icons/newswire_favicon.ico create mode 100644 theme/zen/icons/newswire_favicon.ico diff --git a/daemon.py b/daemon.py index 4eb105fbd..4bd818d5b 100644 --- a/daemon.py +++ b/daemon.py @@ -1127,6 +1127,7 @@ class PubServer(BaseHTTPRequestHandler): if self.path.startswith('/icons/') or \ self.path.startswith('/avatars/') or \ self.path.startswith('/favicon.ico') or \ + self.path.startswith('/newswire_favicon.ico') or \ self.path.startswith('/categories.xml') or \ self.path.startswith('/newswire.xml'): return False @@ -4835,18 +4836,19 @@ class PubServer(BaseHTTPRequestHandler): 'show logout', 'send manifest') def _getFavicon(self, callingDomain: str, - baseDir: str, debug: bool) -> None: - """Return the favicon + baseDir: str, debug: bool, + favFile='favicon.ico') -> None: + """Return the site favicon or default newswire favicon """ favType = 'image/x-icon' - favFilename = 'favicon.ico' + favFilename = favFile if self._hasAccept(callingDomain): if 'image/webp' in self.headers['Accept']: favType = 'image/webp' - favFilename = 'favicon.webp' + favFilename = favFile.split('.')[0] + '.webp' if 'image/avif' in self.headers['Accept']: favType = 'image/avif' - favFilename = 'favicon.avif' + favFilename = favFile.split('.')[0] + '.avif' if not self.server.themeName: self.themeName = getConfigParam(baseDir, 'theme') if not self.server.themeName: @@ -9731,7 +9733,16 @@ class PubServer(BaseHTTPRequestHandler): # favicon image if 'favicon.ico' in self.path: self._getFavicon(callingDomain, self.server.baseDir, - self.server.debug) + self.server.debug, + 'favicon.ico') + return + + # default newswire favicon, for links to sites which + # have no favicon + if 'newswire_favicon.ico' in self.path: + self._getFavicon(callingDomain, self.server.baseDir, + self.server.debug, + 'newswire_favicon.ico') return # check authorization diff --git a/theme/blue/icons/newswire_favicon.ico b/theme/blue/icons/newswire_favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f GIT binary patch literal 1150 zcmd6iF$%&!6hud`RbpdnN^griEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7me`&;0Q`o-a4t*=gzM7=oK>Nf6wQ~`OUs>G9IP6vt{$7Mk$XM zRkwMWXGJ4q8hLHrjK7vXFO#jMb+J9$`_zm3WJCGbeYAgUu5&}akS2eK+kW*SZ%nfp zU&nkgU3qcL*QNiG?b=tfim&>h0uIE6C?3GR1a?w8Xc(3 literal 0 HcmV?d00001 diff --git a/theme/henge/icons/newswire_favicon.ico b/theme/henge/icons/newswire_favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..10bdfcfe5f1931d42190b0f432a91a6f2c74d6ff GIT binary patch literal 1150 zcmd5%I|{-;6db`;iH)r(y@f~c2)4F1g4!q+9>b$(=RrJzAQ7T*78!Yww~@uhgxPs- z-pqc07XK^**BsL}&<8LiC{cOoq@-^(-&6rfA!Gjc{BpLq+V}Okom_XeY@SprAz%~_SLN9tKKMqBe5p-ci?aXb{AlK28t7XW8g6%20%3;n0*2=p1i97 literal 0 HcmV?d00001 diff --git a/theme/indymediaclassic/icons/favicon.ico b/theme/indymediaclassic/icons/favicon.ico index c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f..061668e430e42781e50011bfa9f56f877e7015d3 100644 GIT binary patch literal 766 zcmb`FO-{ow6ojXM6i(13%92AM%8_~iP;Ig22;nFV7iexkmu6>GUZluvhHriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7GUZluvhHGUZluvhHriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7GUZluvhHriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7JjWwN!j7~8#_PrbNJ)|U^RN9%{?+SljvY4ZEH=~wUb zhBTXTb;uXel^2J6G5wcpY+cPt-s*!AI1(Eoe*lL&u)6}=3vfHpHwT_eV#I$YBba>w D0!7)g literal 0 HcmV?d00001 diff --git a/theme/solidaric/icons/newswire_favicon.ico b/theme/solidaric/icons/newswire_favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f GIT binary patch literal 1150 zcmd6iF$%&!6hud`RbpdnN^griEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3zXda50?4^q~Q1u1H%I#ZUEx>e;F9| o|72ij|IEP9{Fs5^$8n%Ke+Gts@jxuk!0_K5h>`Vz*ktGj0Qe9${Qv*} literal 0 HcmV?d00001 diff --git a/webapp_column_right.py b/webapp_column_right.py index d52717fec..32aef9b41 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -197,10 +197,10 @@ def _getNewswireFavicon(url: str) -> str: """Returns a favicon url from the given article link """ if '://' not in url: - return None + return '/newswire_favicon.ico' if url.startswith('http://'): if not (url.endswith('.onion') or url.endswith('.i2p')): - return None + return '/newswire_favicon.ico' domain = url.split('://')[1] if '/' not in domain: return url + '/favicon.ico' From 2d7a8b7d15f919e23eba8365feee3b20cbd9945f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 10:46:35 +0000 Subject: [PATCH 03/16] Substitute a default favicon --- webapp_column_right.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_column_right.py b/webapp_column_right.py index 32aef9b41..b22e4e800 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -190,7 +190,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, def _getBrokenFavSubstitute() -> str: """Substitute link used if a favicon is not available """ - return " onerror=\"this.onerror=null; this.style='width:0%'; this.src=''\"" + return " onerror=\"this.onerror=null; this.src='/default_favicon.ico'\"" def _getNewswireFavicon(url: str) -> str: From 3f8f26feb5e01511c0299079a857a240dcdba0e6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 11:04:54 +0000 Subject: [PATCH 04/16] Newswire favicons --- .../indymediaclassic/icons/newswire_favicon.ico | Bin 766 -> 198 bytes .../indymediamodern/icons/newswire_favicon.ico | Bin 766 -> 198 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/theme/indymediaclassic/icons/newswire_favicon.ico b/theme/indymediaclassic/icons/newswire_favicon.ico index 061668e430e42781e50011bfa9f56f877e7015d3..7aa32157dcd770f6097e70f8715c9f8ad04a3f27 100644 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXlCYw-U+1H*hE?g!%IK>QepKLYU&ApTR$ Y!0^wQf#E+h5H~|Hko^zD2g-vm09?EptpET3 literal 766 zcmb`FO-{ow6ojXM6i(13%92AM%8_~iP;Ig22;nFV7iexkmu6>GUZluvhHfEXlCYw-U+1H*hE?g!%IK>QepKLYU&ApTR$ Y!0^wQf#E+h5H~|Hko^zD2g-vm09?EptpET3 literal 766 zcmb`FO-{ow6ojXM6i(13%92AM%8_~iP;Ig22;nFV7iexkmu6>GUZluvhH Date: Thu, 7 Jan 2021 11:19:18 +0000 Subject: [PATCH 05/16] Newswire favicons --- theme/blue/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/debian/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/default/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/hacker/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/henge/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/lcd/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/light/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/night/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/purple/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/rc3/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/solidaric/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/starlight/icons/favicon.ico | Bin 1150 -> 1150 bytes theme/starlight/icons/newswire_favicon.ico | Bin 1150 -> 198 bytes theme/zen/icons/newswire_favicon.ico | Bin 198 -> 198 bytes 14 files changed, 0 insertions(+), 0 deletions(-) diff --git a/theme/blue/icons/newswire_favicon.ico b/theme/blue/icons/newswire_favicon.ico index c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f..a368686dcbd23e359418e554f1059424ae6cd433 100644 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXl?3$$b=fTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3$$b=fTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3$$b=fTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3us&isbpaI|DSme`&;0Q`o-a4t*=gzM7=oK>Nf6wQ~`OUs>G9IP6vt{$7Mk$XM zRkwMWXGJ4q8hLHrjK7vXFO#jMb+J9$`_zm3WJCGbeYAgUu5&}akS2eK+kW*SZ%nfp zU&nkgU3qcL*QNiG?b=tfim&>h0uIE6C?3GR1a?w8Xc(3 diff --git a/theme/henge/icons/newswire_favicon.ico b/theme/henge/icons/newswire_favicon.ico index 10bdfcfe5f1931d42190b0f432a91a6f2c74d6ff..279a9d6fb822879a3c298503b2b39c03c8da84e8 100644 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXl?3sjdif~EfdXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTb$(=RrJzAQ7T*78!Yww~@uhgxPs- z-pqc07XK^**BsL}&<8LiC{cOoq@-^(-&6rfA!Gjc{BpLq+V}Okom_XeY@SprAz%~_SLN9tKKMqBe5p-ci?aXb{AlK28t7XW8g6%20%3;n0*2=p1i97 diff --git a/theme/lcd/icons/newswire_favicon.ico b/theme/lcd/icons/newswire_favicon.ico index c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f..eeef176c9e1aa1b8575fe4bf12e3a7ddd704a9f9 100644 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXl?3-DSRgQfoeXJD8Q#Qi{g9EcwS@kb#3 e0mOf*85sTnmHlT1;$|oYvj2hjKzSIZL_Yv)Pc)1G literal 1150 zcmd6iF$%&!6hud`RbpdnN^griEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3$$b=fTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3$$b=fTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3;de=6D;-rKLf*jAnpg^<3Rivh(7}H f4riEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3;eg-1eW^$pMhaM5cdP|aUgyS#2JjWwN!j7~8#_PrbNJ)|U^RN9%{?+SljvY4ZEH=~wUb zhBTXTb;uXel^2J6G5wcpY+cPt-s*!AI1(Eoe*lL&u)6}=3vfHpHwT_eV#I$YBba>w D0!7)g diff --git a/theme/solidaric/icons/newswire_favicon.ico b/theme/solidaric/icons/newswire_favicon.ico index c7cb1bbbe0ff1c57a5974ddeb09fc6dc8e31d96f..302007a7049532e9b7c1367d53ffa27cfeec96cb 100644 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXl?3-IvpfTjNbXJD8Q#Qi{g9EcwS@kb#3 f0mOf*85sTriEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7d-pCsU#V$lZr0EPr5DsP?C=v&VBr9-2TG5>phHQQb7`+D6@sykaYPpXvi zI8k+-C!;K{giIr^&71Mp(&c5cwX_)9vz<@9xJlNR58X%mhvquh=ksau`?&5`@AHN< zn{jo>7t)m%hkP;pmuzfb%?iHig911bYa)LDhdZ#n0Gl&#JJB}=o>O7~lo`S73!rww A%K!iX literal 1150 zcmd6iF$%&!6hud`RbpdnN^griEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3uLG51xx+^&%iJri2H%~I1oPu;*UW5 f1Bm}rGcf!!W?=Zw48+Y)3}pWU@qzL%Oo@H~{WdkB literal 1150 zcmd6iF$%&!6hud`RbpdnN^griEjn+X0&v#!*{v3}tERlq{d;~rpPuafdfiU0f41u1 zOT8G^Ywhb~RFvX<6>IZ8lj>bwbGw$8QhT=J)Jwm~hVrrh(f+Zy&JA%PPkcyyUVVs- zc{bzLF)rpSFO6|2|CelPU(G7s>QfbPW^GvI1327){T0|=fZLJW7fEXl?3v?{p2A2B&pMhaM5cdP|aUgyS#2fEXl?3zXda50?4^q~Q1u1H%I#ZUEx>e;F9| o|72ij|IEP9{Fs5^$8n%Ke+Gts@jxuk!0_K5h>`Vz*ktGj0Qe9${Qv*} From 428fb88f2c8d12e9307d2dafec1e1d731f5fdd82 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 11:24:10 +0000 Subject: [PATCH 06/16] Order of precedence --- daemon.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/daemon.py b/daemon.py index 4bd818d5b..fe2e8c033 100644 --- a/daemon.py +++ b/daemon.py @@ -9730,13 +9730,6 @@ class PubServer(BaseHTTPRequestHandler): GETstartTime, GETtimings) return - # favicon image - if 'favicon.ico' in self.path: - self._getFavicon(callingDomain, self.server.baseDir, - self.server.debug, - 'favicon.ico') - return - # default newswire favicon, for links to sites which # have no favicon if 'newswire_favicon.ico' in self.path: @@ -9745,6 +9738,13 @@ class PubServer(BaseHTTPRequestHandler): 'newswire_favicon.ico') return + # favicon image + if 'favicon.ico' in self.path: + self._getFavicon(callingDomain, self.server.baseDir, + self.server.debug, + 'favicon.ico') + return + # check authorization authorized = self._isAuthorized() if self.server.debug: From c62223815b709feb69fb7e7146bd6de6b9759d6f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 11:39:15 +0000 Subject: [PATCH 07/16] Simplify --- daemon.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/daemon.py b/daemon.py index fe2e8c033..45ba3609b 100644 --- a/daemon.py +++ b/daemon.py @@ -4837,18 +4837,17 @@ class PubServer(BaseHTTPRequestHandler): def _getFavicon(self, callingDomain: str, baseDir: str, debug: bool, - favFile='favicon.ico') -> None: + favFilename: str) -> None: """Return the site favicon or default newswire favicon """ favType = 'image/x-icon' - favFilename = favFile if self._hasAccept(callingDomain): if 'image/webp' in self.headers['Accept']: favType = 'image/webp' - favFilename = favFile.split('.')[0] + '.webp' + favFilename = favFilename.split('.')[0] + '.webp' if 'image/avif' in self.headers['Accept']: favType = 'image/avif' - favFilename = favFile.split('.')[0] + '.avif' + favFilename = favFilename.split('.')[0] + '.avif' if not self.server.themeName: self.themeName = getConfigParam(baseDir, 'theme') if not self.server.themeName: From 7442eefbd0bd36c99d7527870fd51228c707eef1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 12:07:02 +0000 Subject: [PATCH 08/16] Try default favicon extension --- daemon.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/daemon.py b/daemon.py index 45ba3609b..c9f372c23 100644 --- a/daemon.py +++ b/daemon.py @@ -4856,6 +4856,12 @@ class PubServer(BaseHTTPRequestHandler): faviconFilename = \ baseDir + '/theme/' + self.server.themeName + \ '/icons/' + favFilename + if not favFilename.endswith('.ico'): + if not os.path.isfile(faviconFilename): + if favFilename.endswith('.webp'): + favFilename = favFilename.replace('.webp', '.ico') + elif favFilename.endswith('.avif'): + favFilename = favFilename.replace('.avif', '.ico') if not os.path.isfile(faviconFilename): # default favicon faviconFilename = \ From 13c05db596cdbd18a437af2e098bb9eb3292711e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 12:12:09 +0000 Subject: [PATCH 09/16] Favicon filename --- webapp_column_right.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_column_right.py b/webapp_column_right.py index b22e4e800..300fa9934 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -190,7 +190,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, def _getBrokenFavSubstitute() -> str: """Substitute link used if a favicon is not available """ - return " onerror=\"this.onerror=null; this.src='/default_favicon.ico'\"" + return " onerror=\"this.onerror=null; this.src='/newswire_favicon.ico'\"" def _getNewswireFavicon(url: str) -> str: From cfaf5a57924822cf1d55465303f2df76b68c82e3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 15:38:55 +0000 Subject: [PATCH 10/16] Deprecate blurhashes They were computationally expensive, and similar functionality could be achieved in a simpler way with css --- README.md | 8 +- blurhash.py | 184 ------------------------------------------ daemon.py | 14 +--- epicyon.py | 32 +++----- gemini/EN/install.gmi | 2 +- media.py | 15 +--- newsdaemon.py | 3 +- posts.py | 50 ++++++------ tests.py | 38 +++------ website/EN/index.html | 2 +- 10 files changed, 57 insertions(+), 291 deletions(-) delete mode 100644 blurhash.py diff --git a/README.md b/README.md index 02ea46df0..bcf442eed 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ On Arch/Parabola: ``` bash sudo pacman -S tor python-pip python-pysocks python-pycryptodome \ - imagemagick python-pillow python-requests \ - perl-image-exiftool python-numpy python-dateutil \ + imagemagick python-requests \ + perl-image-exiftool python-dateutil \ certbot flake8 bandit sudo pip3 install pyqrcode pypng ``` @@ -35,9 +35,9 @@ Or on Debian: ``` bash sudo apt install -y \ tor python3-socks imagemagick \ - python3-numpy python3-setuptools \ + python3-setuptools \ python3-crypto python3-pycryptodome \ - python3-dateutil python3-pil.imagetk \ + python3-dateutil \ python3-idna python3-requests \ python3-django-timezone-field \ libimage-exiftool-perl python3-flake8 \ diff --git a/blurhash.py b/blurhash.py deleted file mode 100644 index de2eb50ea..000000000 --- a/blurhash.py +++ /dev/null @@ -1,184 +0,0 @@ -""" -Copyright (c) 2019 Lorenz Diener - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. -* You and any organization you work for may not promote white supremacy, hate -speech and homo- or transphobia - this license is void if you do. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -https://github.com/halcy/blurhash-python - -Pure python blurhash decoder with no additional dependencies, for -both de- and encoding. - -Very close port of the original Swift implementation by Dag Ă…gren. -""" - -import math - - -# Alphabet for base 83 -alphabet = \ - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \ - "abcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~" -alphabet_values = dict(zip(alphabet, range(len(alphabet)))) - - -def _base83_encode(value, length): - """ - Decodes an integer to a base83 string, as used in blurhash. - - Length is how long the resulting string should be. Will complain - if the specified length is too short. - """ - if int(value) // (83 ** (length)) != 0: - raise ValueError("Specified length is too short to " + - "encode given value.") - - result = "" - for i in range(1, length + 1): - digit = int(value) // (83 ** (length - i)) % 83 - result += alphabet[int(digit)] - return result - - -def _srgb_to_linear(value): - """ - srgb 0-255 integer to linear 0.0-1.0 floating point conversion. - """ - value = float(value) / 255.0 - if value <= 0.04045: - return value / 12.92 - return math.pow((value + 0.055) / 1.055, 2.4) - - -def _sign_pow(value, exp): - """ - Sign-preserving exponentiation. - """ - return math.copysign(math.pow(abs(value), exp), value) - - -def _linear_to_srgb(value): - """ - linear 0.0-1.0 floating point to srgb 0-255 integer conversion. - """ - value = max(0.0, min(1.0, value)) - if value <= 0.0031308: - return int(value * 12.92 * 255 + 0.5) - return int((1.055 * math.pow(value, 1 / 2.4) - 0.055) * 255 + 0.5) - - -def blurhash_encode(image, components_x=4, components_y=4, linear=False): - """ - Calculates the blurhash for an image using the given x and y - component counts. - - Image should be a 3-dimensional array, with the first dimension - being y, the second being x, and the third being the three rgb - components that are assumed to be 0-255 srgb integers - (incidentally, this is the format you will get from a PIL RGB image). - - You can also pass in already linear data - to do this, set linear - to True. This is useful if you want to encode a version of your - image resized to a smaller size (which you should ideally do in - linear colour). - """ - if components_x < 1 or components_x > 9 or \ - components_y < 1 or components_y > 9: - raise ValueError("x and y component counts must be " + - "between 1 and 9 inclusive.") - height = float(len(image)) - width = float(len(image[0])) - - # Convert to linear if neeeded - image_linear = [] - if linear is False: - for y in range(int(height)): - image_linear_line = [] - for x in range(int(width)): - image_linear_line.append([ - _srgb_to_linear(image[y][x][0]), - _srgb_to_linear(image[y][x][1]), - _srgb_to_linear(image[y][x][2]) - ]) - image_linear.append(image_linear_line) - else: - image_linear = image - - # Calculate components - components = [] - max_ac_component = 0.0 - for j in range(components_y): - for i in range(components_x): - norm_factor = 1.0 if (i == 0 and j == 0) else 2.0 - component = [0.0, 0.0, 0.0] - for y in range(int(height)): - for x in range(int(width)): - basis = \ - norm_factor * \ - math.cos(math.pi * float(i) * float(x) / width) * \ - math.cos(math.pi * float(j) * float(y) / height) - component[0] += basis * image_linear[y][x][0] - component[1] += basis * image_linear[y][x][1] - component[2] += basis * image_linear[y][x][2] - - component[0] /= (width * height) - component[1] /= (width * height) - component[2] /= (width * height) - components.append(component) - - if not (i == 0 and j == 0): - max_ac_component = \ - max(max_ac_component, abs(component[0]), - abs(component[1]), abs(component[2])) - - # Encode components - dc_value = (_linear_to_srgb(components[0][0]) << 16) + \ - (_linear_to_srgb(components[0][1]) << 8) + \ - _linear_to_srgb(components[0][2]) - - quant_max_ac_component = int(max(0, min(82, - math.floor(max_ac_component * - 166 - 0.5)))) - ac_component_norm_factor = float(quant_max_ac_component + 1) / 166.0 - - ac_values = [] - for r, g, b in components[1:]: - r2 = r / ac_component_norm_factor - g2 = g / ac_component_norm_factor - b2 = b / ac_component_norm_factor - r3 = math.floor(_sign_pow(r2, 0.5) * 9.0 + 9.5) - g3 = math.floor(_sign_pow(g2, 0.5) * 9.0 + 9.5) - b3 = math.floor(_sign_pow(b2, 0.5) * 9.0 + 9.5) - ac_values.append( - int(max(0.0, min(18.0, r3))) * 19 * 19 + - int(max(0.0, min(18.0, g3))) * 19 + - int(max(0.0, min(18.0, b3))) - ) - - # Build final blurhash - blurhash = "" - blurhashValue = (components_x - 1) + (components_y - 1) * 9 - blurhash += _base83_encode(blurhashValue, 1) - blurhash += _base83_encode(quant_max_ac_component, 1) - blurhash += _base83_encode(dc_value, 4) - for ac_value in ac_values: - blurhash += _base83_encode(ac_value, 2) - - return blurhash diff --git a/daemon.py b/daemon.py index c9f372c23..528fe5fff 100644 --- a/daemon.py +++ b/daemon.py @@ -11977,7 +11977,6 @@ class PubServer(BaseHTTPRequestHandler): False, False, False, commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['replyTo'], fields['replyTo'], fields['subject'], fields['schedulePost'], fields['eventDate'], fields['eventTime'], @@ -12032,7 +12031,6 @@ class PubServer(BaseHTTPRequestHandler): False, False, False, commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['replyTo'], fields['replyTo'], fields['subject'], fields['schedulePost'], @@ -12112,8 +12110,7 @@ class PubServer(BaseHTTPRequestHandler): postJsonObject['object'], filename, attachmentMediaType, - imgDescription, - self.server.useBlurHash) + imgDescription) replaceYouTube(postJsonObject, self.server.YTReplacementDomain) @@ -12144,7 +12141,6 @@ class PubServer(BaseHTTPRequestHandler): False, False, False, commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['replyTo'], fields['replyTo'], fields['subject'], @@ -12177,7 +12173,6 @@ class PubServer(BaseHTTPRequestHandler): commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['replyTo'], fields['replyTo'], fields['subject'], @@ -12230,7 +12225,6 @@ class PubServer(BaseHTTPRequestHandler): False, False, commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['subject'], fields['schedulePost'], fields['eventDate'], @@ -12268,7 +12262,6 @@ class PubServer(BaseHTTPRequestHandler): commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['replyTo'], fields['replyTo'], fields['subject'], @@ -12307,7 +12300,6 @@ class PubServer(BaseHTTPRequestHandler): True, False, False, False, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, None, None, fields['subject'], True, fields['schedulePost'], @@ -12340,7 +12332,6 @@ class PubServer(BaseHTTPRequestHandler): True, False, False, True, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, self.server.debug, fields['subject']) if messageJson: if self._postToOutbox(messageJson, __version__, nickname): @@ -12371,7 +12362,6 @@ class PubServer(BaseHTTPRequestHandler): commentsEnabled, filename, attachmentMediaType, fields['imageDescription'], - self.server.useBlurHash, fields['subject'], int(fields['duration'])) if messageJson: @@ -13464,7 +13454,6 @@ def runDaemon(verifyAllSignatures: bool, domainMaxPostsPerDay=8640, accountMaxPostsPerDay=864, allowDeletion=False, debug=False, unitTest=False, instanceOnlySkillsSearch=False, sendThreads=[], - useBlurHash=False, manualFollowerApproval=True) -> None: if len(domain) == 0: domain = 'localhost' @@ -13520,7 +13509,6 @@ def runDaemon(verifyAllSignatures: bool, httpd.manualFollowerApproval = manualFollowerApproval httpd.onionDomain = onionDomain httpd.i2pDomain = i2pDomain - httpd.useBlurHash = useBlurHash httpd.mediaInstance = mediaInstance httpd.blogsInstance = blogsInstance httpd.newsInstance = newsInstance diff --git a/epicyon.py b/epicyon.py index da5d1cda5..c7af7bfd0 100644 --- a/epicyon.py +++ b/epicyon.py @@ -375,9 +375,6 @@ parser.add_argument('--attach', dest='attach', type=str, default=None, help='File to attach to a post') parser.add_argument('--imagedescription', dest='imageDescription', type=str, default=None, help='Description of an attached image') -parser.add_argument("--blurhash", type=str2bool, nargs='?', - const=True, default=False, - help="Create blurhash for an image") parser.add_argument('--warning', '--warn', '--cwsubject', '--subject', dest='subject', type=str, default=None, help='Subject of content warning') @@ -1002,7 +999,6 @@ if args.message: followersOnly = args.followersonly clientToServer = args.client attachedImageDescription = args.imageDescription - useBlurhash = args.blurhash sendThreads = [] postLog = [] personCache = {} @@ -1023,7 +1019,7 @@ if args.message: toNickname, toDomain, toPort, ccUrl, httpPrefix, sendMessage, followersOnly, args.commentsEnabled, attach, mediaType, - attachedImageDescription, useBlurhash, + attachedImageDescription, cachedWebfingers, personCache, isArticle, args.debug, replyTo, replyTo, subject) for i in range(10): @@ -1864,7 +1860,6 @@ if args.unfilterStr: sys.exit() if args.testdata: - useBlurhash = False nickname = 'testuser567' password = 'boringpassword' print('Generating some test data for user: ' + nickname) @@ -1942,8 +1937,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Zoiks!!!", testFollowersOnly, @@ -1951,8 +1945,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Hey scoob we need like a hundred more #milkshakes", testFollowersOnly, @@ -1960,8 +1953,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Getting kinda spooky around here", testFollowersOnly, @@ -1970,7 +1962,7 @@ if args.testdata: testCommentsEnabled, testAttachImageFilename, testMediaType, testImageDescription, - useBlurhash, 'someone') + 'someone') createPublicPost(baseDir, nickname, domain, port, httpPrefix, "And they would have gotten away with it too" + "if it wasn't for those pesky hackers", @@ -1979,8 +1971,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, 'img/logo.png', 'image/png', - 'Description of image', - useBlurhash) + 'Description of image') createPublicPost(baseDir, nickname, domain, port, httpPrefix, "man these centralized sites are like the worst!", testFollowersOnly, @@ -1988,8 +1979,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "another mystery solved #test", testFollowersOnly, @@ -1997,8 +1987,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "let's go bowling", testFollowersOnly, @@ -2006,8 +1995,7 @@ if args.testdata: testClientToServer, testCommentsEnabled, testAttachImageFilename, - testMediaType, testImageDescription, - useBlurhash) + testMediaType, testImageDescription) domainFull = domain + ':' + str(port) clearFollows(baseDir, nickname, domain) @@ -2179,4 +2167,4 @@ if __name__ == "__main__": args.accountMaxPostsPerDay, args.allowdeletion, debug, False, args.instanceOnlySkillsSearch, [], - args.blurhash, not args.noapproval) + not args.noapproval) diff --git a/gemini/EN/install.gmi b/gemini/EN/install.gmi index 06000e78b..49dfaec68 100644 --- a/gemini/EN/install.gmi +++ b/gemini/EN/install.gmi @@ -4,7 +4,7 @@ You will need python version 3.7 or later. On a Debian based system: - sudo apt install -y tor python3-socks imagemagick python3-numpy python3-setuptools python3-crypto python3-pycryptodome python3-dateutil python3-pil.imagetk python3-idna python3-requests python3-flake8 python3-django-timezone-field python3-pyqrcode python3-png python3-bandit libimage-exiftool-perl certbot nginx wget + sudo apt install -y tor python3-socks imagemagick python3-setuptools python3-crypto python3-pycryptodome python3-dateutil python3-idna python3-requests python3-flake8 python3-django-timezone-field python3-pyqrcode python3-png python3-bandit libimage-exiftool-perl certbot nginx wget The following instructions install Epicyon to the /opt directory. It's not essential that it be installed there, and it could be in any other preferred directory. diff --git a/media.py b/media.py index 763ce77d9..d37487ae2 100644 --- a/media.py +++ b/media.py @@ -6,9 +6,6 @@ __maintainer__ = "Bob Mottram" __email__ = "bob@freedombone.net" __status__ = "Production" -from blurhash import blurhash_encode -from PIL import Image -import numpy import os import datetime from hashlib import sha1 @@ -56,11 +53,6 @@ def removeMetaData(imageFilename: str, outputFilename: str) -> None: os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec -def _getImageHash(imageFilename: str) -> str: - value = numpy.array(Image.open(imageFilename).convert("RGB")) - return blurhash_encode(value) - - def _isMedia(imageFilename: str) -> bool: permittedMedia = getMediaExtensions() for m in permittedMedia: @@ -136,12 +128,9 @@ def _updateEtag(mediaFilename: str) -> None: def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int, postJson: {}, imageFilename: str, - mediaType: str, description: str, - useBlurhash: bool) -> {}: + mediaType: str, description: str) -> {}: """Attaches media to a json object post The description can be None - Blurhash is optional, since low power systems may take a long - time to calculate it """ if not _isMedia(imageFilename): return postJson @@ -181,8 +170,6 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int, } if mediaType.startswith('image/'): attachmentJson['focialPoint'] = [0.0, 0.0] - if useBlurhash: - attachmentJson['blurhash'] = _getImageHash(imageFilename) postJson['attachment'] = [attachmentJson] if baseDir: diff --git a/newsdaemon.py b/newsdaemon.py index 737b4ac9c..4f74d95bf 100644 --- a/newsdaemon.py +++ b/newsdaemon.py @@ -542,7 +542,6 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str, rssDescription = removeHtmlTag(rssDescription, 'height') followersOnly = False - useBlurhash = False # NOTE: the id when the post is created will not be # consistent (it's based on the current time, not the # published time), so we change that later @@ -550,7 +549,7 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str, domain, port, httpPrefix, rssDescription, followersOnly, False, - None, None, None, useBlurhash, + None, None, None, rssTitle) if not blog: continue diff --git a/posts.py b/posts.py index df87b2221..f73709bce 100644 --- a/posts.py +++ b/posts.py @@ -803,7 +803,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, imageDescription: str, - useBlurhash: bool, isModerationReport: bool, + isModerationReport: bool, isArticle: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None, schedulePost=False, @@ -1034,7 +1034,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int, newPost['object'] = \ attachMedia(baseDir, httpPrefix, domain, port, newPost['object'], attachImageFilename, - mediaType, imageDescription, useBlurhash) + mediaType, imageDescription) _appendEventFields(newPost['object'], eventUUID, eventStatus, anonymousParticipationEnabled, repliesModerationOption, @@ -1082,7 +1082,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int, newPost = \ attachMedia(baseDir, httpPrefix, domain, port, newPost, attachImageFilename, - mediaType, imageDescription, useBlurhash) + mediaType, imageDescription) _appendEventFields(newPost, eventUUID, eventStatus, anonymousParticipationEnabled, repliesModerationOption, @@ -1225,7 +1225,7 @@ def createPublicPost(baseDir: str, content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, inReplyTo=None, inReplyToAtomUri=None, subject=None, schedulePost=False, eventDate=None, eventTime=None, location=None) -> {}: @@ -1239,7 +1239,7 @@ def createPublicPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location, None, None, None, None, None, @@ -1251,7 +1251,7 @@ def createBlogPost(baseDir: str, content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, inReplyTo=None, inReplyToAtomUri=None, subject=None, schedulePost=False, eventDate=None, eventTime=None, location=None) -> {}: @@ -1261,7 +1261,7 @@ def createBlogPost(baseDir: str, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location) @@ -1298,7 +1298,7 @@ def createNewsPost(baseDir: str, domain: str, port: int, httpPrefix: str, content: str, followersOnly: bool, saveToFile: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, subject: str) -> {}: clientToServer = False inReplyTo = None @@ -1313,7 +1313,7 @@ def createNewsPost(baseDir: str, content, followersOnly, saveToFile, clientToServer, False, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location) @@ -1327,7 +1327,7 @@ def createQuestionPost(baseDir: str, followersOnly: bool, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, subject: str, durationDays: int) -> {}: """Question post with multiple choice options """ @@ -1340,7 +1340,7 @@ def createQuestionPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, None, None, subject, False, None, None, None, None, None, None, None, None, @@ -1371,7 +1371,7 @@ def createUnlistedPost(baseDir: str, content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, inReplyTo=None, inReplyToAtomUri=None, subject=None, schedulePost=False, eventDate=None, eventTime=None, location=None) -> {}: @@ -1385,7 +1385,7 @@ def createUnlistedPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location, None, None, None, None, None, @@ -1399,7 +1399,7 @@ def createFollowersOnlyPost(baseDir: str, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, inReplyTo=None, inReplyToAtomUri=None, subject=None, schedulePost=False, eventDate=None, eventTime=None, @@ -1414,7 +1414,7 @@ def createFollowersOnlyPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location, None, None, None, None, None, @@ -1428,7 +1428,7 @@ def createEventPost(baseDir: str, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, subject=None, schedulePost=False, eventDate=None, eventTime=None, location=None, category=None, joinMode=None, @@ -1461,7 +1461,7 @@ def createEventPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, None, None, subject, schedulePost, eventDate, eventTime, location, eventUUID, category, joinMode, @@ -1513,7 +1513,7 @@ def createDirectMessagePost(baseDir: str, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, inReplyTo=None, inReplyToAtomUri=None, subject=None, debug=False, schedulePost=False, @@ -1536,7 +1536,7 @@ def createDirectMessagePost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, False, inReplyTo, inReplyToAtomUri, subject, schedulePost, eventDate, eventTime, location, None, None, None, None, None, @@ -1557,7 +1557,7 @@ def createReportPost(baseDir: str, content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, debug: bool, subject=None) -> {}: """Send a report to moderators """ @@ -1626,7 +1626,7 @@ def createReportPost(baseDir: str, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, True, False, None, None, subject, False, None, None, None, None, None, None, None, None, @@ -1717,7 +1717,7 @@ def sendPost(projectVersion: str, saveToFile: bool, clientToServer: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, federationList: [], sendThreads: [], postLog: [], cachedWebfingers: {}, personCache: {}, isArticle: bool, @@ -1776,7 +1776,7 @@ def sendPost(projectVersion: str, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, isArticle, inReplyTo, inReplyToAtomUri, subject, False, None, None, None, None, None, @@ -1838,7 +1838,7 @@ def sendPostViaServer(projectVersion: str, httpPrefix: str, content: str, followersOnly: bool, commentsEnabled: bool, attachImageFilename: str, mediaType: str, - imageDescription: str, useBlurhash: bool, + imageDescription: str, cachedWebfingers: {}, personCache: {}, isArticle: bool, debug=False, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> int: @@ -1914,7 +1914,7 @@ def sendPostViaServer(projectVersion: str, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, - imageDescription, useBlurhash, + imageDescription, False, isArticle, inReplyTo, inReplyToAtomUri, subject, False, None, None, None, None, None, diff --git a/tests.py b/tests.py index e76a3b74d..e88c651b3 100644 --- a/tests.py +++ b/tests.py @@ -256,7 +256,6 @@ def createServerAlice(path: str, domain: str, port: int, httpPrefix = 'http' proxyType = None password = 'alicepass' - useBlurhash = True maxReplies = 64 domainMaxPostsPerDay = 1000 accountMaxPostsPerDay = 1000 @@ -289,8 +288,7 @@ def createServerAlice(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) createPublicPost(path, nickname, domain, port, httpPrefix, "Curiouser and curiouser!", testFollowersOnly, @@ -299,8 +297,7 @@ def createServerAlice(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) createPublicPost(path, nickname, domain, port, httpPrefix, "In the gardens of memory, in the palace " + "of dreams, that is where you and I shall meet", @@ -310,8 +307,7 @@ def createServerAlice(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) global testServerAliceRunning testServerAliceRunning = True maxMentions = 10 @@ -338,7 +334,7 @@ def createServerAlice(path: str, domain: str, port: int, httpPrefix, federationList, maxMentions, maxEmoji, False, proxyType, maxReplies, domainMaxPostsPerDay, accountMaxPostsPerDay, - allowDeletion, True, True, False, sendThreads, False, + allowDeletion, True, True, False, sendThreads, False) @@ -356,7 +352,6 @@ def createServerBob(path: str, domain: str, port: int, proxyType = None clientToServer = False password = 'bobpass' - useBlurhash = False maxReplies = 64 domainMaxPostsPerDay = 1000 accountMaxPostsPerDay = 1000 @@ -388,8 +383,7 @@ def createServerBob(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) createPublicPost(path, nickname, domain, port, httpPrefix, "One of the things I've realised is that " + "I am very simple", @@ -399,8 +393,7 @@ def createServerBob(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) createPublicPost(path, nickname, domain, port, httpPrefix, "Quantum physics is a bit of a passion of mine", testFollowersOnly, @@ -409,8 +402,7 @@ def createServerBob(path: str, domain: str, port: int, testCommentsEnabled, testAttachImageFilename, testMediaType, - testImageDescription, - useBlurhash) + testImageDescription) global testServerBobRunning testServerBobRunning = True maxMentions = 10 @@ -437,7 +429,7 @@ def createServerBob(path: str, domain: str, port: int, httpPrefix, federationList, maxMentions, maxEmoji, False, proxyType, maxReplies, domainMaxPostsPerDay, accountMaxPostsPerDay, - allowDeletion, True, True, False, sendThreads, False, + allowDeletion, True, True, False, sendThreads, False) @@ -485,7 +477,7 @@ def createServerEve(path: str, domain: str, port: int, federationList: [], onionDomain, i2pDomain, None, port, port, httpPrefix, federationList, maxMentions, maxEmoji, False, proxyType, maxReplies, allowDeletion, True, True, False, - sendThreads, False, False) + sendThreads, False) def testPostMessageBetweenServers(): @@ -574,7 +566,6 @@ def testPostMessageBetweenServers(): attachedImageFilename = baseDir + '/img/logo.png' mediaType = getAttachmentMediaType(attachedImageFilename) attachedImageDescription = 'Logo' - useBlurhash = True isArticle = False # nothing in Alice's outbox outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox' @@ -590,7 +581,7 @@ def testPostMessageBetweenServers(): followersOnly, saveToFile, clientToServer, True, attachedImageFilename, mediaType, - attachedImageDescription, useBlurhash, federationList, + attachedImageDescription, federationList, aliceSendThreads, alicePostLog, aliceCachedWebfingers, alicePersonCache, isArticle, inReplyTo, inReplyToAtomUri, subject) @@ -890,7 +881,6 @@ def testFollowBetweenServers(): alicePersonCache = {} aliceCachedWebfingers = {} alicePostLog = [] - useBlurhash = False isArticle = False sendResult = \ sendPost(__version__, @@ -898,7 +888,7 @@ def testFollowBetweenServers(): 'bob', bobDomain, bobPort, ccUrl, httpPrefix, 'Alice message', followersOnly, saveToFile, clientToServer, True, - None, None, None, useBlurhash, federationList, + None, None, None, federationList, aliceSendThreads, alicePostLog, aliceCachedWebfingers, alicePersonCache, isArticle, inReplyTo, inReplyToAtomUri, subject) @@ -1178,7 +1168,6 @@ def testCreatePerson(): port = 80 httpPrefix = 'https' clientToServer = False - useBlurhash = False baseDir = currDir + '/.tests_createperson' if os.path.isdir(baseDir): shutil.rmtree(baseDir) @@ -1197,7 +1186,7 @@ def testCreatePerson(): archivePostsForPerson(nickname, domain, baseDir, 'outbox', None, {}, 4) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "G'day world!", False, True, clientToServer, - True, None, None, useBlurhash, None, None, + True, None, None, None, None, 'Not suitable for Vogons') os.chdir(currDir) @@ -1401,7 +1390,6 @@ def testClientToServer(): attachedImageFilename = baseDir+'/img/logo.png' mediaType = getAttachmentMediaType(attachedImageFilename) attachedImageDescription = 'Logo' - useBlurhash = False isArticle = False cachedWebfingers = {} personCache = {} @@ -1420,7 +1408,7 @@ def testClientToServer(): httpPrefix, 'Sent from my ActivityPub client', followersOnly, True, attachedImageFilename, mediaType, - attachedImageDescription, useBlurhash, + attachedImageDescription, cachedWebfingers, personCache, isArticle, True, None, None, None) print('sendResult: ' + str(sendResult)) diff --git a/website/EN/index.html b/website/EN/index.html index 26f5138b6..39a8b3af8 100644 --- a/website/EN/index.html +++ b/website/EN/index.html @@ -1267,7 +1267,7 @@

You will need python version 3.7 or later.

On a Debian based system:

-

sudo apt install -y tor python3-socks imagemagick python3-numpy python3-setuptools python3-crypto python3-pycryptodome python3-dateutil python3-pil.imagetk python3-idna python3-requests python3-flake8 python3-django-timezone-field python3-pyqrcode python3-png python3-bandit libimage-exiftool-perl certbot nginx wget

+

sudo apt install -y tor python3-socks imagemagick python3-setuptools python3-crypto python3-pycryptodome python3-dateutil python3-idna python3-requests python3-flake8 python3-django-timezone-field python3-pyqrcode python3-png python3-bandit libimage-exiftool-perl certbot nginx wget

From ac3d34bd868ce61f1a3e6c377e6c08577d3b4b0e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 15:39:38 +0000 Subject: [PATCH 11/16] Update dockerfile --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 17ded0a72..fa0ad6338 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,8 +8,6 @@ RUN apt-get update && \ python3-dateutil \ python3-idna \ python3-requests \ - python3-numpy \ - python3-pil.imagetk \ python3-pip \ python3-setuptools \ python3-socks \ From cb10db2b9c9619eba1fd2dd64a2b345f10b95254 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 16:00:39 +0000 Subject: [PATCH 12/16] No longer a goal --- README_goals.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README_goals.md b/README_goals.md index 97f8837fd..be3567585 100644 --- a/README_goals.md +++ b/README_goals.md @@ -15,7 +15,6 @@ * http signatures and basic auth * Compatible with http (onion addresses), https and dat * Minimal dependencies. - * Support image blurhashes * Data minimization principle. Configurable post expiry time * Likes and repeats only visible to authorized viewers * ReplyGuy mitigation - maxmimum replies per post or posts per day From e3530580e1e790d417350e98386f187922378fc5 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 7 Jan 2021 16:01:22 +0000 Subject: [PATCH 13/16] Remove blurhash option --- README_commandline.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README_commandline.md b/README_commandline.md index 4bce92a8c..a8bfc9c92 100644 --- a/README_commandline.md +++ b/README_commandline.md @@ -118,7 +118,6 @@ python3 epicyon.py --nickname [yournick] --domain [name] \ --sendto othernick@domain --message "bees!" \ --warning "bee-related content" --attach bees.png \ --imagedescription "bees on flowers" \ - --blurhash \ --password [c2s password] ``` From 155493c0d02213e9803e2e1615fe77d9b799cc91 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 8 Jan 2021 19:13:59 +0000 Subject: [PATCH 14/16] Comment out debug --- posts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts.py b/posts.py index f73709bce..cca2b093e 100644 --- a/posts.py +++ b/posts.py @@ -146,7 +146,7 @@ def _cleanHtml(rawHtml: str) -> str: def getUserUrl(wfRequest: {}, sourceId=0) -> str: """Gets the actor url from a webfinger request """ - print('getUserUrl: ' + str(sourceId) + ' ' + str(wfRequest)) + # print('getUserUrl: ' + str(sourceId) + ' ' + str(wfRequest)) if not wfRequest.get('links'): if sourceId == 72367: print('getUserUrl failed to get display name for webfinger ' + From 80545e279a5c6bf6efd71cdf25561bdd29b6205f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 8 Jan 2021 21:40:05 +0000 Subject: [PATCH 15/16] Don't show DMs if unauthorized --- posts.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/posts.py b/posts.py index cca2b093e..54855a4c6 100644 --- a/posts.py +++ b/posts.py @@ -171,7 +171,7 @@ def getUserUrl(wfRequest: {}, sourceId=0) -> str: def parseUserFeed(session, feedUrl: str, asHeader: {}, projectVersion: str, httpPrefix: str, domain: str, depth=0) -> {}: - if depth > 10: + if depth > 10: return None feedJson = getJson(session, feedUrl, asHeader, None, @@ -195,7 +195,7 @@ def parseUserFeed(session, feedUrl: str, asHeader: {}, userFeed = \ parseUserFeed(session, nextUrl, asHeader, projectVersion, httpPrefix, - domain, depth+1) + domain, depth + 1) if userFeed: for item in userFeed: yield item @@ -3091,6 +3091,8 @@ def _createBoxIndexed(recentPostsCache: {}, if not authorized: if p.get('object'): if isinstance(p['object'], dict): + if isDM(p): + continue if p['object'].get('likes'): p['likes'] = {'items': []} if p['object'].get('replies'): From 4f8580dcce1972fddd75a028a85b66be2111fc08 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 8 Jan 2021 21:43:04 +0000 Subject: [PATCH 16/16] Comment --- posts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posts.py b/posts.py index 54855a4c6..e3af38f53 100644 --- a/posts.py +++ b/posts.py @@ -171,7 +171,7 @@ def getUserUrl(wfRequest: {}, sourceId=0) -> str: def parseUserFeed(session, feedUrl: str, asHeader: {}, projectVersion: str, httpPrefix: str, domain: str, depth=0) -> {}: - if depth > 10: + if depth > 10: return None feedJson = getJson(session, feedUrl, asHeader, None, @@ -3086,7 +3086,7 @@ def _createBoxIndexed(recentPostsCache: {}, # created by individualPostAsHtml p['hasReplies'] = hasReplies - # Don't show likes, replies or shares (announces) to + # Don't show likes, replies, DMs or shares (announces) to # unauthorized viewers if not authorized: if p.get('object'):