001/*
002 *   Copyright 2020 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.JsonIgnoreProperties;
019import com.fasterxml.jackson.annotation.JsonInclude;
020
021import java.util.Arrays;
022import java.util.Collection;
023
024/**
025 * An NCCO record action which allows for the call to be recorded.
026 */
027@JsonInclude(value = JsonInclude.Include.NON_NULL)
028@JsonIgnoreProperties(ignoreUnknown = true)
029public class RecordAction implements Action {
030    private static final String ACTION = "record";
031
032    private RecordingFormat format;
033    private Integer endOnSilence;
034    private Character endOnKey;
035    private Integer timeOut;
036    private Boolean beepStart;
037    private Collection<String> eventUrl;
038    private EventMethod eventMethod;
039    private SplitRecording split;
040    private Integer channels;
041
042    /**
043     * @deprecated Use {@link Builder}
044     */
045    @Deprecated
046    public RecordAction(Builder builder) {
047        this.format = builder.format;
048        this.endOnSilence = builder.endOnSilence;
049        this.endOnKey = builder.endOnKey;
050        this.timeOut = builder.timeOut;
051        this.beepStart = builder.beepStart;
052        this.eventUrl = builder.eventUrl;
053        this.eventMethod = builder.eventMethod;
054
055        // Split conversation must be enabled for multiple channels. Checked during construction to avoid
056        // method-chaining state confusion.
057        this.split = (builder.channels != null && builder.channels > 1) ? SplitRecording.CONVERSATION : builder.split;
058
059        this.channels = builder.channels;
060    }
061
062    @Override
063    public String getAction() {
064        return ACTION;
065    }
066
067    public RecordingFormat getFormat() {
068        return format;
069    }
070
071    public Integer getEndOnSilence() {
072        return endOnSilence;
073    }
074
075    public Character getEndOnKey() {
076        return endOnKey;
077    }
078
079    public Integer getTimeOut() {
080        return timeOut;
081    }
082
083    public Boolean getBeepStart() {
084        return beepStart;
085    }
086
087    public Collection<String> getEventUrl() {
088        return eventUrl;
089    }
090
091    public EventMethod getEventMethod() {
092        return eventMethod;
093    }
094
095    public SplitRecording getSplit() {
096        return split;
097    }
098
099    public Integer getChannels() {
100        return channels;
101    }
102
103    public static Builder builder() {
104        return new Builder();
105    }
106
107    public static class Builder {
108        private RecordingFormat format = null;
109        private Integer endOnSilence = null;
110        private Character endOnKey = null;
111        private Integer timeOut = null;
112        private Boolean beepStart = null;
113        private Collection<String> eventUrl = null;
114        private EventMethod eventMethod = null;
115        private SplitRecording split = null;
116        private Integer channels = null;
117
118        /**
119         * @param format Record the Call in a specific {@link RecordingFormat}.
120         *               <p>
121         *               The default value is {@link RecordingFormat#MP3}, or {@link RecordingFormat#WAV} when recording
122         *               more than 2 channels.
123         *
124         * @return The {@link Builder} to keep building.
125         */
126        public Builder format(RecordingFormat format) {
127            this.format = format;
128            return this;
129        }
130
131        /**
132         * @param endOnSilence Stop recording after n seconds of silence. Once the recording is stopped the recording
133         *                     data is sent to event_url. The range of possible values is between 3 and 10 inclusively.
134         *
135         * @return The {@link Builder} to keep building.
136         */
137        public Builder endOnSilence(Integer endOnSilence) {
138            this.endOnSilence = endOnSilence;
139            return this;
140        }
141
142        /**
143         * @param endOnKey Stop recording when a digit is pressed on the handset. Possible values are: *, # or any
144         *                 single digit e.g. 9
145         *
146         * @return The {@link Builder} to keep building.
147         */
148        public Builder endOnKey(Character endOnKey) {
149            this.endOnKey = endOnKey;
150            return this;
151        }
152
153        /**
154         * @param timeOut The maximum length of a recording in seconds. One the recording is stopped the recording data
155         *                is sent to event_url. The range of possible values is between 3 seconds and 7200 seconds (2
156         *                hours)
157         *
158         * @return The {@link Builder} to keep building.
159         */
160        public Builder timeOut(Integer timeOut) {
161            this.timeOut = timeOut;
162            return this;
163        }
164
165        /**
166         * @param beepStart Set to true to play a beep when a recording starts
167         *
168         * @return The {@link Builder} to keep building.
169         */
170        public Builder beepStart(Boolean beepStart) {
171            this.beepStart = beepStart;
172            return this;
173        }
174
175        /**
176         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
177         *                 If the message recording is hosted by Vonage, this webhook contains the URL you need to
178         *                 download the recording and other meta data.
179         *
180         * @return The {@link Builder} to keep building.
181         */
182        public Builder eventUrl(Collection<String> eventUrl) {
183            this.eventUrl = eventUrl;
184            return this;
185        }
186
187        /**
188         * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished.
189         *                 If the message recording is hosted by Vonage, this webhook contains the URL you need to
190         *                 download the recording and other meta data.
191         *
192         * @return The {@link Builder} to keep building.
193         */
194        public Builder eventUrl(String... eventUrl) {
195            return eventUrl(Arrays.asList(eventUrl));
196        }
197
198        /**
199         * @param eventMethod The HTTP method used to make the request to eventUrl. The default value is POST.
200         *
201         * @return The {@link Builder} to keep building.
202         */
203        public Builder eventMethod(EventMethod eventMethod) {
204            this.eventMethod = eventMethod;
205            return this;
206        }
207
208        /**
209         * @param split Record the sent and received audio in separate channels of a stereo recording—set to {@link
210         *              SplitRecording#CONVERSATION} to enable this.
211         *
212         * @return The {@link Builder} to keep building.
213         */
214        public Builder split(SplitRecording split) {
215            this.split = split;
216            return this;
217        }
218
219        /**
220         * @param channels The number of channels to record (maximum 32). If the number of participants exceeds channels
221         *                 any additional participants will be added to the last channel in file. {@link #split} will be
222         *                 set to {@link SplitRecording#CONVERSATION} during the build process if channels is greater
223         *                 than 1.
224         *
225         * @return The {@link Builder} to keep building.
226         */
227        public Builder channels(Integer channels) {
228            this.channels = channels;
229            return this;
230        }
231
232        /**
233         * @return A new {@link RecordAction} object from the stored builder options.
234         */
235        public RecordAction build() {
236            return new RecordAction(this);
237        }
238    }
239}