···11-(** Echo bot example *)
11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+66+(** Echo Bot for Zulip.
77+88+ A simple bot that echoes messages back to the sender, with support for
99+ storage commands (store, get, delete, list). See {!README_ECHO_BOT.md}
1010+ for full documentation. *)
-42
examples/example.ml
···11-open Zulip
22-33-let () =
44- Eio_main.run @@ fun env ->
55- Eio.Switch.run @@ fun sw ->
66- Printf.printf "OCaml Zulip Library Example\n";
77- Printf.printf "===========================\n\n";
88-99- (* Create authentication *)
1010- let auth =
1111- Auth.create ~server_url:"https://example.zulipchat.com"
1212- ~email:"bot@example.com" ~api_key:"your-api-key"
1313- in
1414-1515- Printf.printf "Created auth for: %s\n" (Auth.email auth);
1616- Printf.printf "Server URL: %s\n" (Auth.server_url auth);
1717-1818- (* Create a message *)
1919- let message =
2020- Message.create ~type_:`Channel ~to_:[ "general" ]
2121- ~content:"Hello from OCaml Zulip library!" ~topic:"Test" ()
2222- in
2323-2424- Printf.printf "\nCreated message:\n";
2525- Printf.printf "- Type: %s\n" (Message_type.to_string (Message.type_ message));
2626- Printf.printf "- To: %s\n" (String.concat ", " (Message.to_ message));
2727- Printf.printf "- Content: %s\n" (Message.content message);
2828- Printf.printf "- Topic: %s\n"
2929- (match Message.topic message with Some t -> t | None -> "None");
3030-3131- (* Create client *)
3232- let client = Client.create ~sw env auth in
3333- Printf.printf "\nCreated client\n";
3434-3535- (* Test basic client request *)
3636- (try
3737- let _ = Client.request client ~method_:`GET ~path:"/test" () in
3838- Printf.printf "Mock request succeeded\n"
3939- with Eio.Exn.Io _ as e ->
4040- Printf.printf "Mock request failed: %s\n" (Printexc.to_string e));
4141-4242- Printf.printf "\nLibrary is working correctly!\n"
···11-(* Test script to verify real-time bot event processing *)
22-33-open Zulip_bot
44-55-(* Logging setup *)
66-let src = Logs.Src.create "test_realtime_bot" ~doc:"Test real-time bot"
77-88-module Log = (val Logs.src_log src : Logs.LOG)
99-1010-(* Simple test bot handler that logs everything *)
1111-let test_handler ~storage ~identity:_ message =
1212- Log.info (fun m -> m "Received message");
1313-1414- let content = Message.content message in
1515- let sender = Message.sender_email message in
1616- let is_direct = Message.is_private message in
1717-1818- Log.info (fun m -> m "Content: %s" content);
1919- Log.info (fun m -> m "Sender: %s" sender);
2020- Log.info (fun m -> m "Direct: %b" is_direct);
2121-2222- (* Test storage *)
2323- (try
2424- Storage.set storage "last_message" content;
2525- Log.info (fun m -> m "Stored message in bot storage")
2626- with Eio.Exn.Io _ as e ->
2727- Log.err (fun m -> m "Storage error: %s" (Printexc.to_string e)));
2828-2929- (* Always reply with confirmation *)
3030- Response.reply (Printf.sprintf "Test bot received: %s" content)
3131-3232-let run_test verbosity env =
3333- (* Setup logging *)
3434- Logs.set_reporter (Logs_fmt.reporter ());
3535- Logs.set_level
3636- (Some
3737- (match verbosity with
3838- | 0 -> Logs.Info
3939- | 1 -> Logs.Debug
4040- | _ -> Logs.Debug));
4141-4242- Log.info (fun m -> m "Real-time Bot Test");
4343- Log.info (fun m -> m "==================");
4444-4545- (* Load auth from .zuliprc *)
4646- let auth =
4747- try
4848- let a = Zulip.Auth.from_zuliprc () in
4949- Log.info (fun m -> m "Loaded auth for: %s" (Zulip.Auth.email a));
5050- Log.info (fun m -> m "Server: %s" (Zulip.Auth.server_url a));
5151- a
5252- with Eio.Exn.Io _ as e ->
5353- Log.err (fun m -> m "Failed to load .zuliprc: %s" (Printexc.to_string e));
5454- exit 1
5555- in
5656-5757- Eio.Switch.run @@ fun sw ->
5858- (* Create configuration from auth *)
5959- let config =
6060- Config.create ~name:"test-bot"
6161- ~site:(Zulip.Auth.server_url auth)
6262- ~email:(Zulip.Auth.email auth) ~api_key:(Zulip.Auth.api_key auth)
6363- ~description:"A test bot that logs all messages received" ()
6464- in
6565-6666- Log.info (fun m -> m "Starting bot in real-time mode...");
6767- Log.info (fun m -> m "The bot will:");
6868- Log.info (fun m -> m "- Register for message events");
6969- Log.info (fun m -> m "- Poll for new messages");
7070- Log.info (fun m -> m "- Process and reply to messages");
7171- Log.info (fun m -> m "- Store messages in Zulip bot storage");
7272- Log.info (fun m -> m "Press Ctrl+C to stop.");
7373-7474- (* Run the bot - now just a simple function call *)
7575- Bot.run ~sw ~env ~config ~handler:test_handler
7676-7777-(* Command-line interface *)
7878-open Cmdliner
7979-8080-let verbosity =
8181- let doc = "Increase verbosity (can be used multiple times)" in
8282- let verbosity_flags = Arg.(value & flag_all & info [ "v"; "verbose" ] ~doc) in
8383- Term.(const List.length $ verbosity_flags)
8484-8585-let main_cmd =
8686- let doc = "Test real-time bot for Zulip" in
8787- let man =
8888- [
8989- `S Manpage.s_description;
9090- `P
9191- "This bot tests real-time event processing with the Zulip API. It will \
9292- echo received messages and store them in bot storage.";
9393- `P "The bot requires a configured ~/.zuliprc file with API credentials.";
9494- ]
9595- in
9696- let info = Cmd.info "test_realtime_bot" ~version:"2.0.0" ~doc ~man in
9797- let run verbosity = Eio_main.run (run_test verbosity) in
9898- let term = Term.(const run $ verbosity) in
9999- Cmd.v info term
100100-101101-let () = exit (Cmd.eval main_cmd)