Optional notifications for the arrival of posts from low frequency follows

merge-requests/30/head
Bob Mottram 2021-07-06 21:38:08 +01:00
parent 0eb405ef5b
commit 71c2794a19
22 changed files with 221 additions and 18 deletions

View File

@ -286,6 +286,8 @@ from bookmarks import undoBookmark
from petnames import setPetName
from followingCalendar import addPersonToCalendar
from followingCalendar import removePersonFromCalendar
from notifyOnPost import addNotifyOnPost
from notifyOnPost import removeNotifyOnPost
from devices import E2EEdevicesCollection
from devices import E2EEvalidDevice
from devices import E2EEaddDevice
@ -2087,6 +2089,34 @@ class PubServer(BaseHTTPRequestHandler):
self.server.POSTbusy = False
return
# person options screen, on notify checkbox
# See htmlPersonOptions
if '&submitNotifyOnPost=' in optionsConfirmParams:
notify = None
if 'notifyOnPost=' in optionsConfirmParams:
notify = optionsConfirmParams.split('notifyOnPost=')[1]
if '&' in notify:
notify = notify.split('&')[0]
if notify == 'on':
addNotifyOnPost(baseDir,
chooserNickname,
domain,
optionsNickname,
optionsDomainFull)
else:
removeNotifyOnPost(baseDir,
chooserNickname,
domain,
optionsNickname,
optionsDomainFull)
usersPathStr = \
usersPath + '/' + self.server.defaultTimeline + \
'?page=' + str(pageNumber)
self._redirect_headers(usersPathStr, cookie,
callingDomain)
self.server.POSTbusy = False
return
# person options screen, permission to post to newswire
# See htmlPersonOptions
if '&submitPostToNews=' in optionsConfirmParams:

View File

