(* Test script to verify real-time bot event processing *) open Zulip_bot (* Logging setup *) let src = Logs.Src.create "test_realtime_bot" ~doc:"Test real-time bot" module Log = (val Logs.src_log src : Logs.LOG) (* Simple test bot that logs everything *) module Test_bot_handler : Bot_handler.S = struct let initialize _config = Log.info (fun m -> m "Bot initialized"); Ok () let usage () = "Test Bot - Verifies real-time event processing" let description () = "A test bot that logs all messages received" let handle_message ~config:_ ~storage ~identity:_ ~message ~env:_ = Log.info (fun m -> m "Received message"); (* Extract and log message details *) let content = Bot_handler.Message_context.content message in let sender = Bot_handler.Message_context.sender_email message in let is_direct = Bot_handler.Message_context.is_direct message in Log.info (fun m -> m "Content: %s" (Option.value content ~default:"")); Log.info (fun m -> m "Sender: %s" (Option.value sender ~default:"")); Log.info (fun m -> m "Direct: %b" is_direct); (* Test storage *) let test_key = "last_message" in let test_value = Option.value content ~default:"" in (match Bot_storage.put storage ~key:test_key ~value:test_value with | Ok () -> Log.info (fun m -> m "Stored message in bot storage") | Error e -> Log.err (fun m -> m "Storage error: %s" (Zulip.error_message e))); (* Always reply with confirmation *) let reply = Printf.sprintf "Test bot received: %s" (Option.value content ~default:"") in Ok (Bot_handler.Response.Reply reply) end let run_test verbosity env = (* Setup logging *) Logs.set_reporter (Logs_fmt.reporter ()); Logs.set_level (Some (match verbosity with | 0 -> Logs.Info | 1 -> Logs.Debug | _ -> Logs.Debug)); Log.info (fun m -> m "Real-time Bot Test"); Log.info (fun m -> m "=================="); (* Load auth *) let auth = match Zulip.Auth.from_zuliprc () with | Ok a -> Log.info (fun m -> m "Loaded auth for: %s" (Zulip.Auth.email a)); Log.info (fun m -> m "Server: %s" (Zulip.Auth.server_url a)); a | Error e -> Log.err (fun m -> m "Failed to load .zuliprc: %s" (Zulip.error_message e)); exit 1 in Eio.Switch.run @@ fun sw -> let client = Zulip.Client.create ~sw env auth in (* Create bot components *) let config = Bot_config.create [] in let bot_email = Zulip.Auth.email auth in let storage = Bot_storage.create client ~bot_email in let identity = Bot_handler.Identity.create ~full_name:"Test Bot" ~email:bot_email ~mention_name:"testbot" in (* Create handler and runner *) let handler = Bot_handler.create (module Test_bot_handler) ~config ~storage ~identity in let runner = Bot_runner.create ~env ~client ~handler in Log.info (fun m -> m "Starting bot in real-time mode..."); Log.info (fun m -> m "The bot will:"); Log.info (fun m -> m "- Register for message events"); Log.info (fun m -> m "- Poll for new messages"); Log.info (fun m -> m "- Process and reply to messages"); Log.info (fun m -> m "- Store messages in Zulip bot storage"); Log.info (fun m -> m "Press Ctrl+C to stop."); (* Run the bot *) Bot_runner.run_realtime runner (* Command-line interface *) open Cmdliner let verbosity = let doc = "Increase verbosity (can be used multiple times)" in let verbosity_flags = Arg.(value & flag_all & info ["v"; "verbose"] ~doc) in Term.(const List.length $ verbosity_flags) let main_cmd = let doc = "Test real-time bot for Zulip" in let man = [ `S Manpage.s_description; `P "This bot tests real-time event processing with the Zulip API. \ It will echo received messages and store them in bot storage."; `P "The bot requires a configured ~/.zuliprc file with API credentials."; ] in let info = Cmd.info "test_realtime_bot" ~version:"1.0.0" ~doc ~man in let run verbosity = Eio_main.run (run_test verbosity) in let term = Term.(const run $ verbosity) in Cmd.v info term let () = exit (Cmd.eval main_cmd)