Add support for anonymizing select users and add content storage options

This commit is contained in:
Tulir Asokan 2019-02-17 15:57:25 +02:00
parent cf5129cbcf
commit 76f65eb9d3
2 changed files with 50 additions and 16 deletions

View File

@ -1,4 +1,16 @@
# Whether or not everyone can vote
# Whether or not to show content of messages in !karma best.
show_content: true
# Whether or not to store content of messages.
# false - no storage
# partial - store one line
# full - store whole content
store_content: partial
# SHA1 hashes of users who have opted out.
opt_out:
- 783660685956dadb4fa2f1aeac54c8525e8b75b7
# Whether or not everyone can vote.
democracy: true
# The list of people to filter.
# If democracy is enabled, this is a blacklist. Otherwise this is a whitelist.

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Awaitable, Type, Optional, Tuple
import hashlib
import json
import html
@ -41,6 +42,9 @@ DOWNVOTE = f"^(?:{DOWNVOTE_EMOJI}|{DOWNVOTE_EMOJI_SHORTHAND}|{DOWNVOTE_TEXT})$"
class Config(BaseProxyConfig):
def do_update(self, helper: ConfigUpdateHelper) -> None:
helper.copy("democracy")
helper.copy("opt_out")
helper.copy("show_content")
helper.copy("store_content")
helper.copy("filter")
helper.copy("errors.filtered_users")
helper.copy("errors.vote_on_vote")
@ -48,6 +52,10 @@ class Config(BaseProxyConfig):
helper.copy("errors.already_voted")
def sha1(val: str) -> str:
return hashlib.sha1(val.encode("utf-8")).hexdigest()
class KarmaBot(Plugin):
karma_t: Type[Karma]
version: Type[Version]
@ -140,15 +148,18 @@ class KarmaBot(Plugin):
await evt.reply(self._karma_message_list("worst"))
def _parse_content(self, evt: Event) -> str:
if not self.config["store_content"]:
return ""
if isinstance(evt, MessageEvent):
evt.content.trim_reply_fallback()
if evt.content.msgtype in (MessageType.NOTICE, MessageType.TEXT, MessageType.EMOTE):
body = evt.content.body
if evt.content.msgtype == MessageType.EMOTE:
body = "/me " + body
body = body.split("\n")[0]
if len(body) > 60:
body = body[:50] + " \u2026"
body = html.escape(body)
if self.config["store_content"] == "partial":
body = body.split("\n")[0]
if len(body) > 60:
body = body[:50] + " \u2026"
return body
name = media_reply_fallback_body_map[evt.content.msgtype]
return f"[{name}]({self.client.api.get_download_url(evt.content.url)})"
@ -169,7 +180,7 @@ class KarmaBot(Plugin):
if not target:
return
in_filter = evt.sender in self.config["filter"]
if self.config["democracy"] == in_filter:
if self.config["democracy"] == in_filter or sha1(evt.sender) in self.config["opt_out"]:
if self.config["errors.filtered_users"]:
await evt.reply("Sorry, you're not allowed to vote.")
return
@ -186,6 +197,9 @@ class KarmaBot(Plugin):
return
karma_id = dict(given_to=karma_target.sender, given_by=evt.sender, given_in=evt.room_id,
given_for=karma_target.event_id)
anonymize = sha1(karma_target.sender) in self.config["opt_out"]
if anonymize:
karma_id["given_to"] = ""
existing = self.karma_t.get(**karma_id)
if existing is not None:
if existing.value == value:
@ -195,7 +209,7 @@ class KarmaBot(Plugin):
existing.update(new_value=value)
else:
karma = self.karma_t(**karma_id, given_from=evt.event_id, value=value,
content=self._parse_content(karma_target))
content=self._parse_content(karma_target) if not anonymize else "")
karma.insert()
await evt.mark_read()
@ -203,6 +217,11 @@ class KarmaBot(Plugin):
localpart, _ = self.client.parse_mxid(mxid)
return "\u2063".join(localpart)
def _user_link(self, user_id: UserID) -> str:
if not user_id:
return "Anonymous"
return f"[{self._denotify(user_id)}](https://matrix.to/#/{user_id})"
def _karma_user_list(self, list_type: str) -> Optional[str]:
if list_type == "top":
karma_list = self.karma_t.get_top_users()
@ -213,11 +232,19 @@ class KarmaBot(Plugin):
else:
return None
message += "\n".join(
f"{index + 1}. [{self._denotify(karma.user_id)}](https://matrix.to/#/{karma.user_id}): "
f"{index + 1}. {self._user_link(karma.user_id)}: "
f"{self._sign(karma.total)} (+{karma.positive}/-{karma.negative})"
for index, karma in enumerate(karma_list))
for index, karma in enumerate(karma_list) if karma.user_id)
return message
def _message_text(self, index, event) -> str:
text = (f"{index + 1}. [Event](https://matrix.to/#/{event.room_id}/{event.event_id})"
f" by {self._user_link(event.sender)} with"
f" {self._sign(event.total)} karma (+{event.positive}/-{event.negative})\n")
if event.content and self.config["show_content"]:
text += f" \n > {html.escape(event.content)}\n"
return text
def _karma_message_list(self, list_type: str) -> Optional[str]:
if list_type == "best":
karma_list = self.karma_t.get_best_events()
@ -227,13 +254,8 @@ class KarmaBot(Plugin):
message = "#### Worst messages\n\n"
else:
return None
message += "\n".join(
f"{index + 1}. [Event](https://matrix.to/#/{event.room_id}/{event.event_id})"
f" by [{self._denotify(event.sender)}](https://matrix.to/#/{event.sender}) with"
f" {self._sign(event.total)} karma (+{event.positive}/-{event.negative})\n"
f" \n"
f" > {event.content}\n"
for index, event in enumerate(karma_list))
message += "\n".join(self._message_text(index, event)
for index, event in enumerate(karma_list))
return message
@classmethod