Label accusatory posts

merge-requests/30/head
Bob Mottram 2020-06-12 12:50:49 +01:00
parent a4a4c21f4e
commit 0132674ea3
20 changed files with 197 additions and 23 deletions

View File

@ -62,6 +62,7 @@ from question import questionUpdateVotes
from media import replaceYouTube from media import replaceYouTube
from git import isGitPatch from git import isGitPatch
from git import receiveGitPatch from git import receiveGitPatch
from semantic import labelAccusatoryPost
def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None: def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
@ -1316,7 +1317,7 @@ def receiveAnnounce(recentPostsCache: {},
httpPrefix: str, domain: str, onionDomain: str, port: int, httpPrefix: str, domain: str, onionDomain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
debug: bool) -> bool: debug: bool, translate: {}) -> bool:
"""Receives an announce activity within the POST section of HTTPServer """Receives an announce activity within the POST section of HTTPServer
""" """
if messageJson['type'] != 'Announce': if messageJson['type'] != 'Announce':
@ -1398,7 +1399,7 @@ def receiveAnnounce(recentPostsCache: {},
' -> ' + messageJson['object']) ' -> ' + messageJson['object'])
postJsonObject = downloadAnnounce(session, baseDir, httpPrefix, postJsonObject = downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, messageJson, nickname, domain, messageJson,
__version__) __version__, translate)
if postJsonObject: if postJsonObject:
if debug: if debug:
print('DEBUG: Announce post downloaded for ' + print('DEBUG: Announce post downloaded for ' +
@ -2007,6 +2008,8 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Undo bookmark accepted from ' + actor) print('DEBUG: Undo bookmark accepted from ' + actor)
return False return False
labelAccusatoryPost(messageJson, translate)
if receiveAnnounce(recentPostsCache, if receiveAnnounce(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
@ -2016,7 +2019,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
personCache, personCache,
messageJson, messageJson,
federationList, federationList,
debug): debug, translate):
if debug: if debug:
print('DEBUG: Announce accepted from ' + actor) print('DEBUG: Announce accepted from ' + actor)
@ -2171,7 +2174,8 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
'/users/' + nickname + '/tlreplies') '/users/' + nickname + '/tlreplies')
if isImageMedia(session, baseDir, httpPrefix, if isImageMedia(session, baseDir, httpPrefix,
nickname, domain, postJsonObject): nickname, domain, postJsonObject,
translate):
# media index will be updated # media index will be updated
updateIndexList.append('tlmedia') updateIndexList.append('tlmedia')
if isBlogPost(postJsonObject): if isBlogPost(postJsonObject):

View File

@ -51,6 +51,7 @@ from config import getConfigParam
from blocking import isBlocked from blocking import isBlocked
from filters import isFiltered from filters import isFiltered
from git import convertPostToPatch from git import convertPostToPatch
from semantic import labelAccusatoryPost
# try: # try:
# from BeautifulSoup import BeautifulSoup # from BeautifulSoup import BeautifulSoup
# except ImportError: # except ImportError:
@ -2306,14 +2307,14 @@ def isDM(postJsonObject: {}) -> bool:
def isImageMedia(session, baseDir: str, httpPrefix: str, def isImageMedia(session, baseDir: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
postJsonObject: {}) -> bool: postJsonObject: {}, translate: {}) -> bool:
"""Returns true if the given post has attached image media """Returns true if the given post has attached image media
""" """
if postJsonObject['type'] == 'Announce': if postJsonObject['type'] == 'Announce':
postJsonAnnounce = \ postJsonAnnounce = \
downloadAnnounce(session, baseDir, httpPrefix, downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, postJsonObject, nickname, domain, postJsonObject,
__version__) __version__, translate)
if postJsonAnnounce: if postJsonAnnounce:
postJsonObject = postJsonAnnounce postJsonObject = postJsonAnnounce
if postJsonObject['type'] != 'Create': if postJsonObject['type'] != 'Create':
@ -2981,7 +2982,8 @@ def rejectAnnounce(announceFilename: str):
def downloadAnnounce(session, baseDir: str, httpPrefix: str, def downloadAnnounce(session, baseDir: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
postJsonObject: {}, projectVersion: str) -> {}: postJsonObject: {}, projectVersion: str,
translate: {}) -> {}:
"""Download the post referenced by an announce """Download the post referenced by an announce
""" """
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
@ -3094,6 +3096,7 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
# pprint(announcedJson) # pprint(announcedJson)
return None return None
labelAccusatoryPost(postJsonObject, translate)
# set the id to the original status # set the id to the original status
announcedJson['id'] = postJsonObject['object'] announcedJson['id'] = postJsonObject['object']
announcedJson['object']['id'] = postJsonObject['object'] announcedJson['object']['id'] = postJsonObject['object']

