Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main

main
Bob Mottram 2021-03-09 12:03:02 +00:00
commit a9375537db
21 changed files with 207 additions and 57 deletions

View File

@ -120,6 +120,7 @@ from blocking import getDomainBlocklist
from roles import setRole
from roles import clearModeratorStatus
from roles import clearEditorStatus
from roles import clearCounselorStatus
from blog import htmlBlogPageRSS2
from blog import htmlBlogPageRSS3
from blog import htmlBlogView
@ -4728,6 +4729,63 @@ class PubServer(BaseHTTPRequestHandler):
'instance',
'editor')
# change site counselors list
if fields.get('counselors'):
if path.startswith('/users/' +
adminNickname + '/'):
counselorsFile = \
baseDir + \
'/accounts/counselors.txt'
clearCounselorStatus(baseDir)
if ',' in fields['counselors']:
# if the list was given as comma separated
edFile = open(counselorsFile, "w+")
eds = fields['counselors'].split(',')
for edNick in eds:
edNick = edNick.strip()
edDir = baseDir + \
'/accounts/' + edNick + \
'@' + domain
if os.path.isdir(edDir):
edFile.write(edNick + '\n')
edFile.close()
eds = fields['counselors'].split(',')
for edNick in eds:
edNick = edNick.strip()
edDir = baseDir + \
'/accounts/' + edNick + \
'@' + domain
if os.path.isdir(edDir):
setRole(baseDir,
edNick, domain,
'instance', 'counselor')
else:
# nicknames on separate lines
edFile = open(counselorsFile, "w+")
eds = fields['counselors'].split('\n')
for edNick in eds:
edNick = edNick.strip()
edDir = \
baseDir + \
'/accounts/' + edNick + \
'@' + domain
if os.path.isdir(edDir):
edFile.write(edNick + '\n')
edFile.close()
eds = fields['counselors'].split('\n')
for edNick in eds:
edNick = edNick.strip()
edDir = \
baseDir + \
'/accounts/' + \
edNick + '@' + \
domain
if os.path.isdir(edDir):
setRole(baseDir,
edNick, domain,
'instance',
'counselor')
# remove scheduled posts
if fields.get('removeScheduledPosts'):
if fields['removeScheduledPosts'] == 'on':

View File