@ -86,6 +86,7 @@ from categories import guessHashtagCategory
from context import hasValidContext
from speaker import updateSpeaker
from announce import isSelfAnnounce
from notifyOnPost import notifyWhenPersonPosts
def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
@ -1850,6 +1851,18 @@ def _likeNotify(baseDir: str, domain: str, onionDomain: str,
pass
def _notifyPostArrival(baseDir: str, handle: str, url: str) -> None:
"""Creates a notification that a new post has arrived
"""
accountDir = baseDir + '/accounts/' + handle
if not os.path.isdir(accountDir):
return
notifyFile = accountDir + '/.newNotifiedPost'
if not os.path.isfile(notifyFile):
with open(notifyFile, 'w+') as fp:
fp.write(url)
def _replyNotify(baseDir: str, handle: str, url: str) -> None:
"""Creates a notification that a new reply has arrived
"""
@ -2275,6 +2288,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
_updateLastSeen(baseDir, handle, actor)
postIsDM = False
isGroup = _groupHandle(baseDir, handle)
if _receiveLike(recentPostsCache,
@ -2512,6 +2526,15 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
# save the post to file
if saveJson(postJsonObject, destinationFilename):
if not postIsDM:
# should we notify that a post from this person has arrived?
handleNickname = handle.split('@')[0]
handleDomain = handle.split('@')[1]
if notifyWhenPersonPosts(baseDir, nickname, domain,
handleNickname, handleDomain):
postId = removeIdEnding(postJsonObject['id'])
_notifyPostArrival(baseDir, handle, postId)
# If this is a reply to a muted post then also mute it.
# This enables you to ignore a threat that's getting boring
if isReplyToMutedPost:

104
notifyOnPost.py 100644
View File

@ -0,0 +1,104 @@
__filename__ = "notifyOnPost.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "Calendar"
import os
from utils import removeDomainPort
def _notifyOnPostArrival(baseDir: str, nickname: str, domain: str,
followingNickname: str,
followingDomain: str,
add: bool) -> None:
"""Adds or removes a handle from the following.txt list into a list
indicating whether to notify when a new post arrives from that account
"""
# check that a following file exists
domain = removeDomainPort(domain)
followingFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/following.txt'
if not os.path.isfile(followingFilename):
print("WARN: following.txt doesn't exist for " +
nickname + '@' + domain)
return
handle = followingNickname + '@' + followingDomain
# check that you are following this handle
if handle + '\n' not in open(followingFilename).read():
print('WARN: ' + handle + ' is not in ' + followingFilename)
return
notifyOnPostFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/notifyOnPost.txt'
# get the contents of the notifyOnPost file, which is
# a set of handles
followingHandles = ''
if os.path.isfile(notifyOnPostFilename):
print('notify file exists')
with open(notifyOnPostFilename, 'r') as calendarFile:
followingHandles = calendarFile.read()
else:
# create a new notifyOnPost file from the following file
print('Creating notifyOnPost file ' + notifyOnPostFilename)
followingHandles = ''
with open(followingFilename, 'r') as followingFile:
followingHandles = followingFile.read()
if add:
with open(notifyOnPostFilename, 'w+') as fp:
fp.write(followingHandles + handle + '\n')
# already in the notifyOnPost file?
if handle + '\n' in followingHandles:
print(handle + ' exists in notifyOnPost.txt')
if add:
# already added
return
# remove from calendar file
followingHandles = followingHandles.replace(handle + '\n', '')
with open(notifyOnPostFilename, 'w+') as fp:
fp.write(followingHandles)
else:
print(handle + ' not in notifyOnPost.txt')
# not already in the notifyOnPost file
if add:
# append to the list of handles
followingHandles += handle + '\n'
with open(notifyOnPostFilename, 'w+') as fp:
fp.write(followingHandles)
def addNotifyOnPost(baseDir: str, nickname: str, domain: str,
followingNickname: str,
followingDomain: str) -> None:
_notifyOnPostArrival(baseDir, nickname, domain,
followingNickname, followingDomain, True)
def removeNotifyOnPost(baseDir: str, nickname: str, domain: str,
followingNickname: str,
followingDomain: str) -> None:
_notifyOnPostArrival(baseDir, nickname, domain,
followingNickname, followingDomain, False)
def notifyWhenPersonPosts(baseDir: str, nickname: str, domain: str,
followingNickname: str,
followingDomain: str) -> bool:
"""Returns true if receiving notifications when the given publishes a post
"""
if followingNickname == nickname and followingDomain == domain:
return False
notifyOnPostFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/notifyOnPost.txt'
handle = followingNickname + '@' + followingDomain
if not os.path.isfile(notifyOnPostFilename):
# create a new notifyOnPost file
with open(notifyOnPostFilename, 'w+') as fp:
fp.write('')
return handle + '\n' in open(notifyOnPostFilename).read()

View File

@ -215,6 +215,21 @@ function notifications {
fi
fi
# send notifications for posts arriving from a particular person
epicyonNotifyFile="$epicyonDir/.newNotifiedPost"
if [ -f "$epicyonNotifyFile" ]; then
if ! grep -q "##sent##" "$epicyonNotifyFile"; then
epicyonReplyMessage=$(notification_translate_text 'New post')
epicyonNotifyFileContent=$(echo "$epicyonReplyMessage")" "$(cat "$epicyonNotifyFile")
if [[ "$epicyonNotifyFileContent" == *':'* ]]; then
epicyonReplyMessage="Epicyon: $epicyonNotifyFileContent"
fi
sendNotification "$USERNAME" "Epicyon" "$epicyonReplyMessage"
echo "##sent##" > "$epicyonNotifyFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonNotifyFile"
fi
fi
# send notifications for replies to XMPP/email users
epicyonReplyFile="$epicyonDir/.newReply"
if [ -f "$epicyonReplyFile" ]; then

View File

@ -449,5 +449,6 @@
"Import Theme": "استيراد الموضوع",
"Export Theme": "موضوع التصدير",
"Custom post submit button text": "عرف نشر إرسال نص زر",
"Blocked User Agents": "عوامل المستخدم المحظورة"
"Blocked User Agents": "عوامل المستخدم المحظورة",
"Notify me when this account posts": "أعلمني عندما ينشر الحساب هذا"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Importació temàtica",
"Export Theme": "Tema d'exportació",
"Custom post submit button text": "Text de botó d'enviament de publicacions personalitzades",
"Blocked User Agents": "Agents d'usuari bloquejats"
"Blocked User Agents": "Agents d'usuari bloquejats",
"Notify me when this account posts": "Aviseu-me quan publiqui aquest compte"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Thema Mewnforio",
"Export Theme": "Thema Allforio",
"Custom post submit button text": "Testun Post Post Post",
"Blocked User Agents": "Asiantau defnyddwyr wedi'u blocio"
"Blocked User Agents": "Asiantau defnyddwyr wedi'u blocio",
"Notify me when this account posts": "Rhoi gwybod i mi pan fydd y cyfrifon cyfrif hwn"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Theme importieren",
"Export Theme": "Theme exportieren",
"Custom post submit button text": "Benutzerdefinierte Post-Senden Schaltfläche Text",
"Blocked User Agents": "Blockierte Benutzeragenten"
"Blocked User Agents": "Blockierte Benutzeragenten",
"Notify me when this account posts": "Benachrichtigen Sie mich, wenn dieses Konto postet"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Import Theme",
"Export Theme": "Export Theme",
"Custom post submit button text": "Custom post submit button text",
"Blocked User Agents": "Blocked User Agents"
"Blocked User Agents": "Blocked User Agents",
"Notify me when this account posts": "Notify me when this account posts"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Tema de importación",
"Export Theme": "Tema de exportación",
"Custom post submit button text": "POST POST PERSONALIZADO Botón Texto",
"Blocked User Agents": "Agentes de usuario bloqueados"
"Blocked User Agents": "Agentes de usuario bloqueados",
"Notify me when this account posts": "Notifíqueme cuando se publique esta cuenta"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Import thème",
"Export Theme": "Thème d'exportation",
"Custom post submit button text": "Texte de bouton d'envoi postal personnalisé",
"Blocked User Agents": "Agents d'utilisateur bloqués"
"Blocked User Agents": "Agents d'utilisateur bloqués",
"Notify me when this account posts": "Avertissez-moi quand ce compte publie"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Téama Iompórtáil",
"Export Theme": "Téama Easpórtála",
"Custom post submit button text": "Post saincheaptha Cuir isteach an cnaipe Téacs",
"Blocked User Agents": "Gníomhairí úsáideora blocáilte"
"Blocked User Agents": "Gníomhairí úsáideora blocáilte",
"Notify me when this account posts": "Cuir in iúl dom nuair a phostófar an cuntas seo"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "आयात विषय",
"Export Theme": "निर्यात विषय",
"Custom post submit button text": "कस्टम पोस्ट सबमिट बटन टेक्स्ट",
"Blocked User Agents": "अवरुद्ध उपयोगकर्ता एजेंट"
"Blocked User Agents": "अवरुद्ध उपयोगकर्ता एजेंट",
"Notify me when this account posts": "यह खाता पोस्ट होने पर मुझे सूचित करें"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Tema dell'importazione",
"Export Theme": "Esportare tema",
"Custom post submit button text": "Pulsante di invio del post personalizzato",
"Blocked User Agents": "Agenti utente bloccati"
"Blocked User Agents": "Agenti utente bloccati",
"Notify me when this account posts": "Avvisami quando questo account messaggi"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "輸入テーマ",
"Export Theme": "テーマをエクスポートします",
"Custom post submit button text": "カスタムポスト送信ボタンテキスト",
"Blocked User Agents": "ブロックされたユーザーエージェント"
"Blocked User Agents": "ブロックされたユーザーエージェント",
"Notify me when this account posts": "この口座投稿を通知する"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Mijara Import",
"Export Theme": "Mijara Export",
"Custom post submit button text": "Nivîsa bişkojka paşîn a paşîn",
"Blocked User Agents": "Karmendên bikarhêner asteng kirin"
"Blocked User Agents": "Karmendên bikarhêner asteng kirin",
"Notify me when this account posts": "Dema ku ev postên hesabê min agahdar bikin"
}

View File

@ -445,5 +445,6 @@
"Import Theme": "Import Theme",
"Export Theme": "Export Theme",
"Custom post submit button text": "Custom post submit button text",
"Blocked User Agents": "Blocked User Agents"
"Blocked User Agents": "Blocked User Agents",
"Notify me when this account posts": "Notify me when this account posts"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Importar tema",
"Export Theme": "Exportar tema",
"Custom post submit button text": "Texto de botão de envio de post personalizado",
"Blocked User Agents": "Agentes de usuário bloqueados"
"Blocked User Agents": "Agentes de usuário bloqueados",
"Notify me when this account posts": "Notifique-me quando esta conta posts"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Импортировать тему",
"Export Theme": "Экспортная тема",
"Custom post submit button text": "Пользовательский пост Отправить кнопку текста",
"Blocked User Agents": "Заблокированные пользовательские агенты"
"Blocked User Agents": "Заблокированные пользовательские агенты",
"Notify me when this account posts": "Сообщите мне, когда эта учетная запись"
}

View File

@ -449,5 +449,6 @@
"Import Theme": "Ingiza mandhari",
"Export Theme": "Tuma mandhari",
"Custom post submit button text": "Ujumbe wa Desturi Wasilisha Nakala ya kifungo",
"Blocked User Agents": "Wakala wa watumiaji waliozuiwa"
"Blocked User Agents": "Wakala wa watumiaji waliozuiwa",
"Notify me when this account posts": "Nijulishe wakati akaunti hii ya akaunti."
}