67
semantic.py 100644
View File

@ -0,0 +1,67 @@
__filename__ = "semantic.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.1.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
def isAccusatory(content: str, translate: {}, threshold=3) -> bool:
"""Indicates whether the given content is an accusatory post
"""
words = ('you', 'your', "you're", 'if you', 'you are')
if translate:
wordsTranslated = []
for wrd in words:
translated = translate[wrd]
if '|' not in translated:
if translated not in wordsTranslated:
wordsTranslated.append(translated)
else:
# handle differing genders
words2 = translated.split('|')
for wrd2 in words2:
if wrd2.strip() not in wordsTranslated:
wordsTranslated.append(translated)
else:
wordsTranslated = words
contentLower = content.lower()
ctr = 0
for wrd in wordsTranslated:
ctr += contentLower.count(wrd + ' ')
if ctr >= threshold:
return True
return False
def labelAccusatoryPost(postJsonObject: {}, translate: {}, threshold=3):
"""If a post is accusatory and it doesn't mention anyone
specific and isn't a reply and it doesn't have a content
warning then add a default 'accusatory' content warning
"""
if not postJsonObject.get('object'):
return
if not isinstance(postJsonObject['object'], dict):
return
if not postJsonObject['object'].get('content'):
return
if postJsonObject['object'].get('inReplyTo'):
return
if not isinstance(postJsonObject['object']['content'], str):
return
if '@' in postJsonObject['object']['content']:
return
if not isAccusatory(postJsonObject['object']['content'],
translate, threshold):
return
cwStr = translate['Accusatory']
if postJsonObject['object'].get('summary'):
if cwStr not in postJsonObject['object']['summary']:
postJsonObject['object']['summary'] = \
cwStr + ', ' + postJsonObject['object']['summary']
else:
postJsonObject['object']['summary'] = cwStr
postJsonObject['object']['sensitive'] = True

View File

@ -68,6 +68,7 @@ from content import addHtmlTags
from content import removeLongWords from content import removeLongWords
from content import replaceContentDuplicates from content import replaceContentDuplicates
from theme import setCSSparam from theme import setCSSparam
from semantic import isAccusatory
testServerAliceRunning = False testServerAliceRunning = False
testServerBobRunning = False testServerBobRunning = False
@ -1787,8 +1788,17 @@ def testRecentPostsCache():
assert len(recentPostsCache['html'].items()) == maxRecentPosts assert len(recentPostsCache['html'].items()) == maxRecentPosts
def testAccusatory():
print('testAccusatory')
testStr = 'This is not an accusatory post'
assert(not isAccusatory(testStr, None, 3))
testStr = "If you x, and you're y then you are z"
assert(isAccusatory(testStr, None, 3))
def runAllTests(): def runAllTests():
print('Running tests...') print('Running tests...')
testAccusatory()
testWebLinks() testWebLinks()
testRecentPostsCache() testRecentPostsCache()
testTheme() testTheme()

View File

@ -230,5 +230,11 @@
"Zen": "زين", "Zen": "زين",
"Night": "ليل", "Night": "ليل",
"Starlight": "ضوء النجوم", "Starlight": "ضوء النجوم",
"Search banner image": "البحث عن صورة بانر" "Search banner image": "البحث عن صورة بانر",
"Accusatory", "اتهام",
"you": "أنت",
"your": "الخاص بك",
"you're": "أنت على",
"if you": "اذا أنت",
"you are": "أنت"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Nit", "Night": "Nit",
"Starlight": "Starlight", "Starlight": "Starlight",
"Search banner image": "Cerca imatge del banner" "Search banner image": "Cerca imatge del banner",
"Accusatory", "Acusatori",
"you": "vostè",
"your": "la seva",
"you're": "estàs",
"if you": "si tu",
"you are": "tu ets"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Noson", "Night": "Noson",
"Starlight": "Starlight", "Starlight": "Starlight",
"Search banner image": "Chwilio delwedd baner" "Search banner image": "Chwilio delwedd baner",
"Accusatory", "Cyhuddwr",
"you": "ti",
"your": "eich",
"you're": "ti",
"if you": "os ydych",
"you are": "yr ydych"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Nacht", "Night": "Nacht",
"Starlight": "Sternenlicht", "Starlight": "Sternenlicht",
"Search banner image": "Suche Banner Bild" "Search banner image": "Suche Banner Bild",
"Accusatory", "Anklagend",
"you": "du",
"your": "ihre",
"you're": "du bist",
"if you": "wenn du",
"you are": "sie sind"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Night", "Night": "Night",
"Starlight": "Starlight", "Starlight": "Starlight",
"Search banner image": "Search banner image" "Search banner image": "Search banner image",
"Accusatory", "Accusatory",
"you": "you",
"your": "your",
"you're": "you're",
"if you": "if you",
"you are": "you are"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Noche", "Night": "Noche",
"Starlight": "Luz de las estrellas", "Starlight": "Luz de las estrellas",
"Search banner image": "Buscar imagen de banner" "Search banner image": "Buscar imagen de banner",
"Accusatory", "Acusatoria",
"you": "tú",
"your": "tu",
"you're": "tu eres",
"if you": "si tu",
"you are": "usted está"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Nuit", "Night": "Nuit",
"Starlight": "Lumière des étoiles", "Starlight": "Lumière des étoiles",
"Search banner image": "Image de bannière de recherche" "Search banner image": "Image de bannière de recherche",
"Accusatory", "Accusatoire",
"you": "vous",
"your": "votre",
"you're": "tu es",
"if you": "si tu",
"you are": "tu es"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Oíche", "Night": "Oíche",
"Starlight": "Starlight", "Starlight": "Starlight",
"Search banner image": "Cuardaigh íomhá meirge" "Search banner image": "Cuardaigh íomhá meirge",
"Accusatory", "Cúisí",
"you": "tú",
"your": "do",
"you're": "tá tú",
"if you": "má tá tú",
"you are": "tá tú"
} }

