sig
  exception ApiException of string
  module User :
    sig
      type user = {
        id : int;
        first_name : string;
        last_name : string option;
        username : string option;
      }
      val create :
        id:int ->
        first_name:string ->
        ?last_name:string option ->
        ?username:string option -> unit -> Api.User.user
      val read : Yojson.Safe.json -> Api.User.user
    end
  module Chat :
    sig
      type chat_type = Private | Group | Supergroup | Channel
      val read_type : string -> Api.Chat.chat_type
      type chat = {
        id : int;
        chat_type : Api.Chat.chat_type;
        title : string option;
        username : string option;
        first_name : string option;
        last_name : string option;
      }
      val create :
        id:int ->
        chat_type:Api.Chat.chat_type ->
        ?title:string option ->
        ?username:string option ->
        ?first_name:string option ->
        ?last_name:string option -> unit -> Api.Chat.chat
      val read : Yojson.Safe.json -> Api.Chat.chat
    end
  module InputFile :
    sig
      val load : string -> string Lwt.t
      val multipart_body :
        (string * string) list ->
        string * string * string -> string -> string Lwt.t
    end
  module PhotoSize :
    sig
      type photo_size = {
        file_id : string;
        width : int;
        height : int;
        file_size : int option;
      }
      val create :
        file_id:string ->
        width:int ->
        height:int ->
        ?file_size:int option -> unit -> Api.PhotoSize.photo_size
      val read : Yojson.Safe.json -> Api.PhotoSize.photo_size
      module Out :
        sig
          type photo_size = {
            chat_id : int;
            photo : string;
            caption : string option;
            reply_to_message_id : int option;
            reply_markup : unit option;
          }
          val create :
            chat_id:int ->
            photo:string ->
            ?caption:string option ->
            ?reply_to:int option -> unit -> Api.PhotoSize.Out.photo_size
          val prepare : Api.PhotoSize.Out.photo_size -> string
          val prepare_multipart :
            Api.PhotoSize.Out.photo_size -> string -> string Lwt.t
        end
    end
  module Audio :
    sig
      type audio = {
        file_id : string;
        duration : int;
        performer : string option;
        title : string option;
        mime_type : string option;
        file_size : int option;
      }
      val create :
        file_id:string ->
        duration:int ->
        ?performer:string option ->
        ?title:string option ->
        ?mime_type:string option ->
        ?file_size:int option -> unit -> Api.Audio.audio
      val read : Yojson.Safe.json -> Api.Audio.audio
      module Out :
        sig
          type audio = {
            chat_id : int;
            audio : string;
            duration : int option;
            performer : string;
            title : string;
            reply_to_message_id : int option;
            reply_markup : unit option;
          }
          val create :
            chat_id:int ->
            audio:string ->
            ?duration:int option ->
            performer:string ->
            title:string ->
            ?reply_to:int option -> unit -> Api.Audio.Out.audio
          val prepare : Api.Audio.Out.audio -> string
          val prepare_multipart :
            Api.Audio.Out.audio -> string -> string Lwt.t
        end
    end
  module Document :
    sig
      type document = {
        file_id : string;
        thumb : Api.PhotoSize.photo_size option;
        file_name : string option;
        mime_type : string option;
        file_size : int option;
      }
      val create :
        file_id:string ->
        ?thumb:Api.PhotoSize.photo_size option ->
        ?file_name:string option ->
        ?mime_type:string option ->
        ?file_size:int option -> unit -> Api.Document.document
      val read : Yojson.Safe.json -> Api.Document.document
    end
  module Sticker :
    sig
      type sticker = {
        file_id : string;
        width : int;
        height : int;
        thumb : Api.PhotoSize.photo_size option;
        file_size : int option;
      }
      val create :
        file_id:string ->
        width:int ->
        height:int ->
        ?thumb:Api.PhotoSize.photo_size option ->
        ?file_size:int option -> unit -> Api.Sticker.sticker
      val read : Yojson.Safe.json -> Api.Sticker.sticker
    end
  module Video :
    sig
      type video = {
        file_id : string;
        width : int;
        height : int;
        duration : int;
        thumb : Api.PhotoSize.photo_size option;
        mime_type : string option;
        file_size : int option;
      }
      val create :
        file_id:string ->
        width:int ->
        height:int ->
        duration:int ->
        ?thumb:Api.PhotoSize.photo_size option ->
        ?mime_type:string option ->
        ?file_size:int option -> unit -> Api.Video.video
      val read : Yojson.Safe.json -> Api.Video.video
    end
  module Voice :
    sig
      type voice = {
        file_id : string;
        duration : int;
        mime_type : string option;
        file_size : int option;
      }
      val create :
        file_id:string ->
        duration:int ->
        ?mime_type:string option ->
        ?file_size:int option -> unit -> Api.Voice.voice
      val read : Yojson.Safe.json -> Api.Voice.voice
      module Out :
        sig
          type voice = {
            chat_id : int;
            voice : string;
            duration : int option;
            reply_to_message_id : int option;
            reply_markup : unit option;
          }
          val create :
            chat_id:int ->
            voice:string ->
            ?duration:int option ->
            ?reply_to:int option -> unit -> Api.Voice.Out.voice
          val prepare : Api.Voice.Out.voice -> string
          val prepare_multipart :
            Api.Voice.Out.voice -> string -> string Lwt.t
        end
    end
  module Contact :
    sig
      type contact = {
        phone_number : string;
        first_name : string;
        last_name : string option;
        user_id : int option;
      }
      val create :
        phone_number:string ->
        first_name:string ->
        ?last_name:string option ->
        ?user_id:int option -> unit -> Api.Contact.contact
      val read : Yojson.Safe.json -> Api.Contact.contact
    end
  module Location :
    sig
      type location = { longitude : float; latitude : float; }
      val create :
        longitude:float -> latitude:float -> unit -> Api.Location.location
      val read : Yojson.Safe.json -> Api.Location.location
    end
  module Message :
    sig
      type message = {
        message_id : int;
        from : Api.User.user option;
        date : int;
        chat : Api.Chat.chat;
        forward_from : Api.User.user option;
        forward_date : int option;
        reply_to_message : Api.Message.message option;
        text : string option;
        audio : Api.Audio.audio option;
        document : Api.Document.document option;
        photo : Api.PhotoSize.photo_size list option;
        sticker : Api.Sticker.sticker option;
        video : Api.Video.video option;
        voice : Api.Voice.voice option;
        caption : string option;
        contact : Api.Contact.contact option;
        location : Api.Location.location option;
      }
      val create :
        message_id:int ->
        ?from:Api.User.user option ->
        date:int ->
        chat:Api.Chat.chat ->
        ?forward_from:Api.User.user option ->
        ?forward_date:int option ->
        ?reply_to:Api.Message.message option ->
        ?text:string option ->
        ?audio:Api.Audio.audio option ->
        ?document:Api.Document.document option ->
        ?photo:Api.PhotoSize.photo_size list option ->
        ?sticker:Api.Sticker.sticker option ->
        ?video:Api.Video.video option ->
        ?voice:Api.Voice.voice option ->
        ?caption:string option ->
        ?contact:Api.Contact.contact option ->
        ?location:Api.Location.location option -> unit -> Api.Message.message
      val read : Yojson.Safe.json -> Api.Message.message
      val get_sender_first_name : Api.Message.message -> string
      val get_sender_username : Api.Message.message -> string
      val get_sender : Api.Message.message -> string
    end
  module Update :
    sig
      type update = {
        update_id : int;
        message : Api.Message.message option;
      }
      val create :
        update_id:int ->
        ?message:Api.Message.message option -> unit -> Api.Update.update
      val read : Yojson.Safe.json -> Api.Update.update
    end
  module Result :
    sig
      type 'a result = Success of '| Failure of string
      val return : '-> 'Api.Result.result
      val default : '-> 'Api.Result.result -> 'a
      val ( >>= ) :
        'Api.Result.result ->
        ('-> 'Api.Result.result) -> 'Api.Result.result
      val ( <$> ) :
        ('-> 'b) -> 'Api.Result.result -> 'Api.Result.result
    end
  module Command :
    sig
      type action =
          Nothing
        | GetMe of (Api.User.user Api.Result.result -> Api.Command.action)
        | SendMessage of int * string
        | SendPhoto of int * string * string option * int option *
            (string Api.Result.result -> Api.Command.action)
        | ResendPhoto of int * string * string option * int option
        | SendAudio of int * string * string * string * int option *
            (string Api.Result.result -> Api.Command.action)
        | ResendAudio of int * string * string * string * int option
        | SendVoice of int * string * int option *
            (string Api.Result.result -> Api.Command.action)
        | ResendVoice of int * string * int option
        | GetUpdates of
            (Api.Update.update list Api.Result.result -> Api.Command.action)
        | PeekUpdate of
            (Api.Update.update Api.Result.result -> Api.Command.action)
        | PopUpdate of
            (Api.Update.update Api.Result.result -> Api.Command.action)
        | Chain of Api.Command.action * Api.Command.action
      type command = {
        name : string;
        description : string;
        mutable enabled : bool;
        run : Api.Message.message -> Api.Command.action;
      }
      val is_command : Api.Update.update -> bool
      val read_command :
        Api.Message.message -> Api.Command.command list -> Api.Command.action
      val read_update :
        Api.Update.update -> Api.Command.command list -> Api.Command.action
      val tokenize : string -> string list
    end
  module type BOT =
    sig val token : string val commands : Api.Command.command list end
  module type TELEGRAM_BOT =
    sig
      val url : string
      val commands : Api.Command.command list
      val get_me : Api.User.user Api.Result.result Lwt.t
      val send_message :
        chat_id:int -> text:string -> unit Api.Result.result Lwt.t
      val send_photo :
        chat_id:int ->
        photo:string ->
        ?caption:string option ->
        reply_to:int option -> string Api.Result.result Lwt.t
      val resend_photo :
        chat_id:int ->
        photo:string ->
        ?caption:string option ->
        reply_to:int option -> unit Api.Result.result Lwt.t
      val send_audio :
        chat_id:int ->
        audio:string ->
        performer:string ->
        title:string -> reply_to:int option -> string Api.Result.result Lwt.t
      val resend_audio :
        chat_id:int ->
        audio:string ->
        performer:string ->
        title:string -> reply_to:int option -> unit Api.Result.result Lwt.t
      val send_voice :
        chat_id:int ->
        voice:string -> reply_to:int option -> string Api.Result.result Lwt.t
      val resend_voice :
        chat_id:int ->
        voice:string -> reply_to:int option -> unit Api.Result.result Lwt.t
      val get_updates : Api.Update.update list Api.Result.result Lwt.t
      val peek_update : Api.Update.update Api.Result.result Lwt.t
      val pop_update :
        ?run_cmds:bool -> unit -> Api.Update.update Api.Result.result Lwt.t
    end
  module Mk : functor (B : BOT-> TELEGRAM_BOT
end