@ -51,6 +51,14 @@ def clearEditorStatus(baseDir: str) -> None:
_clearRoleStatus(baseDir, 'editor')
def clearCounselorStatus(baseDir: str) -> None:
"""Removes counselor status from all accounts
This could be slow if there are many users, but only happens
rarely when counselors are appointed or removed
"""
_clearRoleStatus(baseDir, 'editor')
def clearModeratorStatus(baseDir: str) -> None:
"""Removes moderator status from all accounts
This could be slow if there are many users, but only happens
@ -119,7 +127,8 @@ def setRole(baseDir: str, nickname: str, domain: str,
roleFiles = {
"moderator": "moderators.txt",
"editor": "editors.txt"
"editor": "editors.txt",
"counselor": "counselors.txt"
}
actorJson = loadJson(actorFilename)

View File

@ -6,7 +6,7 @@
#
# Something like:
#
# */1 * * * * root /usr/local/bin/epicyon-notification --epicyon yes
# */1 * * * * root /usr/local/bin/epicyon-notification
#
# License
# =======
@ -29,6 +29,8 @@
PROJECT_NAME=epicyon
epicyonInstallDir=/opt/${PROJECT_NAME}
MY_EMAIL_ADDRESS="username@domain"
local_domain=$HOSTNAME
if [ -f /var/lib/tor/hidden_service_epicyon/hostname ]; then
local_domain=$(cat /var/lib/tor/hidden_service_epicyon/hostname)
@ -38,18 +40,18 @@ fi
function notification_translate_text {
text="$1"
if ! grep -q '"language":' "${epicyonInstallDir}/config.json"; then
echo "$text"
return
echo "$text"
return
fi
language=$(cat "${epicyonInstallDir}/config.json" | awk -F '"language":' '{print $2}' | awk -F '"' '{print $2}')
translationsFilename="${epicyonInstallDir}/translations/${language}.json"
if [ ! -f "$translationsFilename" ]; then
echo "$text"
return
echo "$text"
return
fi
if ! grep -q "\"$text\":" "$translationsFilename"; then
echo "$text"
return
echo "$text"
return
fi
grep "\"$text\":" "$translationsFilename" | awk -F '"' '{print $4}'
}
@ -71,7 +73,7 @@ function matrix_server_message {
MATRIX_DATA_DIR='/var/lib/matrix'
homeserver_config="${MATRIX_DATA_DIR}/homeserver.yaml"
# shellcheck disable=SC2002
MATRIX_DOMAIN_NAME=$(cat "$homeserver_config" | grep "server_name:" | head -n 1 | awk -F '"' '{print $2}')
if [ ! "$MATRIX_DOMAIN_NAME" ]; then
@ -110,26 +112,42 @@ function sendNotification {
USERNAME="$1"
SUBJECT="$2"
MESSAGE="$3"
hasSent=
if [ -d /etc/prosody ]; then
if [ -f /usr/bin/sendxmpp ]; then
# generate a random password for a temporary user account
notification_user_password=$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 30 ; echo -n '')
# register a temporary xmpp user account to send the message
if prosodyctl register "notification" "$local_domain" "$notification_user_password"; then
if [[ "$SUBJECT" == *' Tor '* ]]; then
MESSAGE="$SUBJECT"
fi
if [ -f /usr/bin/sendxmpp ]; then
# kill any existing message which hasn't sent
kill_sendxmpp_process
# send the xmpp notification using the temporary account
echo "${MESSAGE}" | /usr/bin/sendxmpp -u notification -p "${notification_user_password}" -j localhost -o ${local_domain} --message-type=headline -n -t -s ${PROJECT_NAME} ${USERNAME}@${local_domain}
hasSent=1
fi
fi
# remove the temporary xmpp account
prosodyctl deluser "notification@$local_domain"
fi
fi
if [ -d /etc/matrix ]; then
matrix_server_message "${USERNAME}" "${USERNAME}" "$MESSAGE"
hasSent=1
fi
if [ ! "$hasSent" ]; then
if [[ "$MY_EMAIL_ADDRESS" != "username@domain" ]]; then
# send to a fixed email address for a single user instance
echo "$MESSAGE" | /usr/bin/mail -s "$SUBJECT" "$MY_EMAIL_ADDRESS"
fi
fi
}
@ -140,28 +158,28 @@ function notifications {
fi
if [ ! -f "${epicyonInstallDir}/config.json" ]; then
return
return
fi
# shellcheck disable=SC2002
EPICYON_DOMAIN_NAME=$(cat "${epicyonInstallDir}/config.json" | awk -F '"domain":' '{print $2}' | awk -F '"' '{print $2}')
for d in ${epicyonInstallDir}/accounts/*/ ; do
if [[ "$d" != *'@'* ]]; then
continue
fi
epicyonDir="${d::-1}"
USERNAME=$(echo "$epicyonDir" | awk -F '/' '{print $5}' | awk -F '@' '{print $1}')
if [[ "$d" != *'@'* ]]; then
continue
fi
epicyonDir="${d::-1}"
USERNAME=$(echo "$epicyonDir" | awk -F '/' '{print $5}' | awk -F '@' '{print $1}')
# send notifications for calendar events to XMPP/email users
epicyonCalendarfile="$epicyonDir/.newCalendar"
if [ -f "$epicyonCalendarfile" ]; then
if ! grep -q "##sent##" "$epicyonCalendarfile"; then
epicyonCalendarmessage=$(notification_translate_text 'New calendar event')
epicyonCalendarmessage=$(notification_translate_text 'Calendar')
epicyonCalendarfileContent=$(echo "$epicyonCalendarmessage")" "$(cat "$epicyonCalendarfile")
if [[ "$epicyonCalendarfileContent" == '/calendar'* ]]; then
epicyonCalendarmessage="Epicyon: ${EPICYON_DOMAIN_NAME}/users/${USERNAME}${epicyonCalendarfileContent}"
fi
sendNotification "$USERNAME" "Epicyon" "$epicyonCalendarmessage"
sendNotification "$USERNAME" "Epicyon" "$epicyonCalendarmessage"
echo "##sent##" >> "$epicyonCalendarfile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonCalendarfile"
fi
@ -171,12 +189,12 @@ function notifications {
epicyonDMfile="$epicyonDir/.newDM"
if [ -f "$epicyonDMfile" ]; then
if ! grep -q "##sent##" "$epicyonDMfile"; then
epicyonDMmessage=$(notification_translate_text 'New direct message')
epicyonDMmessage=$(notification_translate_text 'DM')
epicyonDMfileContent=$(echo "$epicyonDMmessage")" "$(cat "$epicyonDMfile")
if [[ "$epicyonDMfileContent" == *':'* ]]; then
epicyonDMmessage="Epicyon: $epicyonDMfileContent"
fi
sendNotification "$USERNAME" "Epicyon" "$epicyonDMmessage"
sendNotification "$USERNAME" "Epicyon" "$epicyonDMmessage"
echo "##sent##" > "$epicyonDMfile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonDMfile"
fi
@ -186,7 +204,7 @@ function notifications {
epicyonLikeFile="$epicyonDir/.newLike"
if [ -f "$epicyonLikeFile" ]; then
if ! grep -q "##sent##" "$epicyonLikeFile"; then
epicyonLikeMessage=$(notification_translate_text 'liked your post')
epicyonLikeMessage=$(notification_translate_text 'Liked by')
epicyonLikeFileContent=$(cat "$epicyonLikeFile" | awk -F ' ' '{print $1}')" "$(echo "$epicyonLikeMessage")" "$(cat "$epicyonLikeFile" | awk -F ' ' '{print $2}')
if [[ "$epicyonLikeFileContent" == *':'* ]]; then
epicyonLikeMessage="Epicyon: $epicyonLikeFileContent"
@ -201,12 +219,12 @@ function notifications {
epicyonReplyFile="$epicyonDir/.newReply"
if [ -f "$epicyonReplyFile" ]; then
if ! grep -q "##sent##" "$epicyonReplyFile"; then
epicyonReplyMessage=$(notification_translate_text 'New reply')
epicyonReplyMessage=$(notification_translate_text 'Replies')
epicyonReplyFileContent=$(echo "$epicyonReplyMessage")" "$(cat "$epicyonReplyFile")
if [[ "$epicyonReplyFileContent" == *':'* ]]; then
epicyonReplyMessage="Epicyon: $epicyonReplyFileContent"
fi
sendNotification "$USERNAME" "Epicyon" "$epicyonReplyMessage"
sendNotification "$USERNAME" "Epicyon" "$epicyonReplyMessage"
echo "##sent##" > "$epicyonReplyFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonReplyFile"
fi
@ -216,18 +234,18 @@ function notifications {
epicyonPatchFile="$epicyonDir/.newPatch"
if [ -f "$epicyonPatchFile" ]; then
if [ -f "${epicyonPatchFile}Content" ]; then
if ! grep -q "##sent##" "$epicyonPatchFile"; then
epicyonPatchMessage=$(cat "$epicyonPatchFile")
if [ "$epicyonPatchMessage" ]; then
# notify the member
sendNotification "$USERNAME" "Epicyon" "$epicyonPatchMessage"
echo "##sent##" > "$epicyonPatchFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonPatchFile"
# send the patch to them by email
cat "${epicyonPatchFile}Content" | mail -s "[Epicyon] $epicyonPatchMessage" "${USERNAME}@${HOSTNAME}"
rm "${epicyonPatchFile}Content"
fi
fi
if ! grep -q "##sent##" "$epicyonPatchFile"; then
epicyonPatchMessage=$(cat "$epicyonPatchFile")
if [ "$epicyonPatchMessage" ]; then
# notify the member
sendNotification "$USERNAME" "Epicyon" "$epicyonPatchMessage"
echo "##sent##" > "$epicyonPatchFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonPatchFile"
# send the patch to them by email
cat "${epicyonPatchFile}Content" | mail -s "[Epicyon] $epicyonPatchMessage" "${USERNAME}@${HOSTNAME}"
rm "${epicyonPatchFile}Content"
fi
fi
fi
fi
@ -235,12 +253,12 @@ function notifications {
epicyonShareFile="$epicyonDir/.newShare"
if [ -f "$epicyonShareFile" ]; then
if ! grep -q "##sent##" "$epicyonShareFile"; then
epicyonShareMessage=$(notification_translate_text 'New shared item')
epicyonShareMessage=$(notification_translate_text 'Shares')
epicyonShareFileContent=$(echo "$epicyonShareMessage")" "$(cat "$epicyonShareFile")
if [[ "$epicyonShareFileContent" == *':'* ]]; then
epicyonShareMessage="Epicyon: $epicyonShareFileContent"
fi
sendNotification "$USERNAME" "Epicyon" "$epicyonShareMessage"
sendNotification "$USERNAME" "Epicyon" "$epicyonShareMessage"
echo "##sent##" > "$epicyonShareFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonShareFile"
fi
@ -264,13 +282,13 @@ function notifications {
if [ $epicyonNotify ]; then
cp "$epicyonFollowFile" "$epicyonFollowNotificationsFile"
chown ${PROJECT_NAME}:${PROJECT_NAME} "$epicyonFollowNotificationsFile"
epicyonFollowMessage=$(notification_translate_text "New follow request")" ${EPICYON_DOMAIN_NAME}/users/${USERNAME}/followers"
sendNotification "$USERNAME" "Epicyon" "$epicyonFollowMessage"
epicyonFollowMessage=$(notification_translate_text 'Approve follower requests')" ${EPICYON_DOMAIN_NAME}/users/${USERNAME}/followers"
sendNotification "$USERNAME" "Epicyon" "$epicyonFollowMessage"
fi
fi
fi
done
done
}
notifications

View File

@ -380,6 +380,9 @@ def _postToSpeakerJson(baseDir: str, nickname: str, domain: str,
content = urllib.parse.unquote_plus(postJsonObject['object']['content'])
content = html.unescape(content)
content = content.replace('<p>', '').replace('</p>', ' ')
# replace some emoji before removing html
if ' <3' in content:
content = content.replace(' <3', ' ' + translate['heart'])
content = removeHtml(htmlReplaceQuoteMarks(content))
content = speakerReplaceLinks(content, translate, detectedLinks)
content = _speakerPronounce(baseDir, content, translate)

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "التصفية والحظر",
"Role Assignment": "تعيين الدور",
"Contact Details": "بيانات المتصل",
"Background Images": "صور الخلفية"
"Background Images": "صور الخلفية",
"heart": "قلب",
"counselor": "مستشار",
"Counselors": "المستشارين"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtratge i bloqueig",
"Role Assignment": "Assignació de funcions",
"Contact Details": "Detalls de contacte",
"Background Images": "Imatges de fons"
"Background Images": "Imatges de fons",
"heart": "cor",
"counselor": "conseller",
"Counselors": "Consellers"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Hidlo a Blocio",
"Role Assignment": "Aseiniad Rôl",
"Background Images": "Delweddau Cefndir",
"Contact Details": "Manylion cyswllt"
"Contact Details": "Manylion cyswllt",
"heart": "galon",
"counselor": "cynghorydd",
"Counselors": "Cynghorwyr"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtern und Blockieren",
"Role Assignment": "Rollenzuweisung",
"Background Images": "Hintergrundbilder",
"Contact Details": "Kontaktdetails"
"Contact Details": "Kontaktdetails",
"heart": "herz",
"counselor": "Beraterin",
"Counselors": "Berater"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtering and Blocking",
"Role Assignment": "Role Assignment",
"Contact Details": "Contact Details",
"Background Images": "Background Images"
"Background Images": "Background Images",
"heart": "heart",
"counselor": "counselor",
"Counselors": "Counselors"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtrado y bloqueo",
"Role Assignment": "Asignación de roles",
"Background Images": "Imágenes de fondo",
"Contact Details": "Detalles de contacto"
"Contact Details": "Detalles de contacto",
"heart": "corazón",
"counselor": "Consejera",
"Counselors": "Consejeras"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtrage et blocage",
"Role Assignment": "Attribution de rôle",
"Background Images": "Images d'arrière-plan",
"Contact Details": "Détails du contact"
"Contact Details": "Détails du contact",
"heart": "cœur",
"counselor": "Conseillère",
"Counselors": "Conseillères"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Scagadh agus Blocáil",
"Role Assignment": "Sannadh Róil",
"Background Images": "Íomhánna Cúlra",
"Contact Details": "Sonraí Teagmhála"
"Contact Details": "Sonraí Teagmhála",
"heart": "chroí",
"counselor": "Comhairleoir",
"Counselors": "Comhairleoirí"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "छानना और अवरुद्ध करना",
"Role Assignment": "भूमिका असाइनमेंट",
"Background Images": "पृष्ठभूमि छवियों",
"Contact Details": "सम्पर्क करने का विवरण"
"Contact Details": "सम्पर्क करने का विवरण",
"heart": "दिल",
"counselor": "काउंसलर",
"Counselors": "सलाहकार"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtraggio e blocco",
"Role Assignment": "Assegnazione del ruolo",
"Background Images": "Immagini di sfondo",
"Contact Details": "Dettagli del contatto"
"Contact Details": "Dettagli del contatto",
"heart": "cuore",
"counselor": "Consulente",
"Counselors": "Consiglieri"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "フィルタリングとブロッキング",
"Role Assignment": "役割の割り当て",
"Background Images": "背景画像",
"Contact Details": "連絡先の詳細"
"Contact Details": "連絡先の詳細",
"heart": "ハート",
"counselor": "カウンセラー",
"Counselors": "カウンセラー"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Fîlterkirin û Astengkirin",
"Role Assignment": "Erk Rol",
"Contact Details": "Agahdariyên Têkiliyê",
"Background Images": "Wêneyên Paşê"
"Background Images": "Wêneyên Paşê",
"heart": "dil",
"counselor": "Pêşnîyarvan",
"Counselors": "Selêwirmendan"
}

View File

@ -392,5 +392,8 @@
"Filtering and Blocking": "Filtering and Blocking",
"Role Assignment": "Role Assignment",
"Background Images": "Background Images",
"Contact Details": "Contact Details"
"Contact Details": "Contact Details",
"heart": "heart",
"counselor": "Counselors",
"Counselors": "Counselors"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Filtragem e Bloqueio",
"Role Assignment": "Atribuição de Função",
"Background Images": "Imagens de fundo",
"Contact Details": "Detalhes do contato"
"Contact Details": "Detalhes do contato",
"heart": "coração",
"counselor": "Conselheira",
"Counselors": "Conselheiras"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "Фильтрация и блокировка",
"Role Assignment": "Назначение ролей",
"Background Images": "Фоновые изображения",
"Contact Details": "Контактная информация"
"Contact Details": "Контактная информация",
"heart": "сердце",
"counselor": "Советник",
"Counselors": "Советники"
}

View File

@ -396,5 +396,8 @@
"Filtering and Blocking": "过滤和阻止",
"Role Assignment": "角色分配",
"Background Images": "背景图片",
"Contact Details": "联系方式"
"Contact Details": "联系方式",
"heart": "心",
"counselor": "顾问",
"Counselors": "辅导员"
}

View File

@ -1387,6 +1387,20 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
' <textarea id="message" name="editors" placeholder="" ' + \
'style="height:200px" spellcheck="false">' + \
editors + '</textarea>'
# counselors
counselors = ''
counselorsFile = baseDir + '/accounts/counselors.txt'
if os.path.isfile(counselorsFile):
with open(counselorsFile, "r") as f:
counselors = f.read()
roleAssignStr += ' <b><label class="labels">' + \
translate['Counselors'] + '</label></b><br>\n'
roleAssignStr += \
' <textarea id="message" name="counselors" ' + \
'placeholder="" ' + \
'style="height:200px" spellcheck="false">' + \
counselors + '</textarea>'
roleAssignStr += ' </div></details>\n'
# Video section