View File

@ -230,5 +230,11 @@
"Zen": "जेन", "Zen": "जेन",
"Night": "रात", "Night": "रात",
"Starlight": "तारों का", "Starlight": "तारों का",
"Search banner image": "बैनर छवि खोजें" "Search banner image": "बैनर छवि खोजें",
"Accusatory", "दोष लगानेवाला",
"you": "आप",
"your": "तुम्हारी",
"you're": "आप कर रहे हैं",
"if you": "अगर तुम",
"you are": "तुम हो"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Notte", "Night": "Notte",
"Starlight": "luce stellare", "Starlight": "luce stellare",
"Search banner image": "Cerca immagine banner" "Search banner image": "Cerca immagine banner",
"Accusatory", "di accusa",
"you": "voi",
"your": "il tuo",
"you're": "sei",
"if you": "se tu",
"you are": "siete"
} }

View File

@ -230,5 +230,11 @@
"Zen": "禅", "Zen": "禅",
"Night": "夜", "Night": "夜",
"Starlight": "スターライト", "Starlight": "スターライト",
"Search banner image": "バナー画像を検索" "Search banner image": "バナー画像を検索",
"Accusatory", "非難",
"you": "君は",
"your": "君の",
"you're": "あなたは",
"if you": "もし、あんたが",
"you are": "あなたは"
} }

View File

@ -226,5 +226,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Night", "Night": "Night",
"Starlight": "Starlight", "Starlight": "Starlight",
"Search banner image": "Search banner image" "Search banner image": "Search banner image",
"Accusatory", "Accusatory",
"you": "you",
"your": "your",
"you're": "you're",
"if you": "if you",
"you are": "you are"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Noite", "Night": "Noite",
"Starlight": "Luz das estrelas", "Starlight": "Luz das estrelas",
"Search banner image": "Pesquisar imagem do banner" "Search banner image": "Pesquisar imagem do banner",
"Accusatory", "Acusatória",
"you": "você",
"your": "sua",
"you're": "você é",
"if you": "se vocês",
"you are": "tu es"
} }

View File

@ -230,5 +230,11 @@
"Zen": "Zen", "Zen": "Zen",
"Night": "Ночь", "Night": "Ночь",
"Starlight": "Звездный свет", "Starlight": "Звездный свет",
"Search banner image": "Поиск изображения баннера" "Search banner image": "Поиск изображения баннера",
"Accusatory", "обличительный",
"you": "вы",
"your": "ваш",
"you're": "Вы",
"if you": "если ты",
"you are": "ты"
} }

View File

@ -229,5 +229,11 @@
"Zen": "禅", "Zen": "禅",
"Night": "晚", "Night": "晚",
"Starlight": "星光", "Starlight": "星光",
"Search banner image": "搜索横幅图像" "Search banner image": "搜索横幅图像",
"Accusatory", "指责的",
"you": "您",
"your": "您的",
"you're": "你是",
"if you": "如果你",
"you are": "你是"
} }

View File

@ -3599,7 +3599,7 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonAnnounce = \ postJsonAnnounce = \
downloadAnnounce(session, baseDir, httpPrefix, downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, postJsonObject, nickname, domain, postJsonObject,
projectVersion) projectVersion, translate)
if not postJsonAnnounce: if not postJsonAnnounce:
return '' return ''
postJsonObject = postJsonAnnounce postJsonObject = postJsonAnnounce