diff --git a/examples/zoomDemo.ur b/examples/zoomDemo.ur
index 33e6dc9..82294cc 100644
--- a/examples/zoomDemo.ur
+++ b/examples/zoomDemo.ur
@@ -1,14 +1,55 @@
(* For this demo, it's necessary to create zoomSecrets.urs,
* defining [api_key] and [api_secret]. *)
structure Z = Zoom.Make(Zoom.TwoLegged(ZoomSecrets))
-
-fun main () =
+
+fun meeting m =
+ case m.Id of
+ None => error Meeting has no ID!
+ | Some id =>
+ r <- Z.CloudRecordings.get id;
+ case (m.StartUrl, m.JoinUrl) of
+ (Some start, Some join) =>
+ return
+ Meeting ID {[id]}
+
+
+
+
+ {case r.ShareUrl of
+ None =>
+ | Some u => - [Share]
}
+ {case r.RecordingFiles of
+ None =>
+ | Some rfs =>
+ List.mapX (fn r => - Recording of size {[r.FileSize]}
+ {case r.PlayUrl of
+ None =>
+ | Some u => [Play]}
+ {case r.DownloadUrl of
+ None =>
+ | Some u => [Download]}
) rfs}
+
+
+ | _ => error New meeting is missing URL to start or join.
+
+fun create r =
+ m <- Z.Meetings.create ({Topic = r.Topic,
+ Typ = Zoom.Scheduled}
+ ++ Api.optionals {StartTime = readError r.StartTime,
+ Duration = 30,
+ Settings = Api.optionals {HostVideo = True,
+ AutoRecording = Zoom.Cloud}});
+ meeting m
+
+fun lookup id =
+ m <- Z.Meetings.get id;
+ meeting m
+
+val main =
rs <- Z.Meetings.list;
return
- {List.mapX (fn r => - {[r.Topic]} ({[r.StartTime]}, {[case r.Typ of
- Zoom.Scheduled => "scheduled"
- | _ => "other"]})
) rs}
+ {List.mapX (fn r => - {[r.Topic]} ({[r.StartTime]})
) rs}
Create Meeting
@@ -19,11 +60,3 @@ fun main () =
-
-and create r =
- Monad.ignore (Z.Meetings.create ({Topic = r.Topic,
- Typ = Zoom.Scheduled}
- ++ Api.optionals {StartTime = readError r.StartTime,
- Duration = 30,
- Settings = Api.optionals {Audio = Zoom.Voip}}));
- redirect (url (main ()))
diff --git a/examples/zoomDemo.urp b/examples/zoomDemo.urp
index ca82cf6..402b12e 100644
--- a/examples/zoomDemo.urp
+++ b/examples/zoomDemo.urp
@@ -3,7 +3,7 @@ rewrite all ZoomDemo/*
database dbname=zoomDemo
sql zoomDemo.sql
safeGetDefault
-allow url https://api.zoom.us/*
+allow url https://*
zoomSecrets
zoomDemo
diff --git a/examples/zoomDemo.urs b/examples/zoomDemo.urs
index 6ac44e0..61778b8 100644
--- a/examples/zoomDemo.urs
+++ b/examples/zoomDemo.urs
@@ -1 +1 @@
-val main : unit -> transaction page
+val main : transaction page
diff --git a/src/ur/zoom.ur b/src/ur/zoom.ur
index 6c72eae..fd02895 100644
--- a/src/ur/zoom.ur
+++ b/src/ur/zoom.ur
@@ -184,6 +184,39 @@ val _ : json (list string) = json_derived
unparse x
end)
+datatype global_dial_in_type =
+ Toll
+ | Tollfree
+val _ : json global_dial_in_type = json_derived
+ (fn x =>
+ case x of
+ "toll" => Toll
+ | "tollfree" => Tollfree
+ | _ => error Bad Zoom global-dial-in type {[x]})
+ (fn x =>
+ case x of
+ Toll => "toll"
+ | Tollfree => "tollfree")
+
+type global_dial_in_number = {
+ Country : string,
+ CountryName : string,
+ City : string,
+ Number : string,
+ Typ : global_dial_in_type
+}
+val _ : json global_dial_in_number = json_record {Country = "country",
+ CountryName = "country_name",
+ City = "city",
+ Number = "number",
+ Typ = "type"}
+
+type global_dial_in_country = {
+ CountryName : string
+}
+val _ : json global_dial_in_country = json_derived (fn s => {CountryName = s})
+ (fn r => r.CountryName)
+
type meeting_settings = {
HostVideo : option bool,
ParticipantVideo : option bool,
@@ -191,6 +224,7 @@ type meeting_settings = {
InMeeting : option bool,
JoinBeforeHost : option bool,
MuteUponEntry : option bool,
+ Watermark : option bool,
UsePmi : option bool,
ApprovalType : option approval_type,
RegistrationType : option registration_type,
@@ -201,9 +235,11 @@ type meeting_settings = {
AlternativeHosts : option (list string),
CloseRegistration : option bool,
WaitingRoom : option bool,
- GlobalDialInCountries : option (list string),
+ GlobalDialInCountries : option (list global_dial_in_country),
+ GlobalDialInNumbers : option (list global_dial_in_number),
ContactName : option string,
ContactEmail : option string,
+ RegistrantsConfirmationEmail : option bool,
RegistrantsEmailNotification : option bool,
MeetingAuthentication : option bool,
AuthenticationOption : option string,
@@ -217,6 +253,7 @@ val _ : json meeting_settings = json_record_withOptional
InMeeting = "in_meeting",
JoinBeforeHost = "join_before_host",
MuteUponEntry = "mute_upon_entry",
+ Watermark = "watermark",
UsePmi = "use_pmi",
ApprovalType = "approval_type",
RegistrationType = "registration_type",
@@ -228,25 +265,48 @@ val _ : json meeting_settings = json_record_withOptional
CloseRegistration = "close_registration",
WaitingRoom = "waiting_room",
GlobalDialInCountries = "global_dial_in_countries",
+ GlobalDialInNumbers = "global_dial_in_numbers",
ContactName = "contact_name",
ContactEmail = "contact_email",
+ RegistrantsConfirmationEmail = "registrants_confirmation_email",
RegistrantsEmailNotification = "registrants_email_notification",
MeetingAuthentication = "meeting_authentication",
AuthenticationOption = "authentication_option",
AuthenticationDomains = "authentication_domains"}
+datatype meeting_status =
+ Waiting
+ | Started
+ | Finished
+val _ : json meeting_status = json_derived
+ (fn x =>
+ case x of
+ "waiting" => Waiting
+ | "started" => Started
+ | "finished" => Finished
+ | _ => error Bad Zoom meeting status {[x]})
+ (fn x =>
+ case x of
+ Waiting => "waiting"
+ | Started => "started"
+ | Finished => "finished")
+
type meeting = {
Uuid : option string,
Id : option int,
HostId : option string,
Topic : string,
Typ : meeting_type,
+ Status : option meeting_status,
StartTime : option time,
Duration : option int,
Timezone : option string,
Password : option string,
+ H323Password : option string,
+ Pmi : option int,
Agenda : option string,
CreatedAt : option time,
+ StartUrl : option string,
JoinUrl : option string,
Recurrence : option recurrence,
Settings : option meeting_settings
@@ -257,12 +317,16 @@ val _ : json meeting = json_record_withOptional
{Uuid = "uuid",
Id = "id",
HostId = "host_id",
+ Status = "status",
StartTime = "start_time",
Duration = "duration",
Timezone = "timezone",
Password = "password",
+ H323Password = "h323_password",
+ Pmi = "pmi",
Agenda = "agenda",
CreatedAt = "created_at",
+ StartUrl = "start_url",
JoinUrl = "join_url",
Recurrence = "recurrence",
Settings = "settings"}
@@ -271,23 +335,120 @@ type meetings_response = {
Meetings : list meeting
}
val _ : json meetings_response = json_record {Meetings = "meetings"}
-
-type room = {
- Id : string,
- Nam : string,
- ActivationCode : string,
- Status : string
+
+datatype file_type =
+ MP4
+ | M4A
+ | TIMELINE
+ | TRANSCRIPT
+ | CHAT
+ | CC
+val _ : json file_type = json_derived
+ (fn x =>
+ case x of
+ "MP4" => MP4
+ | "M4A" => M4A
+ | "TIMELINE" => TIMELINE
+ | "TRANSCRIPT" => TRANSCRIPT
+ | "CHAT" => CHAT
+ | "CC" => CC
+ | _ => error Bad Zoom file type {[x]})
+ (fn x =>
+ case x of
+ MP4 => "MP4"
+ | M4A => "M4A"
+ | TIMELINE => "TIMELINE"
+ | TRANSCRIPT => "TRANSCRIPT"
+ | CHAT => "CHAT"
+ | CC => "CC")
+
+datatype recording_type =
+ SharedScreenWithSpeakerViewCC
+ | SharedScreenWithSpeakerView
+ | SharedScreenWithGalleryView
+ | SpeakerView
+ | GalleryView
+ | SharedScreen
+ | AudioOnly
+ | AudioTranscript
+ | ChatFile
+ | Timeline
+val _ : json recording_type = json_derived
+ (fn x =>
+ case x of
+ "shared_screen_with_speaker_view(CC)" => SharedScreenWithSpeakerViewCC
+ | "shared_screen_with_speaker_view" => SharedScreenWithSpeakerView
+ | "shared_screen_with_gallery_view" => SharedScreenWithGalleryView
+ | "speaker_view" => SpeakerView
+ | "gallery_view" => GalleryView
+ | "shared_screen" => SharedScreen
+ | "audio_only" => AudioOnly
+ | "audio_transcript" => AudioTranscript
+ | "chat_file" => ChatFile
+ | "TIMELINE" => Timeline
+ | _ => error Bad Zoom recording type {[x]})
+ (fn x =>
+ case x of
+ SharedScreenWithSpeakerViewCC => "shared_screen_with_speaker_view(CC)"
+ | SharedScreenWithSpeakerView => "shared_screen_with_speaker_view"
+ | SharedScreenWithGalleryView => "shared_screen_with_gallery_view"
+ | SpeakerView => "speaker_view"
+ | GalleryView => "gallery_view"
+ | SharedScreen => "shared_screen"
+ | AudioOnly => "audio_only"
+ | AudioTranscript => "audio_transcript"
+ | ChatFile => "chat_file"
+ | Timeline => "TIMELINE")
+
+type recording_file = {
+ Id : option string,
+ MeetingId : option string,
+ RecordingStart : option time,
+ RecordingEnd : option time,
+ FileType : option file_type,
+ FileSize : option int,
+ PlayUrl : option string,
+ DownloadUrl : option string,
+ Status : option string,
+ DeletedTime : option time,
+ RecordingType : option recording_type
}
-val _ : json room = json_record {Id = "id",
- Nam = "name",
- ActivationCode = "activation_code",
- Status = "status"}
-
-type rooms_response = {
- Rooms : list room
+val _ : json recording_file = json_record_withOptional {}
+ {Id = "id",
+ MeetingId = "meeting_id",
+ RecordingStart = "recording_start",
+ RecordingEnd = "recording_end",
+ FileType = "file_type",
+ FileSize = "file_size",
+ PlayUrl = "play_url",
+ DownloadUrl = "download_url",
+ Status = "status",
+ DeletedTime = "deleted_time",
+ RecordingType = "recording_type"}
+
+type recording = {
+ Uuid : option string,
+ Id : option int,
+ AccountId : option string,
+ HostId : option string,
+ Topic : string,
+ StartTime : option time,
+ Duration : option int,
+ TotalSize : option int,
+ ShareUrl : option string,
+ RecordingFiles : option (list recording_file)
}
-val _ : json rooms_response = json_record {Rooms = "rooms"}
-
+val _ : json recording = json_record_withOptional {Topic = "topic"}
+ {Uuid = "uuid",
+ Id = "id",
+ AccountId = "account_id",
+ HostId = "host_id",
+ StartTime = "start_time",
+ Duration = "duration",
+ TotalSize = "total_size",
+ ShareUrl = "share_url",
+ RecordingFiles = "recording_files"}
+
functor Make(M : AUTH) = struct
open M
@@ -315,12 +476,16 @@ functor Make(M : AUTH) = struct
fun create x =
s <- apiPost "users/me/meetings" (toJson x);
return (fromJson s)
+
+ fun get x =
+ s <- api ("meetings/" ^ show x);
+ return (fromJson s)
end
- structure Rooms = struct
- val list =
- s <- api "rooms";
- return (fromJson s : rooms_response).Rooms
+ structure CloudRecordings = struct
+ fun get x =
+ s <- api ("meetings/" ^ show x ^ "/recordings");
+ return (fromJson s)
end
end
diff --git a/src/ur/zoom.urs b/src/ur/zoom.urs
index 25744d3..a670e33 100644
--- a/src/ur/zoom.urs
+++ b/src/ur/zoom.urs
@@ -58,6 +58,22 @@ datatype auto_recording =
| Cloud
| NoRecording
+datatype global_dial_in_type =
+ Toll
+ | Tollfree
+
+type global_dial_in_number = {
+ Country : string,
+ CountryName : string,
+ City : string,
+ Number : string,
+ Typ : global_dial_in_type
+}
+
+type global_dial_in_country = {
+ CountryName : string
+}
+
type meeting_settings = {
HostVideo : option bool,
ParticipantVideo : option bool,
@@ -65,6 +81,7 @@ type meeting_settings = {
InMeeting : option bool,
JoinBeforeHost : option bool,
MuteUponEntry : option bool,
+ Watermark : option bool,
UsePmi : option bool,
ApprovalType : option approval_type,
RegistrationType : option registration_type,
@@ -75,46 +92,98 @@ type meeting_settings = {
AlternativeHosts : option (list string),
CloseRegistration : option bool,
WaitingRoom : option bool,
- GlobalDialInCountries : option (list string),
+ GlobalDialInCountries : option (list global_dial_in_country),
+ GlobalDialInNumbers : option (list global_dial_in_number),
ContactName : option string,
ContactEmail : option string,
+ RegistrantsConfirmationEmail : option bool,
RegistrantsEmailNotification : option bool,
MeetingAuthentication : option bool,
AuthenticationOption : option string,
AuthenticationDomains : option (list string)
}
-
+
+datatype meeting_status =
+ Waiting
+ | Started
+ | Finished
+
type meeting = {
Uuid : option string,
Id : option int,
HostId : option string,
Topic : string,
Typ : meeting_type,
+ Status : option meeting_status,
StartTime : option time,
Duration : option int,
Timezone : option string,
Password : option string,
+ H323Password : option string,
+ Pmi : option int,
Agenda : option string,
CreatedAt : option time,
+ StartUrl : option string,
JoinUrl : option string,
Recurrence : option recurrence,
Settings : option meeting_settings
}
-type room = {
- Id : string,
- Nam : string,
- ActivationCode : string,
- Status : string
+datatype file_type =
+ MP4
+ | M4A
+ | TIMELINE
+ | TRANSCRIPT
+ | CHAT
+ | CC
+
+datatype recording_type =
+ SharedScreenWithSpeakerViewCC
+ | SharedScreenWithSpeakerView
+ | SharedScreenWithGalleryView
+ | SpeakerView
+ | GalleryView
+ | SharedScreen
+ | AudioOnly
+ | AudioTranscript
+ | ChatFile
+ | Timeline
+
+type recording_file = {
+ Id : option string,
+ MeetingId : option string,
+ RecordingStart : option time,
+ RecordingEnd : option time,
+ FileType : option file_type,
+ FileSize : option int,
+ PlayUrl : option string,
+ DownloadUrl : option string,
+ Status : option string,
+ DeletedTime : option time,
+ RecordingType : option recording_type
}
+
+type recording = {
+ Uuid : option string,
+ Id : option int,
+ AccountId : option string,
+ HostId : option string,
+ Topic : string,
+ StartTime : option time,
+ Duration : option int,
+ TotalSize : option int,
+ ShareUrl : option string,
+ RecordingFiles : option (list recording_file)
+}
functor Make(M : AUTH) : sig
structure Meetings : sig
val list : transaction (list meeting)
val create : meeting -> transaction meeting
+ val get : int (* ID *) -> transaction meeting
end
- structure Rooms : sig
- val list : transaction (list room)
+ structure CloudRecordings : sig
+ val get : int (* meeting ID *) -> transaction recording
end
end