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
|
import json
|
||||||
from typing import Dict, Set, Generator, Optional, NamedTuple
|
from typing import Dict, Set, Generator, Optional, NamedTuple
|
||||||
import mattermost
|
import mattermost
|
||||||
import mattermost.ws
|
|
||||||
import re
|
import re
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
|
from mmws import MMws
|
||||||
|
|
||||||
|
|
||||||
class NotFound(Exception):
|
class NotFound(Exception):
|
||||||
|
@ -31,6 +33,14 @@ def yes_no(x):
|
||||||
return "yes" if x else "no"
|
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]:
|
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.
|
@raises ApiException: Passed on from lower layers.
|
||||||
|
@ -117,30 +127,50 @@ def login(mm_api, parsed):
|
||||||
|
|
||||||
def cat(mm_api: mattermost.MMApi, parsed):
|
def cat(mm_api: mattermost.MMApi, parsed):
|
||||||
|
|
||||||
channels = [
|
# channels = [
|
||||||
resolve_team_channel(mm_api, query)
|
# resolve_team_channel(mm_api, query)
|
||||||
for query in parsed.channels
|
# for query in parsed.channels
|
||||||
]
|
# ]
|
||||||
|
team, channel = resolve_team_channel(mm_api, parsed.channel)
|
||||||
|
|
||||||
users = list(mm_api.get_users())
|
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:
|
# backlog = []
|
||||||
if not parsed.ids:
|
# backlog_lock = Lock()
|
||||||
def attribute(key_value):
|
if parsed.follow:
|
||||||
key, value = key_value
|
raise NotImplementedError("--follow is not yet supported")
|
||||||
if key == "channel_id":
|
# def webs_handler(mmws, event_data):
|
||||||
assert value == channel["id"]
|
# if event_data["event"] == "posted":
|
||||||
return "channel", channel["name"]
|
# with backlog_lock:
|
||||||
if key == "user_id":
|
# if backlog is not None:
|
||||||
return "username", first(u["username"] for u in users if u["id"] == value)
|
# backlog.append(event_data["data"])
|
||||||
return key_value
|
# return
|
||||||
else:
|
# print(post_str(attribute, event_data["data"], parsed))
|
||||||
def attribute(key_value):
|
|
||||||
return key_value
|
|
||||||
|
|
||||||
posts = get_posts_for_channel(mm_api, channel["id"], after=parsed.after)
|
# ws_url = http_to_ws(mm_api._url) + "/v4/websocket"
|
||||||
for post in posts:
|
# MMws(webs_handler, mm_api, ws_url)
|
||||||
print(post_str(attribute, post, parsed))
|
# 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):
|
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("--after", help="all after post with ID")
|
||||||
parser_cat.add_argument("--since", help="all after timestamp")
|
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 = subparsers.add_parser("send", help="send message(s)")
|
||||||
parser_send.add_argument(
|
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"`{prog_name} {parsed.action}` requires access token; get one with `{prog_name} login` "
|
||||||
f"and set environment variable {ENVVAR_ACCESSTOKEN}")
|
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:
|
if access_token:
|
||||||
mm_api._headers.update({"Authorization": f"Bearer {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