95 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| import argparse
 | |
| import multiprocessing as mp
 | |
| import os
 | |
| import sys
 | |
| from typing import Any, Callable, Dict
 | |
| 
 | |
| import interrealm_bridge_config
 | |
| 
 | |
| import zulip
 | |
| 
 | |
| 
 | |
| 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/"
 | |
|                 )
 | |
|             if msg["content"].startswith(("```", "- ", "* ", "> ", "1. ")):
 | |
|                 # If a message starts with special prefixes, make sure to prepend a newline for
 | |
|                 # formatting purpose
 | |
|                 msg["content"] = "\n" + msg["content"]
 | |
|             msg_data = {
 | |
|                 "type": "stream",
 | |
|                 "to": to_bot["stream"],
 | |
|                 "subject": subject,
 | |
|                 "content": "**{}**: {}".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 topic in a specified stream from
 | |
|     the first realm to a specified topic in a specified stream in the second realm.
 | |
| 
 | |
|     If the --stream flag is added, then the mirroring
 | |
|     granularity becomes stream-wide. Instead of one topic,
 | |
|     all topics within the stream 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()
 | 