View File

@ -449,5 +449,6 @@
"Import Theme": "进口主题",
"Export Theme": "出口主题",
"Custom post submit button text": "自定义发布提交按钮文本",
"Blocked User Agents": "阻止用户代理商"
"Blocked User Agents": "阻止用户代理商",
"Notify me when this account posts": "此帐户帖子时通知我"
}

View File

@ -23,6 +23,7 @@ from blocking import isBlocked
from follow import isFollowerOfPerson
from follow import isFollowingActor
from followingCalendar import receivingCalendarEvents
from notifyOnPost import notifyWhenPersonPosts
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
from webapp_utils import getBrokenLinkSubstitute
@ -246,8 +247,21 @@ def htmlPersonOptions(defaultTimeline: str,
'name="submitPetname">' + \
translate['Submit'] + '</button><br>\n'
# checkbox for receiving calendar events
# Notify when a post arrives from this person
if isFollowingActor(baseDir, nickname, domain, optionsActor):
checkboxStr = \
' <input type="checkbox" class="profilecheckbox" ' + \
'name="notifyOnPost" checked> 🔔' + \
translate['Notify me when this account posts'] + \
'\n <button type="submit" class="buttonsmall" ' + \
'name="submitNotifyOnPost">' + \
translate['Submit'] + '</button><br>\n'
if not notifyWhenPersonPosts(baseDir, nickname, domain,
optionsNickname,
optionsDomainFull):
checkboxStr = checkboxStr.replace(' checked>', '>')
optionsStr += checkboxStr
checkboxStr = \
' <input type="checkbox" ' + \
'class="profilecheckbox" name="onCalendar" checked> ' + \