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

View File

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

View File

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

View File

@ -230,5 +230,11 @@
"Zen": "Zen",
"Night": "Nit",
"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",
"Night": "Noson",
"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",
"Night": "Nacht",
"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",
"Night": "Night",
"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",
"Night": "Noche",
"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",
"Night": "Nuit",
"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",
"Night": "Oíche",
"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": "जेन",
"Night": "रात",
"Starlight": "तारों का",
"Search banner image": "बैनर छवि खोजें"
"Search banner image": "बैनर छवि खोजें",
"Accusatory", "दोष लगानेवाला",
"you": "आप",
"your": "तुम्हारी",
"you're": "आप कर रहे हैं",
"if you": "अगर तुम",
"you are": "तुम हो"
}

View File

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

View File

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

View File

@ -229,5 +229,11 @@
"Zen": "禅",
"Night": "晚",
"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 = \
downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, postJsonObject,
projectVersion)
projectVersion, translate)
if not postJsonAnnounce:
return ''
postJsonObject = postJsonAnnounce