71b405e95d
This script moved from the bots package to the API package, and does not explicitly require python3.
93 lines
3.6 KiB
Python
Executable file
93 lines
3.6 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import sys
|
|
import os
|
|
import argparse
|
|
import multiprocessing as mp
|
|
import zulip
|
|
import interrealm_bridge_config
|
|
|
|
from typing import Any, Callable, Dict
|
|
|
|
|
|
def create_pipe_event(to_client: zulip.Client, from_bot: Dict[str, Any],
|
|
to_bot: Dict[str, Any], stream_wide: bool
|
|
) -> Callable[[Dict[str, Any]], None]:
|
|
def _pipe_message(msg: Dict[str, Any]) -> None:
|
|
isa_stream = msg["type"] == "stream"
|
|
not_from_bot = msg["sender_email"] not in (from_bot["email"], to_bot["email"])
|
|
in_the_specified_stream = msg["display_recipient"] == from_bot["stream"]
|
|
|
|
if stream_wide:
|
|
# If tunnel granularity is at stream-wide, all subjects are
|
|
# mirrored as-is without translation.
|
|
at_the_specified_subject = True
|
|
subject = msg["subject"]
|
|
else:
|
|
at_the_specified_subject = msg["subject"] == from_bot["subject"]
|
|
subject = to_bot["subject"]
|
|
|
|
if isa_stream and not_from_bot and in_the_specified_stream and at_the_specified_subject:
|
|
if "/user_uploads/" in msg["content"]:
|
|
# Fix the upload URL of the image to be the source of where it
|
|
# comes from
|
|
msg["content"] = msg["content"].replace("/user_uploads/",
|
|
from_bot["site"] + "/user_uploads/")
|
|
msg_data = {
|
|
"sender": to_client.email,
|
|
"type": "stream",
|
|
"to": to_bot["stream"],
|
|
"subject": subject,
|
|
"content": "**{0}**: {1}".format(msg["sender_full_name"], msg["content"]),
|
|
"has_attachment": msg.get("has_attachment", False),
|
|
"has_image": msg.get("has_image", False),
|
|
"has_link": msg.get("has_link", False)
|
|
}
|
|
print(msg_data)
|
|
print(to_client.send_message(msg_data))
|
|
|
|
def _pipe_event(event: Dict[str, Any]) -> None:
|
|
# See zerver/lib/events.py for a comprehensive event list
|
|
if event["type"] == "message":
|
|
msg = event["message"]
|
|
_pipe_message(msg)
|
|
return _pipe_event
|
|
|
|
if __name__ == "__main__":
|
|
usage = """run-interrealm-bridge [--stream]
|
|
|
|
Relay each message received at a specified subject in a specified stream from
|
|
the first realm to a specified subject in a specified stream in the second realm.
|
|
|
|
If the --stream flag is added, then the tunnel granularity becomes
|
|
stream-wide. All subjects are mirrored as-is without translation.
|
|
"""
|
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
|
|
|
parser = argparse.ArgumentParser(usage=usage)
|
|
parser.add_argument('--stream',
|
|
action='store_true',
|
|
help="",
|
|
default=False)
|
|
args = parser.parse_args()
|
|
|
|
options = interrealm_bridge_config.config
|
|
|
|
bot1 = options["bot_1"]
|
|
bot2 = options["bot_2"]
|
|
client1 = zulip.Client(email=bot1["email"], api_key=bot1["api_key"],
|
|
site=bot1["site"])
|
|
client2 = zulip.Client(email=bot2["email"], api_key=bot2["api_key"],
|
|
site=bot2["site"])
|
|
# A bidirectional tunnel
|
|
pipe_event1 = create_pipe_event(client2, bot1, bot2, args.stream)
|
|
p1 = mp.Process(target=client1.call_on_each_event, args=(pipe_event1, ["message"]))
|
|
pipe_event2 = create_pipe_event(client1, bot2, bot1, args.stream)
|
|
p2 = mp.Process(target=client2.call_on_each_event, args=(pipe_event2, ["message"]))
|
|
p1.start()
|
|
p2.start()
|
|
print("Listening...")
|
|
p1.join()
|
|
p2.join()
|