Add sending, start work on --follow
This commit is contained in:
parent
6a35ad2554
commit
65bfa726ca
3 changed files with 109 additions and 23 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
77
mmcli.py
77
mmcli.py
|
@ -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
52
mmws.py
Normal 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()
|
Loading…
Reference in a new issue