diff --git a/src/discuss.ml b/src/discuss.ml
new file mode 100644
index 0000000..916de87
--- /dev/null
+++ b/src/discuss.ml
@@ -0,0 +1,169 @@
+(** Creating the table of all messages.
+
+ Each message is made of :
+
+ - an id (msg_id)
+ - the id of the sender (from_id)
+ - the id of the receiver (to_id)
+ - some text (msg)
+
+ TODO: add date ? *)
+let () =
+ let create_msg_table =
+ Caqti_request.exec Caqti_type.unit
+ "CREATE TABLE IF NOT EXISTS msg ( msg_id TEXT, from_id TEXT, to_id TEXT, \
+ msg TEXT, PRIMARY KEY(msg_id), FOREIGN KEY(from_id) REFERENCES \
+ user(user_id) ON DELETE CASCADE, FOREIGN KEY(to_id) REFERENCES \
+ user(user_id) ON DELETE CASCADE);"
+ in
+ match Db.Db.exec create_msg_table () with
+ | Ok () -> ()
+ | Error _e -> Dream.error (fun log -> log "can't create msg table")
+
+(** let's find who the user is talking to so we can know if they're dangerous *)
+let find_comrades =
+ let find_comrades =
+ Caqti_request.collect
+ Caqti_type.(tup2 string string)
+ Caqti_type.(tup2 string string)
+ "SELECT from_id, to_id FROM msg WHERE from_id=? OR to_id=?"
+ in
+ fun user_id ->
+ let open Bindings in
+ let^ comrades = Db.Db.collect_list find_comrades (user_id, user_id) in
+ let comrades =
+ List.map (fun (l, r) -> if l = user_id then r else l) comrades
+ in
+ Ok (List.sort_uniq String.compare comrades)
+
+(** find all messages between two товарищи *)
+let find_messages =
+ let find_messages =
+ Caqti_request.collect
+ Caqti_type.(tup2 (tup2 string string) (tup2 string string))
+ Caqti_type.(tup2 string string)
+ "SELECT from_id, msg FROM msg WHERE (from_id=? AND to_id=?) OR \
+ (from_id=? AND to_id=?)"
+ in
+ fun k1 k2 ->
+ let open Bindings in
+ let^ comrades = Db.Db.collect_list find_messages ((k1, k2), (k2, k1)) in
+ Ok comrades
+
+(** display the list of discussions *)
+let render request =
+ match Dream.session "user_id" request with
+ | None ->
+ let redirect_url =
+ Format.sprintf "/login=?redirect=%s" (Dream.to_percent_encoded "/discuss")
+ in
+ Dream.respond ~status:`See_Other ~headers:[ ("Location", redirect_url) ] ""
+ | Some user_id -> (
+ match find_comrades user_id with
+ | Error e -> Template_utils.render_unsafe e request
+ | Ok comrades -> (
+ let comrades =
+ Bindings.unwrap_list
+ (fun id ->
+ match User.get_nick id with
+ | Error _e as e -> e
+ | Ok nick -> Ok (id, nick) )
+ comrades
+ in
+ match comrades with
+ | Error e -> Template_utils.render_unsafe e request
+ | Ok comrades ->
+ let pp_one_discuss fmt (id, nick) =
+ Format.fprintf fmt {|
% begin match Dream.session "nick" request with
diff --git a/src/template_utils.ml b/src/template_utils.ml
new file mode 100644
index 0000000..5293aca
--- /dev/null
+++ b/src/template_utils.ml
@@ -0,0 +1,21 @@
+let get_title content =
+ let open Soup in
+ try
+ let soup = content |> parse in
+ soup $ "h1" |> R.leaf_text
+ with Failure _e -> "Permap"
+
+let render ?title content request =
+ let title =
+ match title with None -> get_title content | Some title -> title
+ in
+ Dream.html
+ @@ Template.render_unsafe ~title:(Dream.html_escape title)
+ ~content:(Dream.html_escape content)
+ request
+
+let render_unsafe ?title content request =
+ let title =
+ match title with None -> get_title content | Some title -> title
+ in
+ Dream.html @@ Template.render_unsafe ~title ~content request
diff --git a/src/user.ml b/src/user.ml
index 263f23b..8cf67a5 100644
--- a/src/user.ml
+++ b/src/user.ml
@@ -387,11 +387,12 @@ let public_profile user_id =