001/*
002 *   Copyright 2024 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.voice.ncco;
017
018import com.fasterxml.jackson.annotation.JsonProperty;
019import com.vonage.client.JsonableBaseObject;
020import java.util.Arrays;
021import java.util.Collection;
022
023/**
024 * An NCCO record action which allows for the call to be recorded.
025 * <p>
026 *
027 * The record action is asynchronous. Recording starts when the record action is executed in the NCCO and finishes
028 * when the synchronous condition in the action is met. That is, endOnSilence, timeOut or endOnKey. If you do not
029 * set a synchronous condition, the Voice API immediately executes the next NCCO without recording.
030 */
031public final class RecordAction extends JsonableBaseObject implements Action {
032    private static final String ACTION = "record";
033
034    private RecordingFormat format;
035    private Integer endOnSilence, timeOut, channels;
036    private Character endOnKey;
037    private Boolean beepStart;
038    private Collection<String> eventUrl;
039    private EventMethod eventMethod;
040    private SplitRecording split;
041    private TranscriptionSettings transcription;
042
043    RecordAction() {}
044
045    private RecordAction(Builder builder) {
046        format = builder.format;
047        endOnSilence = builder.endOnSilence;
048        endOnKey = builder.endOnKey;
049        timeOut = builder.timeOut;
050        beepStart = builder.beepStart;
051        eventUrl = builder.eventUrl;
052        eventMethod = builder.eventMethod;
053        // Split conversation must be enabled for multiple channels. Checked during construction to avoid
054        // method-chaining state confusion.
055        split = (builder.channels != null && builder.channels > 1) ? SplitRecording.CONVERSATION : builder.split;
056        channels = builder.channels;
057        transcription = builder.transcription;
058    }
059
060    @Override
061    public String getAction() {
062        return ACTION;
063    }
064
065    @JsonProperty("format")
066    public RecordingFormat getFormat() {
067        return format;
068    }
069
070    @JsonProperty("endOnSilence")
071    public Integer getEndOnSilence() {
072        return endOnSilence;
073    }
074
075    @JsonProperty("endOnKey")
076    public Character getEndOnKey() {
077        return endOnKey;
078    }
079
080    @JsonProperty("timeOut")
081    public Integer getTimeOut() {
082        return timeOut;
083    }
084
085    @JsonProperty("beepStart")
086    public Boolean getBeepStart() {
087        return beepStart;
088    }
089
090    @JsonProperty("eventUrl")
091    public Collection<String> getEventUrl() {
092        return eventUrl;
093    }
094
095    @JsonProperty("eventMethod")
096    public EventMethod getEventMethod() {
097        return eventMethod;
098    }
099
100    @JsonProperty("split")
101    public SplitRecording getSplit() {
102        return split;
103    }
104
105    @JsonProperty("channels")
106    public Integer getChannels() {
107        return channels;
108    }
109
110    @JsonProperty("transcription")
111    public TranscriptionSettings getTranscription() {
112        return transcription;
113    }
114
115    /**
116     * Entrypoint for constructing an instance of this class.
117     *
118     * @return A new Builder.
119     */
120    public static Builder builder() {
121        return new Builder();
122    }
123
124    /**
125     * Builder for a RecordAction. All fields are optional.
126     */
127    public static class Builder {
128        private RecordingFormat format;
129        private Character endOnKey;
130        private Integer timeOut, channels, endOnSilence;
131        private Boolean beepStart;
132        private Collection<String> eventUrl;
133        private EventMethod eventMethod;
134        private SplitRecording split;
135        private TranscriptionSettings transcription;
136
137        Builder() {}
138
139        /**
140         * @param format Record the Call in a specific {@link RecordingFormat}.
141         *               <p>
142         *               The default value is {@link RecordingFormat#MP3}, or {@link RecordingFormat#WAV} when recording
143         *               more than 2 channels.
144         *
145         * @return This builder.
146         */
147        public Builder format(RecordingFormat format) {
148            this.format = format;
149            return this;
150        }
151
152        /**
153         * @param endOnSilence Stop recording after n seconds of silence. Once the recording is stopped the recording
154         *                     data is sent to event_url. The range of possible values is between 3 and 10 inclusively.
155         *
156         * @return This builder.
157         */
158        public Builder endOnSilence(Integer endOnSilence) {
159            this.endOnSilence = endOnSilence;
160            return this;
161        }
162
163        /**
164         * @param endOnKey Stop recording when a digit is pressed on the handset. Possible values are: *, # or any
165         *                 single digit e.g. 9
166         *
167         * @return This builder.
168         */
169        public Builder endOnKey(Character endOnKey) {
170            this.endOnKey = endOnKey;
171            return this;
172        }
173
174        /**
175         * @param timeOut The maximum length of a recording in seconds. One the recording is stopped the recording data
176         *                is sent to event_url. The range of possible values is between 3 seconds and 7200 seconds (2
177         *                hours)
178         *
179         * @return This builder.
180         */
181        public Builder timeOut(Integer timeOut) {
182            this.timeOut = timeOut;
183            return this;
184        }
185
186        /**
187         * @param beepStart Set to true to play a beep when a recording starts
188         *
189         * @return This builder.
190         */
191        public Builder beepStart(Boolean beepStart) {
192            this.beepStart = beepStart;
193            return this;
194        }
195
196        /**
197         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
198         *                 If the message recording is hosted by Vonage, this webhook contains the URL you need to
199         *                 download the recording and other meta data.
200         *
201         * @return This builder.
202         */
203        public Builder eventUrl(Collection<String> eventUrl) {
204            this.eventUrl = eventUrl;
205            return this;
206        }
207
208        /**
209         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
210         *                 If the message recording is hosted by Vonage, this webhook contains the URL you need to
211         *                 download the recording and other meta data.
212         *
213         * @return This builder.
214         */
215        public Builder eventUrl(String... eventUrl) {
216            return eventUrl(Arrays.asList(eventUrl));
217        }
218
219        /**
220         * @param eventMethod The HTTP method used to make the request to eventUrl. The default value is POST.
221         *
222         * @return This builder.
223         */
224        public Builder eventMethod(EventMethod eventMethod) {
225            this.eventMethod = eventMethod;
226            return this;
227        }
228
229        /**
230         * @param split Record the sent and received audio in separate channels of a stereo recording-set to {@link
231         *              SplitRecording#CONVERSATION} to enable this.
232         *
233         * @return This builder.
234         */
235        public Builder split(SplitRecording split) {
236            this.split = split;
237            return this;
238        }
239
240        /**
241         * @param channels The number of channels to record (maximum 32). If the number of participants exceeds channels
242         *                 any additional participants will be added to the last channel in file. {@link #split} will be
243         *                 set to {@link SplitRecording#CONVERSATION} during the build process if channels is greater
244         *                 than 1.
245         *
246         * @return This builder.
247         */
248        public Builder channels(Integer channels) {
249            this.channels = channels;
250            return this;
251        }
252
253        /**
254         * Set this parameter to a non-null value to transcribe the recording.
255         *
256         * @param transcription The transcription settings.
257         *
258         * @return This builder.
259         * @since 8.2.0
260         */
261        public Builder transcription(TranscriptionSettings transcription) {
262            this.transcription = transcription;
263            return this;
264        }
265
266        /**
267         * Builds the RecordAction.
268         *
269         * @return A new RecordAction object from the stored builder options.
270         */
271        public RecordAction build() {
272            return new RecordAction(this);
273        }
274    }
275}