Initial commit
This commit is contained in:
commit
d6b1062fe8
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.mbp
|
||||
*.zip
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Tulir Asokan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
5
README.md
Normal file
5
README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# echo
|
||||
A simple [maubot](https://github.com/maubot/maubot) that displays everyone's homeserver software version.
|
||||
|
||||
## Usage
|
||||
* `!shame` - Reply with a list of homeservers and their respective running versions.
|
9
base-config.yaml
Normal file
9
base-config.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
# The https://github.com/matrix-org/matrix-federation-tester instance to use.
|
||||
# {server} is replaced with the server name.
|
||||
federation_tester: https://matrix.org/federationtester/api/report?server_name={server}
|
||||
#
|
||||
# Instances to ignore as they might be permanently erroring and causing slow responses
|
||||
# dead_servers:
|
||||
# - host1.example.com
|
||||
# - host2.example.com
|
||||
# - host.example.org
|
8
maubot.yaml
Normal file
8
maubot.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
maubot: 0.1.0
|
||||
id: sh.wallace.matrix.shameotron
|
||||
version: 0.0.2
|
||||
license: MIT
|
||||
modules:
|
||||
- shameotron
|
||||
main_class: ShameOTron
|
||||
database: false
|
141
shameotron.py
Normal file
141
shameotron.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
"""
|
||||
[Maubot](https://mau.dev/maubot/maubot) plugin to shame room members into
|
||||
upgrading their Matrix homeservers to the latest version.
|
||||
"""
|
||||
import json
|
||||
|
||||
from typing import Dict, List, Type
|
||||
|
||||
import requests
|
||||
|
||||
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
|
||||
from mautrix.types import TextMessageEventContent, MessageType, Format, \
|
||||
RelatesTo, RelationType, EventID, RoomID, UserID
|
||||
from mautrix.util import markdown
|
||||
|
||||
from maubot import Plugin, MessageEvent
|
||||
from maubot.handlers import command
|
||||
|
||||
|
||||
class Config(BaseProxyConfig):
|
||||
"""
|
||||
Config class
|
||||
"""
|
||||
def do_update(self, helper: ConfigUpdateHelper) -> None:
|
||||
"""
|
||||
Class method to update the config
|
||||
"""
|
||||
helper.copy('federation_tester')
|
||||
helper.copy('dead_servers')
|
||||
|
||||
|
||||
class ShameOTron(Plugin):
|
||||
"""
|
||||
Main class for the Shame-o-Tron
|
||||
"""
|
||||
async def start(self) -> None:
|
||||
"""
|
||||
Class method for plugin startup
|
||||
"""
|
||||
self.on_external_config_update()
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_config_class(cls) -> Type[Config]:
|
||||
"""
|
||||
Class method for getting the config
|
||||
"""
|
||||
return Config
|
||||
|
||||
|
||||
async def _edit(self, room_id: RoomID, event_id: EventID, text: str) -> None:
|
||||
"""
|
||||
Class method to update an existing message event
|
||||
"""
|
||||
content = TextMessageEventContent(msgtype=MessageType.NOTICE, body=text, format=Format.HTML,
|
||||
formatted_body=markdown.render(text))
|
||||
content.set_edit(event_id)
|
||||
await self.client.send_message(room_id, content)
|
||||
|
||||
|
||||
async def _load_members(self, room_id: RoomID) -> Dict[str, List[UserID]]:
|
||||
"""
|
||||
Class method to return the servers and room members
|
||||
"""
|
||||
users = await self.client.get_joined_members(room_id)
|
||||
servers: Dict[str, List[UserID]] = {}
|
||||
for user in users:
|
||||
_, server = self.client.parse_user_id(user)
|
||||
servers.setdefault(server, []).append(user)
|
||||
return servers
|
||||
|
||||
|
||||
async def query_homeserver_version(self, host):
|
||||
"""
|
||||
Function to query the Federation Tester to retrieve the running version
|
||||
for a server
|
||||
|
||||
host: (str) Server to get version for
|
||||
|
||||
Returns: (str) Version string of the server
|
||||
"""
|
||||
try:
|
||||
req = requests.get(
|
||||
self.config["federation_tester"].format(server=host),
|
||||
timeout=10000
|
||||
)
|
||||
except requests.exceptions.Timeout:
|
||||
return '[TIMEOUT]'
|
||||
|
||||
data = json.loads(req.text)
|
||||
|
||||
if not data['FederationOK']:
|
||||
return '[OFFLINE]'
|
||||
|
||||
try:
|
||||
return data['Version']['version']
|
||||
except KeyError:
|
||||
return '[ERROR]'
|
||||
|
||||
|
||||
@command.new('shame', help='Show versions of all homeservers in the room')
|
||||
async def shame_handler(self, evt: MessageEvent) -> None:
|
||||
"""
|
||||
Class method to handle the `!shame` command
|
||||
"""
|
||||
event_id = await evt.reply('Loading member list...')
|
||||
member_servers = await self._load_members(evt.room_id)
|
||||
|
||||
# Filter out the "dead servers"
|
||||
dead_servers = self.config['dead_servers']
|
||||
if dead_servers:
|
||||
# Return a unique list
|
||||
member_servers = sorted(
|
||||
list(
|
||||
set(member_servers.keys() - set(dead_servers))
|
||||
)
|
||||
)
|
||||
|
||||
await self._edit(
|
||||
evt.room_id,
|
||||
event_id,
|
||||
'Member list loaded, fetching versions... please wait...'
|
||||
)
|
||||
|
||||
versions = []
|
||||
for host in member_servers:
|
||||
versions.append(
|
||||
(host, await self.query_homeserver_version(host))
|
||||
)
|
||||
|
||||
await self._edit(
|
||||
evt.room_id,
|
||||
event_id,
|
||||
(
|
||||
'#### Homeserver versions\n'
|
||||
+ '\n'.join(
|
||||
f'* {host}: [{version}]({self.config["federation_tester"].format(server=host)})'
|
||||
for host, version in versions
|
||||
)
|
||||
)
|
||||
)
|
Loading…
Reference in a new issue