From 6b3e9396d747a2f5acb2354b1d41f8f420356863 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 13 Jul 2020 14:36:45 +0100 Subject: [PATCH 1/7] Check if post was already liked --- inbox.py | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/inbox.py b/inbox.py index 864def14e..be5af0ce0 100644 --- a/inbox.py +++ b/inbox.py @@ -1032,11 +1032,16 @@ def receiveLike(recentPostsCache: {}, if debug: print('DEBUG: liked post found in inbox') - updateLikesCollection(recentPostsCache, baseDir, postFilename, - messageJson['object'], - messageJson['actor'], domain, debug) - likeNotify(baseDir, domain, onionDomain, handle, - messageJson['actor'], messageJson['object']) + if not alreadyLiked(baseDir, + handle.split('@')[0], + handle.split('@')[1], + messageJson['object'], + messageJson['actor']): + updateLikesCollection(recentPostsCache, baseDir, postFilename, + messageJson['object'], + messageJson['actor'], domain, debug) + likeNotify(baseDir, domain, onionDomain, handle, + messageJson['actor'], messageJson['object']) return True @@ -1706,6 +1711,37 @@ def dmNotify(baseDir: str, handle: str, url: str) -> None: fp.write(url) +def alreadyLiked(baseDir: str, nickname: str, domain: str, + postUrl: str, likerActor: str) -> bool: + """Is the given post already liked by the given handle? + """ + postFilename = \ + locatePost(baseDir, nickname, domain, postUrl) + if not postFilename: + return False + postJsonObject = loadJson(postFilename, 1) + if not postJsonObject: + return False + if not postJsonObject.get('object'): + return False + if not isinstance(postJsonObject['object'], dict): + return False + if not postJsonObject['object'].get('likes'): + return False + if not postJsonObject['object']['likes'].get('items'): + return False + for like in postJsonObject['object']['likes']['items']: + if not like.get('type'): + continue + if not like.get('actor'): + continue + if like['type'] != 'Like': + continue + if like['actor'] == likerActor: + return True + return False + + def likeNotify(baseDir: str, domain: str, onionDomain: str, handle: str, actor: str, url: str) -> None: """Creates a notification that a like has arrived From 333357400761037f9dba5aa8636524f1e43afaae Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 13 Jul 2020 20:42:30 +0100 Subject: [PATCH 2/7] Link to who liked a post --- daemon.py | 19 +++++++++++++++++-- inbox.py | 2 +- translations/ar.json | 3 ++- translations/ca.json | 3 ++- translations/cy.json | 3 ++- translations/de.json | 3 ++- translations/en.json | 3 ++- translations/es.json | 3 ++- translations/fr.json | 3 ++- translations/ga.json | 3 ++- translations/hi.json | 3 ++- translations/it.json | 3 ++- translations/ja.json | 3 ++- translations/oc.json | 3 ++- translations/pt.json | 3 ++- translations/ru.json | 3 ++- translations/zh.json | 3 ++- webinterface.py | 15 +++++++++++++-- 18 files changed, 61 insertions(+), 20 deletions(-) diff --git a/daemon.py b/daemon.py index 6795a1504..6b9892f95 100644 --- a/daemon.py +++ b/daemon.py @@ -3444,6 +3444,13 @@ class PubServer(BaseHTTPRequestHandler): # get an individual post from the path /@nickname/statusnumber if '/@' in self.path: + likedBy = None + if '?likedBy=' in self.path: + likedBy = self.path.split('?likedBy=')[1].strip() + if '?' in likedBy: + likedBy = likedBy.split('?')[0] + self.path = self.path.split('?likedBy=')[0] + namedStatus = self.path.split('/@')[1] if '/' not in namedStatus: # show actor @@ -3504,7 +3511,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, postJsonObject, httpPrefix, - projectVersion) + projectVersion, + likedBy) msg = msg.encode('utf-8') self._set_headers('text/html', len(msg), cookie, callingDomain) @@ -3897,6 +3905,12 @@ class PubServer(BaseHTTPRequestHandler): # get an individual post from the path # /users/nickname/statuses/number if '/statuses/' in self.path and '/users/' in self.path: + likedBy = None + if '?likedBy=' in self.path: + likedBy = self.path.split('?likedBy=')[1].strip() + if '?' in likedBy: + likedBy = likedBy.split('?')[0] + self.path = self.path.split('?likedBy=')[0] namedStatus = self.path.split('/users/')[1] if '/' in namedStatus: postSections = namedStatus.split('/') @@ -3957,7 +3971,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, postJsonObject, httpPrefix, - projectVersion) + projectVersion, + likedBy) msg = msg.encode('utf-8') self._set_headers('text/html', len(msg), diff --git a/inbox.py b/inbox.py index be5af0ce0..171206ce5 100644 --- a/inbox.py +++ b/inbox.py @@ -1775,7 +1775,7 @@ def likeNotify(baseDir: str, domain: str, onionDomain: str, str(likerNickname) + '@' + str(likerDomain)) likerHandle = actor if likerHandle != handle: - likeStr = likerHandle + ' ' + url + likeStr = likerHandle + ' ' + url + '?likedBy=' + actor prevLikeFile = accountDir + '/.prevLike' # was there a previous like notification? if os.path.isfile(prevLikeFile): diff --git a/translations/ar.json b/translations/ar.json index cf3cad0fb..4bd93a6ce 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -251,5 +251,6 @@ "Unavailable": "غير متوفره", "The server is busy. Please try again later": "الخادم مشغول. الرجاء معاودة المحاولة في وقت لاحق", "Receive calendar events from this account": "تلقي أحداث التقويم من هذا الحساب", - "Grayscale": "درجات الرمادي" + "Grayscale": "درجات الرمادي", + "Liked by": "نال إعجاب" } diff --git a/translations/ca.json b/translations/ca.json index cfb4be41c..ccaebffa1 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -251,5 +251,6 @@ "Unavailable": "No disponible", "The server is busy. Please try again later": "El servidor està ocupat. Siusplau, intenta-ho més tard", "Receive calendar events from this account": "Rep esdeveniments del calendari des d’aquest compte", - "Grayscale": "Escala de grisos" + "Grayscale": "Escala de grisos", + "Liked by": "M'agrada" } diff --git a/translations/cy.json b/translations/cy.json index 508955a57..4544c2de4 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -251,5 +251,6 @@ "Unavailable": "Ddim ar gael", "The server is busy. Please try again later": "Mae'r gweinydd yn brysur. Rho gynnig Arni eto'n hwyrach", "Receive calendar events from this account": "Derbyn digwyddiadau calendr o'r cyfrif hwn", - "Grayscale": "Graddlwyd" + "Grayscale": "Graddlwyd", + "Liked by": "Hoffi" } diff --git a/translations/de.json b/translations/de.json index 63919ff73..25e70a00e 100644 --- a/translations/de.json +++ b/translations/de.json @@ -251,5 +251,6 @@ "Unavailable": "Nicht verfügbar", "The server is busy. Please try again later": "Der Server ist beschäftigt. Bitte versuchen Sie es später noch einmal", "Receive calendar events from this account": "Erhalten Sie Kalenderereignisse von diesem Konto", - "Grayscale": "Graustufen" + "Grayscale": "Graustufen", + "Liked by": "Gefallen von" } diff --git a/translations/en.json b/translations/en.json index 3f8e37521..44a323614 100644 --- a/translations/en.json +++ b/translations/en.json @@ -251,5 +251,6 @@ "Unavailable": "Unavailable", "The server is busy. Please try again later": "The server is busy. Please try again later", "Receive calendar events from this account": "Receive calendar events from this account", - "Grayscale": "Grayscale" + "Grayscale": "Grayscale", + "Liked by": "Liked by" } diff --git a/translations/es.json b/translations/es.json index a49c3e296..cedb08a47 100644 --- a/translations/es.json +++ b/translations/es.json @@ -251,5 +251,6 @@ "Unavailable": "Indisponible", "The server is busy. Please try again later": "El servidor esta ocupado. Por favor, inténtelo de nuevo más tarde", "Receive calendar events from this account": "Recibe eventos de calendario de esta cuenta", - "Grayscale": "Escala de grises" + "Grayscale": "Escala de grises", + "Liked by": "Apreciado por" } diff --git a/translations/fr.json b/translations/fr.json index 3b59c6ce2..35413a30d 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -251,5 +251,6 @@ "Unavailable": "Indisponible", "The server is busy. Please try again later": "Le serveur est occupé. Veuillez réessayer plus tard", "Receive calendar events from this account": "Recevoir des événements d'agenda de ce compte", - "Grayscale": "Niveaux de gris" + "Grayscale": "Niveaux de gris", + "Liked by": "Aimé par" } diff --git a/translations/ga.json b/translations/ga.json index f905ea89e..89c3d8df4 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -251,5 +251,6 @@ "Unavailable": "Níl sé ar fáil", "The server is busy. Please try again later": "Tá an freastalaí gnóthach. Bain triail eile as níos déanaí", "Receive calendar events from this account": "Faigh imeachtaí féilire ón gcuntas seo", - "Grayscale": "Liathscála" + "Grayscale": "Liathscála", + "Liked by": "Thaitin" } diff --git a/translations/hi.json b/translations/hi.json index 253a727a0..7222f66c6 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -251,5 +251,6 @@ "Unavailable": "अनुपलब्ध", "The server is busy. Please try again later": "सर्वर व्यस्त है। बाद में पुन: प्रयास करें", "Receive calendar events from this account": "इस खाते से कैलेंडर ईवेंट प्राप्त करें", - "Grayscale": "ग्रेस्केल" + "Grayscale": "ग्रेस्केल", + "Liked by": "द्वारा पसंद किया गया" } diff --git a/translations/it.json b/translations/it.json index a5d0ace2f..fa88fb7d4 100644 --- a/translations/it.json +++ b/translations/it.json @@ -251,5 +251,6 @@ "Unavailable": "non disponibile", "The server is busy. Please try again later": "Il server è occupato. Per favore riprova più tardi", "Receive calendar events from this account": "Ricevi eventi di calendario da questo account", - "Grayscale": "Scala di grigi" + "Grayscale": "Scala di grigi", + "Liked by": "Mi è piaciuto" } diff --git a/translations/ja.json b/translations/ja.json index 33574f2c2..7952606c5 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -251,5 +251,6 @@ "Unavailable": "利用できません", "The server is busy. Please try again later": "サーバーはビジーです。 後でもう一度やり直してください", "Receive calendar events from this account": "このアカウントからカレンダーイベントを受信します", - "Grayscale": "グレースケール" + "Grayscale": "グレースケール", + "Liked by": "好き" } diff --git a/translations/oc.json b/translations/oc.json index e1f09dfd5..006a4f40a 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -247,5 +247,6 @@ "Unavailable": "Unavailable", "The server is busy. Please try again later": "The server is busy. Please try again later", "Receive calendar events from this account": "Receive calendar events from this account", - "Grayscale": "Grayscale" + "Grayscale": "Grayscale", + "Liked by": "Liked by" } diff --git a/translations/pt.json b/translations/pt.json index fa1299000..930e15d55 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -251,5 +251,6 @@ "Unavailable": "Indisponível", "The server is busy. Please try again later": "O servidor está ocupado. Por favor, tente novamente mais tarde", "Receive calendar events from this account": "Receba eventos da agenda desta conta", - "Grayscale": "Escala de cinza" + "Grayscale": "Escala de cinza", + "Liked by": "Curtida por" } diff --git a/translations/ru.json b/translations/ru.json index c15f68cd4..bf69ce736 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -251,5 +251,6 @@ "Unavailable": "Недоступен", "The server is busy. Please try again later": "Сервер занят. Пожалуйста, попробуйте позже", "Receive calendar events from this account": "Получать события календаря от этого аккаунта", - "Grayscale": "Оттенки серого" + "Grayscale": "Оттенки серого", + "Liked by": "Понравилось" } diff --git a/translations/zh.json b/translations/zh.json index a1886a2c8..8b8c89c38 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -250,5 +250,6 @@ "Unavailable": "不可用", "The server is busy. Please try again later": "服务器忙。 请稍后再试", "Receive calendar events from this account": "从该帐户接收日历事件", - "Grayscale": "灰阶" + "Grayscale": "灰阶", + "Liked by": "喜欢的人" } diff --git a/webinterface.py b/webinterface.py index ecc49606b..2453e50cd 100644 --- a/webinterface.py +++ b/webinterface.py @@ -4983,11 +4983,22 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int, baseDir: str, session, wfRequest: {}, personCache: {}, nickname: str, domain: str, port: int, authorized: bool, postJsonObject: {}, httpPrefix: str, - projectVersion: str) -> str: + projectVersion: str, likedBy: str) -> str: """Show an individual post as html """ iconsDir = getIconsDir(baseDir) - postStr = \ + postStr = '' + if likedBy: + likedByNickname = getNicknameFromActor(likedBy) + likedByDomain, likedByPort = getDomainFromActor(likedBy) + if likedByPort: + if likedByPort != 80 and likedByPort != 443: + likedByDomain += ':' + str(likedByPort) + postStr += \ + '

' + translate['Liked by'] + \ + ' @' + \ + likedByNickname + '@' + likedByDomain + '

\n' + postStr += \ individualPostAsHtml(recentPostsCache, maxRecentPosts, iconsDir, translate, None, baseDir, session, wfRequest, personCache, From 295f2accf827729f6d3fad51ae17741ce798e5e3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 14 Jul 2020 10:09:33 +0100 Subject: [PATCH 3/7] Button to follow liker --- follow.py | 2 +- webinterface.py | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/follow.py b/follow.py index b39636547..a66cadf10 100644 --- a/follow.py +++ b/follow.py @@ -84,7 +84,7 @@ def removeFromFollowRejects(baseDir: str, def isFollowingActor(baseDir: str, nickname: str, domain: str, actor: str) -> bool: - """Is the given actor a follower of the given nickname? + """Is the given nickname following the given actor? """ if ':' in domain: domain = domain.split(':')[0] diff --git a/webinterface.py b/webinterface.py index 2453e50cd..8099bc338 100644 --- a/webinterface.py +++ b/webinterface.py @@ -4994,10 +4994,32 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int, if likedByPort: if likedByPort != 80 and likedByPort != 443: likedByDomain += ':' + str(likedByPort) + likedByHandle = likedByNickname + '@' + likedByDomain postStr += \ '

' + translate['Liked by'] + \ ' @' + \ - likedByNickname + '@' + likedByDomain + '

\n' + likedByHandle + '' + + domainFull = domain + if port: + if port != 80 and port != 443: + domainFull = domain + ':' + str(port) + actor = '/users/' + nickname + followStr = '
' + followStr += \ + ' ' + followStr += \ + ' ' + if not isFollowingActor(baseDir, nickname, domainFull, likedBy): + followStr += ' ' + followStr += ' ' + followStr += '
' + postStr += followStr + '

\n' + postStr += \ individualPostAsHtml(recentPostsCache, maxRecentPosts, iconsDir, translate, None, From fac5b6ecb3eed5c044cec52af1515f788f329bd4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 14 Jul 2020 14:52:47 +0100 Subject: [PATCH 4/7] Notes on notifications --- epicyon-notification | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/epicyon-notification b/epicyon-notification index 1d3d5a8ec..358d5f11b 100755 --- a/epicyon-notification +++ b/epicyon-notification @@ -1,7 +1,12 @@ #!/bin/bash # # This can be called from a crontab entry to send notifications -# when Epicyon events occur +# when Epicyon events occur. You will need to have +# sendxmpp+prosody or Synapse (matrix) installed. +# +# Something like: +# +# */1 * * * * root /usr/local/bin/epicyon-notification --epicyon yes # # License # ======= From c28041140f8294badf767ec381844bed12cd0708 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 14 Jul 2020 15:36:18 +0100 Subject: [PATCH 5/7] Arror style tweaks --- img/icons/starlight/pagedown.png | Bin 3544 -> 3140 bytes img/icons/starlight/pageup.png | Bin 3565 -> 3103 bytes img/icons/starlight/prev.png | Bin 3548 -> 3178 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/img/icons/starlight/pagedown.png b/img/icons/starlight/pagedown.png index 28bbd007415d15c717ff8f6fe0d4936d4a7d25ee..a71972c14e5019105aba2211d5c3b42f72715a91 100644 GIT binary patch delta 3059 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 B(?tLP delta 3466 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 diff --git a/img/icons/starlight/pageup.png b/img/icons/starlight/pageup.png index 40bee46d6fd8c2667ddc994889333bcbbdab0540..ef0e4c0de9d95fb28d7bba4365e33350af15f8c1 100644 GIT binary patch delta 3046 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 delta 3528 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 delta 3470 zcmV;94RP}77~C6>BYz7MdQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+O3&cmg71O zME|*pUV=Ci%i(xV@1U387nJO@v+Nw|y;RwfHIN_z2n1AS{_nrb{D;3_-C;t^B}qyL ze?fw{%0W5KKiS{*2>W~gh3gW(pU#{61;;7R-k(2nz3#7^kAEKz+~%`DB-ks;|Wr>k_9waIG(bVS7eZQGpK0fPaRz7$7+dQ5K883~(xWQIrd)6-lfYD9P+fh+x|En9rWbn+mZR~{rk};=ev5H_n&;3 zE+295@`8=8oqxYw{4lYs8~Y~6}=czhWf?6B1?JNLfZj)}odm)Selo!{q*&rV$Tic`?d zE|YJ9Ayh#yZZ{VeSdVrN(W3o`Ex&R0+!xuODP&C^*8sSP zxg*9{4+2NBKH6lD>|C}MKNbM0Snhmq4FqhAZeXMfq=qxu6{mCaOt$-87hQ6C8g2rJ zNM>cQ5r1C+D}+e=C)?P!w+a; zq>)D%GU~Ku!W1*iIMd9tOqq2NYs;^&;z}#8vVUaNJ8BoIe{8=%&0eUvjg;P(@2GLs z|W5Qb@8T=tIL2Xa5c z&BXE}+}wA_8HMiOK+XW&pSZn1ZD^hA8?iGB)u)Fi`?x+!HLg@GYW3W=akObOQ1zJC z+<%1FSDd-US>jRAO0JU^{GSfDsqy?;2n;EWYV3(5C(1RP&;39Cwv@t8c;>Ktvh znMXg}ic7Dhm=}v)!7V(igL})qC9lWLk1TWKYIAq%w6Sih_1FxV*w2D67x)ucPVq}P zEGzgudh3G#`M~zo-h4Vi1?kZTX_-(TC3m6@ACneU-68~rUofZO{UkgwOCe8eHh-DW zJ329V;164|Jw?YoIS{*PU`m~f_>MM28>^jbA9~4cI0;Q+?9=0HPxwXOeW-1@!7#(~ zc#Z1N<@+iEmj2jqkTQ78MMCd%mBM*}X+ZOaB@66L>LD^MV@K|GZjWEr@EJ6hn_Vpn zF_FOANa$$q&Fw(d3?apB z!twQfn1Nqnw2%dPm?m@xw@$QNBP~dWL9jR6m>QuMrW4UAhNr%j3Q$pjYBd|l0E2za z<<{mRdIPBzsSA6;Xs6trQICX;0m?hpA?FD|h^^$2y>;Xv(w&gbp?{?*aaBgH zvl7ft=sbXilb&{IiApZLhYZRbpy-% z6kVft<3QZ&M5P9JQi)t2XFRPJq6C7{@ z#UfHoOjSa%t6tFHje8DDZ+~M#l#aT^KQ=#8F0yQ%@KvuRyRl0{n$fU|J}<0Mml~Kq z#OVp9X(ZuR>K@}NP(O$15hW$IN0$2x6NT&!lv42@P(9#e-UBs$lReW^w4zY4UCSrc zWj|-eB?yRlP{mtR`l_Ut7V%6ipjh3!iWF$)p?MJ~oBcevDrh727JsQZ2@=meY!{$% zDht3RE}jmHhsmYiVR~1)-a@sJqHzH$bAt7ota_bP=J#3kI;qSB)|owMr`ihq?EE0E z7k$r$3H{aRq82b(O5~)*tQ^zvkvq;@$usEV;SfqvLU4(u#c6WMvz{nu>-%1km{PM_ zxkgRb+62#+lh z(%NdQCq_z*#@8h^sN+punQdOLV*`K;&}2c0uqK&4(+aF!8h;5$Xka%jyRUnEh>alg zw*hdzf0qrohwcwetNsDSt!V>_6=4tv9Rv9WD%;dhp0Y)Ay6HOH@m^hR{bKYK!5OsGN%djbJ7_*Tc$C(}-iwkw_2MXb7Pm6$DR{iF**Py+{ zIX#$F+DbGlF@KO!tD}h;w1#-6|2o4<`uf1(tsBi}Ke8P4w!U50Ol3!%-J?06`)H;jJ4=H@+}|9_6n&A*{&mCencbZ)Ic3l{3c z+ud5+J`Z`h-t<=yd1(*1Ap+cr4Y%C)0b6VEDvP z=6k098AF+0aQ&BWP0ah(Cck@YV#;BWsQTtA&{quV;-I6Yz>ayU(&_X9GHQD5KHSt$ zB!whN(pO07tR;pNkL6v+{X&+S4_*4tWU2XEBKyo^=ASfsk3436*6g__w#z5kwMViu zuYcI?B0Gmh<4n5|n<{A~W3uNAF| z$U1xx&7fIHK!`JNwUCnNqYR7QOA$Jw%iqzPIr;6M)7z^Q`73%eC%-+?+q;Ol?O)TM zdBcBDls^hV6oTU!PmI+g?N?Bq)}GQIU4Nm%foRj#ewY<@Zy!#v5&T%UthVzYxRR7( z!kn6D^f;9T>6a2T`c_$OY?PXNCx>n^d;F3h3zw%bD7;%kRKL$_#0(=>&MOK zhWznGF=y`THg9$Np7YFKy(+%Dv9)}?^)MUEQ6WWb5Q#~Dl47a!5lV`*B}$5IlYb)5 zLAdGS7g^ce^fJAOgbE63HEz^*yzHu~<%(2Jtxb(PH)(?G7pX&mEMylEDxZ3cNh%gc zTUtXW1-qSgYS6*(qW|$AifYErGgl0)PAI=<%iqzT`E6VNj{eL~8j$b#u{-mYAGM)R zsHjFWpBk4Y8ZGbe6|YfMvkc18JTq&K*+nOQ6rK4+(b1Rqv5zD4{Sv`!cLLX>F;N4VHxZ(-(U>$Qj98=->}$~wA_F*I5F*3A zoIn7bzzGC!89(2afGW_wV7vgiikBO+1ib7=>R9e+>UusSNGEqW%fmh$TMmq=8oDDk w&HlC??ZYuTqqtF>z*uH?j1KR*{`w<)0G^qy511vgyZ`_I07*qoM6N<$g8dx6$^ZZW From 0dd0ffc3d8fc6d6a6de414f1214e548be5e5b7e4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 14 Jul 2020 18:41:57 +0100 Subject: [PATCH 6/7] handle followers/following pages --- daemon.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/daemon.py b/daemon.py index 6b9892f95..16ec828dd 100644 --- a/daemon.py +++ b/daemon.py @@ -1744,7 +1744,9 @@ class PubServer(BaseHTTPRequestHandler): divertToLoginScreen = False else: if self.path.endswith('/following') or \ + '/following?page=' in self.path or \ self.path.endswith('/followers') or \ + '/followers?page=' in self.path or \ self.path.endswith('/skills') or \ self.path.endswith('/roles') or \ self.path.endswith('/shares'): From eceb815cab4c6db050694f3557ec7cbf4f045301 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 14 Jul 2020 18:50:32 +0100 Subject: [PATCH 7/7] Use userspath --- webinterface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webinterface.py b/webinterface.py index 8099bc338..ad7db9acb 100644 --- a/webinterface.py +++ b/webinterface.py @@ -2821,7 +2821,7 @@ def htmlProfile(defaultTimeline: str, domain, port, session, wfRequest, personCache, extraJson, projectVersion, ["unfollow"], selected, - actor, pageNumber, maxItemsPerPage) + usersPath, pageNumber, maxItemsPerPage) if selected == 'followers': profileStr += \ htmlProfileFollowing(translate, baseDir, httpPrefix, @@ -2829,7 +2829,7 @@ def htmlProfile(defaultTimeline: str, domain, port, session, wfRequest, personCache, extraJson, projectVersion, ["block"], - selected, actor, pageNumber, + selected, usersPath, pageNumber, maxItemsPerPage) if selected == 'roles': profileStr += \