Add sending, start work on --follow

This commit is contained in:
Midgard 2021-03-15 01:11:50 +01:00
parent 6a35ad2554
commit 65bfa726ca
Signed by: midgard
GPG key ID: 511C112F1331BBB4
3 changed files with 109 additions and 23 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
__pycache__/
*.pyc
*.pyo

View file

@ -10,8 +10,10 @@ import time
import json
from typing import Dict, Set, Generator, Optional, NamedTuple
import mattermost
import mattermost.ws
import re
from threading import Lock
from mmws import MMws
class NotFound(Exception):
@ -31,6 +33,14 @@ def yes_no(x):
return "yes" if x else "no"
def http_to_ws(url):
"""
Transform url from http to ws and https to wss
"""
assert url.startswith("http://") or url.startswith("https://")
return "ws" + url[4:]
def get_posts_for_channel(self, channel_id: str, progress=lambda x: None, **kwargs) -> Generator[Dict, None, None]:
"""
@raises ApiException: Passed on from lower layers.
@ -117,30 +127,50 @@ def login(mm_api, parsed):
def cat(mm_api: mattermost.MMApi, parsed):
channels = [
resolve_team_channel(mm_api, query)
for query in parsed.channels
]
# channels = [
# resolve_team_channel(mm_api, query)
# for query in parsed.channels
# ]
team, channel = resolve_team_channel(mm_api, parsed.channel)
users = list(mm_api.get_users())
if not parsed.ids:
def attribute(key_value):
key, value = key_value
if key == "channel_id":
assert value == channel["id"]
return "channel", channel["name"]
if key == "user_id":
return "username", first(u["username"] for u in users if u["id"] == value)
return key_value
else:
def attribute(key_value):
return key_value
for team, channel in channels:
if not parsed.ids:
def attribute(key_value):
key, value = key_value
if key == "channel_id":
assert value == channel["id"]
return "channel", channel["name"]
if key == "user_id":
return "username", first(u["username"] for u in users if u["id"] == value)
return key_value
else:
def attribute(key_value):
return key_value
# backlog = []
# backlog_lock = Lock()
if parsed.follow:
raise NotImplementedError("--follow is not yet supported")
# def webs_handler(mmws, event_data):
# if event_data["event"] == "posted":
# with backlog_lock:
# if backlog is not None:
# backlog.append(event_data["data"])
# return
# print(post_str(attribute, event_data["data"], parsed))
posts = get_posts_for_channel(mm_api, channel["id"], after=parsed.after)
for post in posts:
print(post_str(attribute, post, parsed))
# ws_url = http_to_ws(mm_api._url) + "/v4/websocket"
# MMws(webs_handler, mm_api, ws_url)
# return
posts = get_posts_for_channel(mm_api, channel["id"], after=parsed.after)
for post in posts:
print(post_str(attribute, post, parsed))
# with backlog_lock:
# for post in backlog:
# print(post_str(attribute, post, parsed))
# backlog = None
def send(mm_api: mattermost.MMApi, parsed):
@ -245,7 +275,7 @@ Hint: JSON output can be filtered on the command line with jq(1).
# ---
parser_cat.add_argument("--after", help="all after post with ID")
parser_cat.add_argument("--since", help="all after timestamp")
parser_cat.add_argument("-f", "--follow", help="keep running, printing new posts as they come in")
parser_cat.add_argument("-f", "--follow", action="store_true", help="keep running, printing new posts as they come in")
parser_send = subparsers.add_parser("send", help="send message(s)")
parser_send.add_argument(
@ -268,7 +298,8 @@ Hint: JSON output can be filtered on the command line with jq(1).
f"`{prog_name} {parsed.action}` requires access token; get one with `{prog_name} login` "
f"and set environment variable {ENVVAR_ACCESSTOKEN}")
mm_api = mattermost.MMApi(f"https://{parsed.server}/api")
server = parsed.server if re.match(r"^[a-z]+://", parsed.server) else f"https://{parsed.server}"
mm_api = mattermost.MMApi(f"{server}/api")
if access_token:
mm_api._headers.update({"Authorization": f"Bearer {access_token}"})

52
mmws.py Normal file
View file

@ -0,0 +1,52 @@
import sys
import json
import threading
import websocket
websocket.enableTrace(True)
class MMws:
"""
Websocket client.
"""
def __init__(self, ws_handler, api, ws_url):
self.api = api
self.ws_url = ws_url
self.ws_handler = ws_handler
self.ws_app = None
self.thread = threading.Thread(target=self._open_websocket)
self.thread.setName("websocket")
self.thread.setDaemon(False)
self.thread.start()
def _open_websocket(self):
def on_open(ws):
print("Opened")
ws.send(json.dumps({
"seq": 1, "action": "authentication_challenge", "data": {"token": self.api._bearer}
}))
def on_message(ws, msg):
print(msg)
self.ws_handler(self, msg)
def on_error(ws, error):
print(error, file=sys.stderr)
sys.exit(1)
self.ws_app = websocket.WebSocketApp(self.ws_url, on_open=on_open, on_message=on_message,
on_close=lambda ws: print("Closed"))
print("Start", flush=True)
self.ws_app.run_forever()
print("Done", flush=True)
def close_websocket(self):
self.ws_app.close()
self.thread.join()