Files
boot/irc.ml

114 lines
3.8 KiB
OCaml

(*
when all you can do is type, making things more complicated than a list is hard?
we need to design this somehow before implementing it
really the graphical drawing / window management funcitons i think at this point.
features:
- message drafts? more like, if you send too many messages to someone all at once it will hold them so you can respond later and not flood people.......
- i mean really what you want is an editable stream, so you can stage messages for later
- because i mean, if this is a bicycle, and you can make it however you want, you can just fuck with the conversation thread with computer assistance instaed of just relying on your memory.
*)
open Lwt
open Lwt_react
module F = Fmt
module Communicator = struct
type msg = {content: string; time: string; mutable seen: bool}
let create_msg ?(time = "<ts>") content =
{content; time; seen= false}
type channel =
{ mutable name: string
; mutable content: msg list
; mutable sender: string -> unit }
let add_msg (c : channel) msg = c.content <- msg :: c.content
type c = {mutable channel: channel; mutable subs: c list}
type protocol = Irc | Email | Rss | Mublog
let make_channel (c : c) ?(sender = fun _ -> ()) name =
c.subs <-
{channel= {name; content= []; sender}; subs= []} :: c.subs
let make () : c =
let c =
{ name= "top"
; content= [create_msg "Wecome to the Communicator"]
; sender= (fun _ -> ()) } in
c.sender <- (fun s -> c.content <- create_msg s :: c.content) ;
c.sender "Currently only IRC is implemented" ;
{channel= c; subs= []}
type connection = unit Lwt.t
module Irc = struct
module C = Irc_client_tls
module M = Irc_message
let connection (c : c) server port nick channels : unit Lwt.t =
let add_msg cn str = add_msg cn.channel (create_msg str) in
C.reconnect_loop ~after:30
~connect:(fun () ->
Lwt_io.printl "Connecting..."
>>= fun () ->
C.connect_by_name ~server ~port ~nick ()
>>= fun c ->
Lwt_io.printl "connect_by_name returned"
>>= fun () -> Lwt.return c )
~f:(fun connection ->
Lwt_io.printl "Connected"
>>= fun () ->
Lwt_list.iter_p
(fun channel ->
let joiner = C.send_join ~connection ~channel in
(* make_channel c ~sender:(fun s ->
C.send_privmsg ~target:channel ~message:s) channel ; *)
joiner )
channels )
~callback:(fun _connection result ->
match result with
| Result.Ok ({M.command= M.Other _; _} as msg) ->
add_msg c
(F.str "Got unknown message: %s\n" (M.to_string msg)) ;
Lwt.return_unit
| Result.Ok ({M.command= M.PRIVMSG (target, data); _} as msg)
->
add_msg c
(F.str "Got PRIVMSG: target=%s, data=%s; %s\n" target
data (M.to_string msg) ) ;
Lwt.return_unit
| Result.Ok msg ->
add_msg c (M.to_string msg) ;
Lwt.return_unit
| Result.Error e -> Lwt_io.printl e )
()
end
module Panel = struct
let panel c =
Panel.prettyprint ~height:20. ~tag:"Communicator" (fun pp ->
F.pf pp " <><><> COMMUNICATOR <><><> @.@." ;
List.iter
(fun msg -> F.pf pp "[%s] %s@." msg.time msg.content)
(List.rev c.channel.content) )
end
end
let _ =
let comm = Communicator.make () in
let hackint =
Communicator.Irc.connection comm "irc.hackint.org" 6697 "cqcaml"
["#CQC"] in
Lwt.async (fun () -> hackint) ;
root_actor := std_actor (Communicator.Panel.panel comm)
(**
program starts...
- spawn connections to servers
- these connections will populate the Channel.t in a Channel.tree
**)