diff --git a/.classpath b/.classpath index 1321a81..b38515d 100644 --- a/.classpath +++ b/.classpath @@ -1,13 +1,45 @@ - - + - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index c055778..2573375 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,65 @@ -# Compiled class file -*.class +### Eclipse template +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders -# Log file -*.log +# External tool builders +.externalToolBuilders/ -# BlueJ files -*.ctxt +# Locally stored "Eclipse launch configurations" +*.launch -# Mobile Tools for Java (J2ME) -.mtj.tmp/ +# PyDev specific (Python IDE for Eclipse) +*.pydevproject -# Package Files # -#*.jar # in order to include external library -*.war -*.ear -*.zip -*.tar.gz -*.rar +# CDT-specific (C/C++ Development Tooling) +.cproject -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -/build/ +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +/target/ + +.idea/ diff --git a/.project b/.project index c48d052..3843021 100644 --- a/.project +++ b/.project @@ -11,13 +11,24 @@ - org.eclipse.wst.common.project.facet.core.builder + org.eclipse.m2e.core.maven2Builder - org.eclipse.wst.common.project.facet.core.nature org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + + 1683816513702 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index a698e59..93d8913 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,17 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=11 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs b/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs deleted file mode 100644 index 7c8126d..0000000 --- a/.settings/org.eclipse.jst.j2ee.ejb.annotations.xdoclet.prefs +++ /dev/null @@ -1,5 +0,0 @@ -XDOCLETBUILDERACTIVE=true -XDOCLETHOME= -XDOCLETUSEGLOBAL=true -XDOCLETVERSION=1.2.1 -eclipse.preferences.version=1 diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs deleted file mode 100644 index b196c64..0000000 --- a/.settings/org.eclipse.ltk.core.refactoring.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa..0000000 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/README.md b/README.md index 61b83d1..c40a7b7 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,28 @@ +# BigBlueButton API Library for Java -Special note: -1. This project used Lombok library, if you want to deploy this project, make sure you have Lombok installed. To install, follow the following steps: - - download from https://projectlombok.org/download - - go to the location where the Lombar.jar was downloaded, and run "java -jar lombok.jar", change the jar file name to the name of the lombok jar file that you downloaded - - after you run the previous step, a window should appear, brownse to your editor location (for eclipse, it's where eclipse.exe is located) - - click install - - launch Eclipse (or other IDE) - - add the zomlok library to your project (right click on the properties -> Java Build Path -> Libraries -> add Extenal JARs -> select the lombok jar file that you just downloaded -> Apply and Close +![Home Image](https://raw.githubusercontent.com/wiki/bigbluebutton/bigbluebutton-api-java/images/header.png) +## Description + +Official Java Library from BigBlueButton API. + +## Requirements + + - JVM 11+ + - BigBlueButton 2.6+ + +## Installation + +### Using maven + +## Maintainers + + - [Ghazi Triki](ghazi.triki@riadvice.tn) from [RIADVICE](https://riadvice.tn) + +## Build + +```bash +mvn formatter:format && mvn package +``` + +## Support diff --git a/lib/apache-commons-codec-1.4.jar b/lib/apache-commons-codec-1.4.jar deleted file mode 100644 index 422c42b..0000000 Binary files a/lib/apache-commons-codec-1.4.jar and /dev/null differ diff --git a/lib/lombok.jar b/lib/lombok.jar deleted file mode 100644 index 1728da7..0000000 Binary files a/lib/lombok.jar and /dev/null differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..32594f5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,265 @@ + + + + 4.0.0 + + org.bigbluebutton.api + bigbluebutton-api-java + 0.1-SNAPSHOT + + BigBlueButton Java API + https://bigbluebutton.org + + + + GhaziTriki + Ghazi Triki + ghazi.triki@riadvice.tn + RIADVICE + htttps://riadvice.tn + + architect + developer + + Africa/Tunis + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + + + 11 + 2.15.0 + 2.0.7 + + + + + commons-codec + commons-codec + 1.15 + + + org.projectlombok + lombok + 1.18.26 + true + + + org.apache.httpcomponents.client5 + httpclient5 + 5.2.1 + + + commons-io + commons-io + 2.11.0 + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + org.junit.jupiter + junit-jupiter-api + 5.9.3 + test + + + com.github.javafaker + javafaker + 1.0.2 + test + + + org.slf4j + slf4j-api + ${slf4j.version} + test + + + ch.qos.logback + logback-classic + 1.4.7 + test + + + + + src/main/java + src/test/java + + + maven-clean-plugin + 3.2.0 + + + maven-resources-plugin + 3.3.1 + + + maven-compiler-plugin + 3.11.0 + + ${java.version} + ${java.version} + + + + maven-surefire-plugin + 3.1.0 + + + --illegal-access=permit + + true + 2 + true + ${surefireArgLine} + + + + maven-jar-plugin + 3.3.0 + + + maven-install-plugin + 3.1.1 + + + maven-deploy-plugin + 3.1.1 + + + maven-site-plugin + 3.12.1 + + + maven-project-info-reports-plugin + 3.4.3 + + + org.apache.maven.plugins + maven-pmd-plugin + 3.20.0 + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + + java + + + + + + net.revelc.code.formatter + formatter-maven-plugin + 2.22.0 + + + + + + + + + ${java.version} + ${java.version} + ${java.version} + LF + UTF-8 + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.3.4 + + + com.github.spotbugs + spotbugs + 4.7.3.4 + + + + + org.jacoco + jacoco-maven-plugin + 0.8.10 + + + default-prepare-agent + + prepare-agent + + + + ${project.build.directory}/coverage-reports/jacoco.exec + surefireArgLine + + + + default-report + test + + report + + + + ${project.build.directory}/coverage-reports/jacoco.exec + + ${project.reporting.outputDirectory}/jacoco + + + + default-check + + check + + + + + BUNDLE + + + COMPLEXITY + COVEREDRATIO + 0.75 + + + + + + + + + + + diff --git a/src/BigBlueButton/api/BBBException.java b/src/BigBlueButton/api/BBBException.java deleted file mode 100644 index 58c613c..0000000 --- a/src/BigBlueButton/api/BBBException.java +++ /dev/null @@ -1,58 +0,0 @@ -package BigBlueButton.api; - -/** - * Exception generated while communicating with BBB server - * - * see https://github.com/sakaicontrib/bbb-tool/blob/master/api/src/java/org/sakaiproject/bbb/api/BBBException.java - */ -public class BBBException extends Exception { - private static final long serialVersionUID = 2421100107566638321L; - - public static final String MESSAGEKEY_HTTPERROR = "httpError"; - public static final String MESSAGEKEY_NOTFOUND = "notFound"; - public static final String MESSAGEKEY_NOACTION = "noActionSpecified"; - public static final String MESSAGEKEY_IDNOTUNIQUE = "idNotUnique"; - public static final String MESSAGEKEY_NOTSTARTED = "notStarted"; - public static final String MESSAGEKEY_ALREADYENDED = "alreadyEnded"; - public static final String MESSAGEKEY_INTERNALERROR = "internalError"; - public static final String MESSAGEKEY_UNREACHABLE = "unreachableServerError"; - public static final String MESSAGEKEY_INVALIDRESPONSE = "invalidResponseError"; - public static final String MESSAGEKEY_GENERALERROR = "generalError"; - - private String messageKey; - - public BBBException(String messageKey, String message, Throwable cause) { - super(message, cause); - this.messageKey = messageKey; - } - - public BBBException(String messageKey, String message) { - super(message); - this.messageKey = messageKey; - } - - public String getMessageKey() { - return messageKey; - } - - public void setMessageKey(String messageKey) { - this.messageKey = messageKey; - } - - public String getPrettyMessage() { - String _message = getMessage(); - String _messageKey = getMessageKey(); - - StringBuilder pretty = new StringBuilder(); - if(_message != null) { - pretty.append(_message); - } - if(_messageKey != null && !"".equals(_messageKey.trim())) { - pretty.append(" ("); - pretty.append(_messageKey); - pretty.append(")"); - } - return pretty.toString(); - } - -} \ No newline at end of file diff --git a/src/BigBlueButton/api/BBBMeeting.java b/src/BigBlueButton/api/BBBMeeting.java deleted file mode 100644 index 50e04f2..0000000 --- a/src/BigBlueButton/api/BBBMeeting.java +++ /dev/null @@ -1,58 +0,0 @@ -package BigBlueButton.api; - -import java.util.Map; -import java.util.Date; -import java.util.HashMap; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -/** - * Object for a BigBlueButton meeting. - * @author Adrian Fish - * Based on: https://github.com/sakaicontrib/bbb-tool/blob/master/api/src/java/org/sakaiproject/bbb/api/BBBMeeting.java - * - * Last modified by Yunkai Wang - */ -@Getter @Setter @ToString -public class BBBMeeting { - private String name = null; - private String meetingID; - private String attendeePW = null; - private String moderatorPW = null; - private String dialNumber = null; - private String voiceBridge = null; - private String webVoice = null; - private String logoutURL = null; - private Boolean record = null; - private Long duration = null; - - // user cannot directly modify this field - @Setter (AccessLevel.NONE) - private Map meta = new HashMap(); - private String moderatorOnlyMessage = null; - private Boolean autoStartRecording = null; - private Boolean allowStartStopRecording = null; - private Boolean webcamsOnlyForModerator = null; - private String logo = null; - private String copyright = null; - private Boolean muteOnStart = null; - private String welcome = null; - private Date startDate = null; - private Date endDate = null; - - public BBBMeeting(String meetingID) { - this.meetingID = meetingID; - } - - public void addMeta(String key, String value) { - meta.put(key, value); - } - - public void removeMeta(String key) { - if (meta.containsKey(key)) - meta.remove(key); - } -} diff --git a/src/BigBlueButton/impl/BBBAPI.java b/src/BigBlueButton/impl/BBBAPI.java deleted file mode 100644 index 690013d..0000000 --- a/src/BigBlueButton/impl/BBBAPI.java +++ /dev/null @@ -1,135 +0,0 @@ -package BigBlueButton.impl; - -import java.util.Map; -import BigBlueButton.api.BBBException; -import BigBlueButton.api.BBBMeeting; - -/** - * List of supported API for BigBlueButton, see BigBlueButton doc for more information - * Based on: https://github.com/sakaicontrib/bbb-tool/blob/master/impl/src/java/org/sakaiproject/bbb/impl/bbbapi/BBBAPI.java - * - * Last modified by Yunkai Wang - */ -public interface BBBAPI { - - /** - * Get the API version of the server - * - * @return API version - */ - public String getAPIVersion(); - - /** - * Get the base url of the server - * - * @return url - */ - public String getUrl(); - - /** - * Allow user to create meeting - * - * @return BBBMeeting object on success, on failure, BBBException is thrown - * @throws BBBException - */ - public BBBMeeting createMeeting(final String meetingID) throws BBBException; - public BBBMeeting createMeeting(final BBBMeeting meeting) throws BBBException; - public BBBMeeting createMeeting(final BBBMeeting meeting, final BBBModule module) throws BBBException; - - /** - * Check if the meeting is already running - * - * @return true if the meeting is running, false otherwise - * @throws BBBException - */ - public boolean isMeetingRunning(String meetingID) throws BBBException; - - /** - * Get meeting information corresponds to the given meetingID and role - * - * @return Map that contains all meeting information - * @throws BBBException - */ - public Map getMeetingInfo(String meetingID, String password) throws BBBException; - public Map getMeetingInfo(final BBBMeeting meeting) throws BBBException; - - /** - * End the given meeting - * - * @return true if the meeting is successfully ended or does not exist, false otherwise - * @throws BBBException - */ - public boolean endMeeting(String meetingID, String password) throws BBBException; - public boolean endMeeting(final BBBMeeting meeting) throws BBBException; - - /** - * Get the url to join the given meeting with the display name and corresponding role type - * - * @return url for joining the meeting - */ - public String getJoinMeetingURL(String meetingID, String password, String userDisplayName); - public String getJoinMeetingURL(String meetingID, String password, String userDisplayName, String userId); - - /** - * Get the list of all live meetings in server, every parameter like meetingIDs can be a list of meetings but separated - * by commas(e.g., "id1,id2") - * - * @return a map which has a field named meetings, and the value is the list of meeting information - * @throws BBBException - */ - public Map getMeetings() throws BBBException; - - /** - * Get the list of recordings that map the given fields - * - * @return a map which has a field named recordings, and the value is the list of recording information - * @throws BBBException - */ - public Map getRecordings() throws BBBException; - public Map getRecordings(String meetingIDs) throws BBBException; - public Map getRecordings(String meetingIDs, String recordIDs) throws BBBException; - public Map getRecordings(String meetingIDs, String recordIDs, String states) throws BBBException; - public Map getRecordings(String meetingIDs, String recordIDs, String states, Map meta) throws BBBException; - - /** - * Delete a given recording (or a list of recordings whose ids are separated by commas) - * - * @return true if the recording is successfully deleted, exception is thrown on failure - * @throws BBBException - */ - public boolean deteteRecordings(String recordIDs) throws BBBException; - - /** - * Publish/unpublish the recording(s) - * - * @return true if the recording(s) is successfully published/unpublished, exception is thrown on failure - * @throws BBBException - */ - public boolean publishRecordings(String recordIDs, boolean publish) throws BBBException; - - /** - * Update the recording(s) - * - * @return true if the recording(s) is successfully updated, exception is thrown on failure - * @throws BBBException - */ - public boolean updateRecordings(String recordIDs) throws BBBException; - public boolean updateRecordings(String recordIDs, Map meta) throws BBBException; - - /** - * Get the default config xml file from the BBB server and save it to the given file path - * - * @return true on success, on failure, BBBException is thrown - * @throws BBBException - */ - public boolean getDefaultConfigXML(String fileName) throws BBBException; - - - /** - * Set the config for the given meeting - * - * @return true on success, on failure, BBBException is thrown - * @throws BBBException - */ - public boolean setConfigXML(String meetingID, String fileName) throws BBBException; -} diff --git a/src/BigBlueButton/impl/BBBModule.java b/src/BigBlueButton/impl/BBBModule.java deleted file mode 100644 index f4dca63..0000000 --- a/src/BigBlueButton/impl/BBBModule.java +++ /dev/null @@ -1,88 +0,0 @@ -package BigBlueButton.impl; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import org.apache.commons.codec.binary.Base64; - -/** - * Java class that stores that modules configuration to be used for create BigBlueButton meeting. - * See the following url for more details - * https://github.com/mconf/bigbluebutton-api-ruby/blob/master/lib/bigbluebutton_modules.rb - * - * @author Yunkai Wang - */ -public class BBBModule { - public enum PresentationType { - url, file, base64; - } - - private LinkedList presentation_urls = new LinkedList(); - private LinkedList presentation_files = new LinkedList(); - private Map presentation_base64s = new HashMap(); - - public void add_presentation(PresentationType type, String value) { - add_presentation(type, value, ""); - } - - public void add_presentation(PresentationType type, String value, String name) { - switch (type) { - case url: - presentation_urls.add(value); - return; - case file: - presentation_files.add(value); - return; - case base64: - presentation_base64s.put(name, value); - return; - } - } - - public String to_xml() throws IOException { - if (!has_presentation()) return ""; - String xml = ""; - xml += presentations_to_xml(); - xml += ""; - return xml; - } - - private String presentations_to_xml() throws IOException { - String xml = ""; - for (String url : presentation_urls) - xml += String.format("", url); - for (Map.Entry entry : presentation_base64s.entrySet()) { - xml += String.format("", entry.getKey()); - xml += entry.getValue(); - xml += ""; - } - - for (String fileName : presentation_files) { - File f = new File(fileName); - xml += String.format("", f.getName()); - FileReader fr = new FileReader(fileName); - BufferedReader br = new BufferedReader(fr); - String file = ""; - String line = ""; - while ((line = br.readLine()) != null) - file += line + "\n"; - br.close(); - byte[] bytes = Base64.encodeBase64(file.getBytes()); - for (byte b : bytes) - xml += (char)b; - xml += ""; - } - xml += ""; - return xml; - } - - private boolean has_presentation() { - return !(presentation_urls.isEmpty() && - presentation_files.isEmpty() && - presentation_base64s.isEmpty()); - } -} diff --git a/src/BigBlueButton/impl/BaseBBBAPI.java b/src/BigBlueButton/impl/BaseBBBAPI.java deleted file mode 100644 index 3500a27..0000000 --- a/src/BigBlueButton/impl/BaseBBBAPI.java +++ /dev/null @@ -1,684 +0,0 @@ -package BigBlueButton.impl; - -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.HashMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import BigBlueButton.api.BBBException; -import BigBlueButton.api.BBBMeeting; - -import org.apache.commons.codec.digest.DigestUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * Base class for interacting with any BigBlueButton API version. - * @author Nuno Fernandes - * - * Last modified by Yunkai Wang - */ -public class BaseBBBAPI implements BBBAPI { - /** - * BBB server url, including bigbluebutton webapp path. Will default to - * http://localhost/bigbluebutton if not specified - */ - protected String bbbUrl = "http://127.0.0.1/bigbluebutton"; - /** BBB security salt */ - protected String bbbSalt = null; - - // API Server Path - protected final static String API_SERVERPATH = "/api/"; - - // API Calls - protected final static String APICALL_CREATE = "create"; - protected final static String APICALL_ISMEETINGRUNNING = "isMeetingRunning"; - protected final static String APICALL_GETMEETINGINFO = "getMeetingInfo"; - protected final static String APICALL_GETMEETINGS = "getMeetings"; - protected final static String APICALL_JOIN = "join"; - protected final static String APICALL_END = "end"; - protected final static String APICALL_VERSION = ""; - protected final static String APICALL_getRecordS = "getRecordings"; - protected final static String APICALL_PUBLISHRECORDINGS = "publishRecordings"; - protected final static String APICALL_UPDATERECORDINGS = "updateRecordings"; - protected final static String APICALL_DELETERECORDINGS = "deleteRecordings"; - protected final static String APICALL_GETCONFIGXML = "getDefaultConfigXML"; - protected final static String APICALL_SETCONFIGXML = "setConfigXML"; - - // API Response Codes - protected final static String APIRESPONSE_SUCCESS = "SUCCESS"; - protected final static String APIRESPONSE_FAILED = "FAILED"; - - // API Versions - public final static String APIVERSION_063 = "0.63"; - public final static String APIVERSION_064 = "0.64"; - public final static String APIVERSION_070 = "0.70"; - public final static String APIVERSION_080 = "0.80"; - public final static String APIVERSION_081 = "0.81"; - public final static String APIVERSION_MINIMUM = APIVERSION_063; - public final static String APIVERSION_LATEST = APIVERSION_081; - - // ----------------------------------------------------------------------- - // --- Initialization related methods ------------------------------------ - // ----------------------------------------------------------------------- - public BaseBBBAPI(String url, String salt) { - this.bbbUrl = url; - - if (bbbUrl.endsWith("/") && bbbUrl.length() > 0) { - bbbUrl = bbbUrl.substring(0, bbbUrl.length() - 1); - } - - this.bbbSalt = salt; - } - - public String getUrl() { - return this.bbbUrl; - } - - /* - public String getSalt() { - return this.bbbSalt; - } - */ - - private String encode(String msg) throws UnsupportedEncodingException { - return URLEncoder.encode(msg, getParametersEncoding()); - } - - // ----------------------------------------------------------------------- - // --- BBB API implementation methods ------------------------------------ - // ----------------------------------------------------------------------- - - /* Create BBB meeting */ - public BBBMeeting createMeeting(final String meetingID) throws BBBException { - return createMeeting(new BBBMeeting(meetingID), null); - } - - public BBBMeeting createMeeting(final BBBMeeting meeting) throws BBBException { - return createMeeting(meeting, null); - } - - public BBBMeeting createMeeting(final BBBMeeting meeting, final BBBModule module) throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append("meetingID=" + meeting.getMeetingID()); - if (meeting.getName() != null) - query.append("&name=" + encode(meeting.getName())); - if (meeting.getAttendeePW() != null) - query.append("&attendeePW=" + meeting.getAttendeePW()); - if (meeting.getModeratorPW() != null) - query.append("&moderatorPW=" + meeting.getModeratorPW()); - if (meeting.getWelcome() != null) - query.append("&welcome=" + encode(meeting.getWelcome())); - if (meeting.getDialNumber() != null) - query.append("&dialNumber=" + meeting.getDialNumber()); - if (meeting.getVoiceBridge() != null) - query.append("&voiceBridge=" + meeting.getVoiceBridge()); - if (meeting.getWebVoice() != null) - query.append("&webVoice=" + encode(meeting.getWebVoice())); - if (meeting.getLogoutURL() != null) - query.append("&logoutURL=" + encode(meeting.getLogoutURL())); - if (meeting.getRecord() != null) - query.append("&record=" + Boolean.toString(meeting.getRecord())); - if (meeting.getDuration() != null) - query.append("&duration=" + meeting.getDuration().toString()); - if (!meeting.getMeta().isEmpty()) { - for(Entry entry : meeting.getMeta().entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - query.append("&meta_" + key + "="); - query.append(encode(value)); - } - } - if (meeting.getModeratorOnlyMessage() != null) - query.append("&moderatorOnlyMessage=" + encode(meeting.getModeratorOnlyMessage())); - if (meeting.getAutoStartRecording() != null) - query.append("&autoStartRecording=" + Boolean.toString(meeting.getAutoStartRecording())); - if (meeting.getAllowStartStopRecording() != null) - query.append("&allowStartStopRecording=" + Boolean.toString(meeting.getAllowStartStopRecording())); - if (meeting.getWebcamsOnlyForModerator() != null) - query.append("&logo=" + Boolean.toString(meeting.getWebcamsOnlyForModerator())); - if (meeting.getLogo() != null) - query.append("&logo=" + encode(meeting.getLogo())); - if (meeting.getCopyright() != null) - query.append("©right=" + encode(meeting.getCopyright())); - if (meeting.getMuteOnStart() != null) - query.append("&muteOnStart=" + Boolean.toString(meeting.getMuteOnStart())); - query.append(getCheckSumParameterForQuery(APICALL_CREATE, query.toString())); - - Map response = doAPICall(APICALL_CREATE, query.toString(), - module == null ? null : module.to_xml()); - - // capture important information from returned response - meeting.setModeratorPW((String)response.get("moderatorPW")); - meeting.setAttendeePW((String)response.get("attendeePW")); - meeting.setDialNumber((String)response.get("dialNumber")); - meeting.setVoiceBridge((String)response.get("voiceBridge")); - SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy"); - try { - meeting.setStartDate(formatter.parse((String)response.get("createDate"))); - } catch (ParseException e) { } - - return meeting; - } catch (BBBException e) { - throw e; - } catch (IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* Check if meeting is running */ - public boolean isMeetingRunning(String meetingID) - throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append("meetingID=" + meetingID); - query.append(getCheckSumParameterForQuery(APICALL_ISMEETINGRUNNING, query.toString())); - - Map response = doAPICall(APICALL_ISMEETINGRUNNING, query.toString()); - return Boolean.parseBoolean((String) response.get("running")); - } catch (Exception e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* Get list of all running BBB meetings */ - public Map getMeetings() throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append(getCheckSumParameterForQuery(APICALL_GETMEETINGS, query.toString())); - Map response = doAPICall(APICALL_GETMEETINGS, query.toString()); - - return response; - } catch (Exception e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* Get BBB meeting information */ - public Map getMeetingInfo(final BBBMeeting meeting) throws BBBException { - return getMeetingInfo(meeting.getMeetingID(), meeting.getModeratorPW()); - } - - public Map getMeetingInfo(String meetingID, String password) - throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append("meetingID=" + meetingID); - query.append("&password=" + password); - query.append(getCheckSumParameterForQuery(APICALL_GETMEETINGINFO, query.toString())); - Map response = doAPICall(APICALL_GETMEETINGINFO, query.toString()); - return response; - } catch (BBBException e) { - throw new BBBException(e.getMessageKey(), e.getMessage(), e); - } - } - - /* End given BBB meeting */ - public boolean endMeeting(final BBBMeeting meeting) throws BBBException { - return endMeeting(meeting.getMeetingID(), meeting.getModeratorPW()); - } - - public boolean endMeeting(String meetingID, String password) throws BBBException { - StringBuilder query = new StringBuilder(); - query.append("meetingID=" + meetingID); - query.append("&password=" + password); - query.append(getCheckSumParameterForQuery(APICALL_END, query.toString())); - - try { - doAPICall(APICALL_END, query.toString()); - } catch (BBBException e) { - if(BBBException.MESSAGEKEY_NOTFOUND.equals(e.getMessageKey())) { - // we can safely ignore this one: the meeting is not running - return true; - }else{ - throw e; - } - } - - return true; - } - - /** Get recordings from BBB server */ - public Map getRecordings() throws BBBException { - return getRecordings(null, null, null, null); - } - - public Map getRecordings(String meetingIDs) throws BBBException { - return getRecordings(meetingIDs, null, null, null); - } - - public Map getRecordings(String meetingIDs, String recordIDs) throws BBBException { - return getRecordings(meetingIDs, recordIDs, null, null); - } - - public Map getRecordings(String meetingIDs, String recordIDs, String states) throws BBBException { - return getRecordings(meetingIDs, recordIDs, states, null); - } - - public Map getRecordings(String meetingIDs, String recordIDs, String states, Map meta) throws BBBException { - try { - StringBuilder query = new StringBuilder(); - if (meetingIDs != null) - query.append("meetingID=" + meetingIDs); - if (recordIDs != null) - query.append("recordID=" + recordIDs); - if (states != null) - query.append("state=" + states); - if (meta != null && meta.size() != 0) { - for(Entry entry : meta.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - query.append("&meta_" + key + "="); - query.append(encode(value)); - } - } - query.append(getCheckSumParameterForQuery(APICALL_getRecordS, query.toString())); - Map response = doAPICall(APICALL_getRecordS, query.toString()); - - return response; - } catch (BBBException e) { - throw new BBBException(e.getMessageKey(), e.getMessage(), e); - } catch (IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* Detete a record from BBB server */ - public boolean deteteRecordings(String recordIDs) throws BBBException { - StringBuilder query = new StringBuilder(); - query.append("recordID=" + recordIDs); - query.append(getCheckSumParameterForQuery(APICALL_DELETERECORDINGS, query.toString())); - try { - Map response = doAPICall(APICALL_DELETERECORDINGS, query.toString()); - return response.get("returncode").toString().equals("SUCCESS") ? true : false; - } catch (BBBException e) { - throw e; - } - } - - /* Publish/Unpublish a recording on BBB server */ - public boolean publishRecordings(String recordIDs, boolean publish) throws BBBException { - StringBuilder query = new StringBuilder(); - query.append("recordID=" + recordIDs); - query.append("&publish=" + Boolean.toString(publish)); - query.append(getCheckSumParameterForQuery(APICALL_PUBLISHRECORDINGS, query.toString())); - - try { - Map response = doAPICall(APICALL_PUBLISHRECORDINGS, query.toString()); - return response.get("returncode").toString().equals("SUCCESS") ? true : false; - } catch (BBBException e) { - throw e; - } - } - - /* Update a recording on BBB server */ - public boolean updateRecordings(String recordingIDs) throws BBBException { - return updateRecordings(recordingIDs, null); - } - - public boolean updateRecordings(String recordingIDs, Map meta) throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append("recordID=" + recordingIDs); - if (meta != null && meta.size() != 0) { - for(Entry entry : meta.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - query.append("&meta_" + key + "="); - query.append(encode(value)); - } - } - query.append(getCheckSumParameterForQuery(APICALL_UPDATERECORDINGS, query.toString())); - Map response = doAPICall(APICALL_UPDATERECORDINGS, query.toString()); - return response.get("returncode").toString().equals("SUCCESS") ? true : false; - } catch (BBBException e) { - throw e; - } catch (IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* Build the join meeting url based on user role */ - public String getJoinMeetingURL(String meetingID, String password, String userDisplayName) { - return getJoinMeetingURL(meetingID, password, userDisplayName, null); - } - - public String getJoinMeetingURL(String meetingID, String password, String userDisplayName, String userId) { - StringBuilder url = null; - try { - StringBuilder joinQuery = new StringBuilder(); - joinQuery.append("meetingID=" + meetingID); - if (userId != null) - joinQuery.append("&userID=" + encode(userId)); - - joinQuery.append("&fullName="); - userDisplayName = (userDisplayName == null) ? "user" : userDisplayName; - try { - joinQuery.append(encode(userDisplayName)); - } catch (UnsupportedEncodingException e) { - joinQuery.append(userDisplayName); - } - joinQuery.append("&password=" + password); - joinQuery.append(getCheckSumParameterForQuery(APICALL_JOIN, joinQuery.toString())); - - url = new StringBuilder(bbbUrl); - if (url.toString().endsWith("/api")) { - url.append("/"); - } else { - url.append(API_SERVERPATH); - } - url.append(APICALL_JOIN + "?" + joinQuery); - } catch (UnsupportedEncodingException e) { } - return url.toString(); - } - - /* Download default config xml file from the server and save the file to given file location */ - public boolean getDefaultConfigXML(String filePath) throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append(getCheckSumParameterForQuery(APICALL_GETCONFIGXML, query.toString())); - Map response = doAPICall(APICALL_GETCONFIGXML, query.toString()); - - File file = new File(filePath); - if (file.exists() && !file.canWrite()) { - throw new IOException("Failed to edit " + filePath); - } else if (!file.exists()) { - if (!file.createNewFile()) - throw new IOException("Failed to create " + filePath); - } - - FileOutputStream output = new FileOutputStream(file); - output.write(((String)response.get("xml")).getBytes()); - output.close(); - return true; - } catch (BBBException e) { - throw e; - } catch (IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /* set the config.xml file for the given meeting */ - public boolean setConfigXML(String meetingID, String filePath) throws BBBException { - try { - StringBuilder query = new StringBuilder(); - query.append("meetingID=" + meetingID); - query.append(getCheckSumParameterForQuery(APICALL_SETCONFIGXML, query.toString())); - - File file = new File(filePath); - if (!file.exists() || !file.canRead()) { - throw new IOException("Failed to read " + filePath); - } - - FileInputStream input = new FileInputStream(file); - byte[] b = input.readAllBytes(); - input.close(); - String xml = ""; - for (byte a : b) - xml += (char)a; - query.append("&configXML=" + encode(xml)); - - Map response = doAPICall(APICALL_SETCONFIGXML, query.toString()); - return response.get("returncode").toString().equals("SUCCESS") ? true : false; - } catch (BBBException e) { - throw e; - } catch (IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_INTERNALERROR, e.getMessage(), e); - } - } - - /** Get the BBB API version running on BBB server */ - public final String getAPIVersion() { - String _version = null; - try { - Map response = doAPICall(APICALL_VERSION, null); - _version = (String) response.get("version"); - _version = _version != null ? _version.trim() : null; - if (_version == null || Float.valueOf(_version.substring(0, 3)) < 0.0) { - _version = null; - } - _version = _version.trim(); - } catch (BBBException e) { - if (BBBException.MESSAGEKEY_NOACTION.equals(e.getMessageKey())) { - // we are clearly connecting to BBB < 0.70 => assuming minimum - // version (0.63) - _version = APIVERSION_MINIMUM; - } else { - // something went wrong => warn user - _version = null; - } - } catch (Exception e) { - // something went wrong => warn user - _version = null; - } - return _version; - } - - // ----------------------------------------------------------------------- - // --- BBB API utility methods ------------------------------------------- - // ----------------------------------------------------------------------- - /** Compute the query string checksum based on the security salt */ - protected String getCheckSumParameterForQuery(String apiCall, - String queryString) { - if (bbbSalt != null) - return "&checksum=" + DigestUtils.shaHex(apiCall + queryString + bbbSalt); - else - return ""; - } - - /** Encoding used when encoding url parameters */ - protected String getParametersEncoding() { - return "UTF-8"; - } - - - /* Make an API call */ - protected Map doAPICall(String apiCall, String query) throws BBBException { - return doAPICall(apiCall, query, null); - } - - protected Map doAPICall(String apiCall, String query, String data) throws BBBException { - StringBuilder urlStr = new StringBuilder(bbbUrl); - if (urlStr.toString().endsWith("/api")){ - urlStr.append("/"); - } else { - urlStr.append(API_SERVERPATH); - } - urlStr.append(apiCall); - if (query != null) { - urlStr.append("?"); - urlStr.append(query); - } - - try { - // open connection - URL url = new URL(urlStr.toString()); - HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection(); - httpConnection.setUseCaches(false); - httpConnection.setDoOutput(true); - if(data != null){ - httpConnection.setRequestMethod("POST"); - httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - httpConnection.setRequestProperty("Content-Length", "" + data.length()); - httpConnection.setRequestProperty("Content-Language", "en-US"); - httpConnection.setDoInput(true); - - DataOutputStream wr = new DataOutputStream( httpConnection.getOutputStream() ); - wr.writeBytes (data); - wr.flush(); - wr.close(); - } else { - httpConnection.setRequestMethod("GET"); - } - httpConnection.connect(); - - int responseCode = httpConnection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { - // read response - InputStreamReader isr = null; - BufferedReader reader = null; - StringBuilder xml = new StringBuilder(); - try { - isr = new InputStreamReader(httpConnection.getInputStream(), "UTF-8"); - reader = new BufferedReader(isr); - String line = reader.readLine(); - while (line != null) { - if( !line.startsWith("")) - xml.append(line.trim()); - line = reader.readLine(); - } - } finally { - if (reader != null) - reader.close(); - if (isr != null) - isr.close(); - } - httpConnection.disconnect(); - - // parse response - //Patch to fix the NaN error - String stringXml = xml.toString(); - stringXml = stringXml.replaceAll(">.\\s+?<", "><"); - - if (apiCall.equals(APICALL_GETCONFIGXML)) { - Map map = new HashMap(); - map.put("xml", stringXml); - return map; - } - - Document dom = null; - - // Initialize XML libraries - DocumentBuilderFactory docBuilderFactory; - DocumentBuilder docBuilder; - docBuilderFactory = DocumentBuilderFactory.newInstance(); - try { - docBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); - docBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); - - docBuilder = docBuilderFactory.newDocumentBuilder(); - dom = docBuilder.parse(new InputSource( new StringReader(stringXml))); - } catch (ParserConfigurationException e) { } - Map response = getNodesAsMap(dom, "response"); - - String returnCode = (String) response.get("returncode"); - if (APIRESPONSE_FAILED.equals(returnCode)) { - throw new BBBException((String) response.get("messageKey"), (String) response.get("message")); - } - - return response; - } else { - throw new BBBException(BBBException.MESSAGEKEY_HTTPERROR, "BBB server responded with HTTP status code " + responseCode); - } - - } catch(BBBException e) { - throw new BBBException( e.getMessageKey(), e.getMessage(), e); - } catch(IOException e) { - throw new BBBException(BBBException.MESSAGEKEY_UNREACHABLE, e.getMessage(), e); - } catch(SAXException e) { - throw new BBBException(BBBException.MESSAGEKEY_INVALIDRESPONSE, e.getMessage(), e); - } catch(IllegalArgumentException e) { - throw new BBBException(BBBException.MESSAGEKEY_INVALIDRESPONSE, e.getMessage(), e); - } catch(Exception e) { - throw new BBBException(BBBException.MESSAGEKEY_UNREACHABLE, e.getMessage(), e); - } - } - - - // ----------------------------------------------------------------------- - // --- BBB Other utility methods ----------------------------------------- - // ----------------------------------------------------------------------- - /** Get all nodes under the specified element tag name as a Java map */ - protected Map getNodesAsMap(Document dom, String elementTagName) { - Node firstNode = dom.getElementsByTagName(elementTagName).item(0); - return processNode(firstNode); - } - - protected Map processNode(Node _node) { - Map map = new HashMap(); - NodeList responseNodes = _node.getChildNodes(); - int images = 1; //counter for images (i.e image1, image2, image3) - for (int i = 0; i < responseNodes.getLength(); i++) { - Node node = responseNodes.item(i); - String nodeName = node.getNodeName().trim(); - if (node.getChildNodes().getLength() == 1 - && ( node.getChildNodes().item(0).getNodeType() == org.w3c.dom.Node.TEXT_NODE || node.getChildNodes().item(0).getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) ) { - String nodeValue = node.getTextContent(); - if (nodeName == "image" && node.getAttributes() != null){ - Map imageMap = new HashMap(); - Node heightAttr = node.getAttributes().getNamedItem("height"); - Node widthAttr = node.getAttributes().getNamedItem("width"); - Node altAttr = node.getAttributes().getNamedItem("alt"); - - imageMap.put("height", heightAttr.getNodeValue()); - imageMap.put("width", widthAttr.getNodeValue()); - imageMap.put("title", altAttr.getNodeValue()); - imageMap.put("url", nodeValue); - map.put(nodeName + images, imageMap); - images++; - } else { - map.put(nodeName, nodeValue != null ? nodeValue.trim() : null); - } - } else if (node.getChildNodes().getLength() == 0 - && node.getNodeType() != org.w3c.dom.Node.TEXT_NODE - && node.getNodeType() != org.w3c.dom.Node.CDATA_SECTION_NODE) { - map.put(nodeName, ""); - } else if (node.getChildNodes().getLength() >= 1) { - boolean isList = false; - for (int c = 0; c < node.getChildNodes().getLength(); ++c) { - try { - Node n = node.getChildNodes().item(c); - if (n.getChildNodes().item(0).getNodeType() != org.w3c.dom.Node.TEXT_NODE - && n.getChildNodes().item(0).getNodeType() != org.w3c.dom.Node.CDATA_SECTION_NODE) { - isList = true; - break; - } - } catch (Exception e) { - continue; - } - } - List list = new ArrayList(); - if (isList) { - for (int c = 0; c < node.getChildNodes().getLength(); ++c) { - Node n = node.getChildNodes().item(c); - list.add(processNode(n)); - } - if (nodeName == "preview"){ - Node n = node.getChildNodes().item(0); - map.put(nodeName, new ArrayList(processNode(n).values())); - } else { - map.put(nodeName, list); - } - } else { - map.put(nodeName, processNode(node)); - } - } else { - map.put(nodeName, processNode(node)); - } - } - return map; - } -} diff --git a/src/main/java/org/bigbluebutton/api/ApiMetaParams.java b/src/main/java/org/bigbluebutton/api/ApiMetaParams.java new file mode 100644 index 0000000..b347f77 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/ApiMetaParams.java @@ -0,0 +1,42 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import java.util.regex.Pattern; + +public class ApiMetaParams { + + // Meta prefix + public static String META_PREFIX = "meta_"; + + // Official meta regex pattern + public static final Pattern META_VAR_PATTERN = Pattern.compile("meta_[a-zA-Z][a-zA-Z0-9-]*$"); + + // Predefined metas + public static String END_CALLBACK_URL = "endCallbackUrl"; + public static String BBB_RECORDING_READY_URL = "bbb-recording-ready-url"; + public static String CANVAS_RECORDING_READY_URL = "canvas-recording-ready-url"; + public static String BBB_ANONYMIZE_CHAT = "bbb-anonymize-chat"; + public static String BBB_ANONYMIZE_MODERATORS = "bbb-anonymize-moderators"; + public static String HACK_RECORD_VIEWER_VIDEO = "hack-record-viewer-video"; + + private ApiMetaParams() { + throw new IllegalStateException("ApiMetaParams is a utility class. Instanciation is forbidden."); + } +} diff --git a/src/main/java/org/bigbluebutton/api/ApiMethod.java b/src/main/java/org/bigbluebutton/api/ApiMethod.java new file mode 100644 index 0000000..4cd9df8 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/ApiMethod.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import lombok.Getter; + +public enum ApiMethod { + ROOT(""), CREATE("create"), JOIN("join"), INSERT_DOCUMENT("insertDocument"), ENTER("enter"), END("end"), + IS_MEETING_RUNNING("isMeetingRunning"), GET_MEETING_INFO("getMeetingInfo"), GET_MEETINGS("getMeetings"), + SIGN_OUT("signOut"), GET_RECORDINGS("getRecordings"), PUBLISH_RECORDINGS("publishRecordings"), + DELETE_RECORDINGS("deleteRecordings"), UPDATE_RECORDINGS("updateRecordings"), + GET_RECORDING_TEXT_TRACKS("getRecordingTextTracks"), PUT_RECORDING_TEXT_TRACK("putRecordingTextTrack"), + HOOKS_CREATE("hooks/create"), HOOKS_LIST("hooks/list"), HOOKS_DESTROY("hooks/destroy"); + + @Getter + private String name; + + ApiMethod(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/ApiParams.java b/src/main/java/org/bigbluebutton/api/ApiParams.java new file mode 100644 index 0000000..7e03592 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/ApiParams.java @@ -0,0 +1,128 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +public class ApiParams { + + public static final String ALLOW_START_STOP_RECORDING = "allowStartStopRecording"; + public static final String AUTO_START_RECORDING = "autoStartRecording"; + public static final String BANNER_COLOR = "bannerColor"; + public static final String BANNER_TEXT = "bannerText"; + public static final String CHECKSUM = "checksum"; + public static final String COPYRIGHT = "copyright"; + public static final String CREATE_TIME = "createTime"; + public static final String DIAL_NUMBER = "dialNumber"; + public static final String DURATION = "duration"; + public static final String FREE_JOIN = "freeJoin"; + public static final String FULL_NAME = "fullName"; + public static final String GUEST_POLICY = "guestPolicy"; + public static final String MEETING_LAYOUT = "meetingLayout"; + public static final String DEFAULT_LAYOUT = "defaultLayout"; + public static final String IS_BREAKOUT = "isBreakout"; + public static final String LOGO = "logo"; + public static final String LOGOUT_TIMER = "logoutTimer"; + public static final String LOGOUT_URL = "logoutURL"; + public static final String MAX_PARTICIPANTS = "maxParticipants"; + public static final String MEETING_ID = "meetingID"; + public static final String META = "meta"; + public static final String MODERATOR_ONLY_MESSAGE = "moderatorOnlyMessage"; + public static final String MUTE_ON_START = "muteOnStart"; + public static final String MEETING_KEEP_EVENTS = "meetingKeepEvents"; + public static final String ALLOW_MODS_TO_UNMUTE_USERS = "allowModsToUnmuteUsers"; + public static final String ALLOW_REQUESTS_WITHOUT_SESSION = "allowRequestsWithoutSession"; + public static final String ALLOW_MODS_TO_EJECT_CAMERAS = "allowModsToEjectCameras"; + public static final String NAME = "name"; + public static final String PARENT_MEETING_ID = "parentMeetingID"; + public static final String RECORD = "record"; + public static final String RECORD_ID = "recordID"; + public static final String KIND = "kind"; + public static final String LANG = "lang"; + public static final String LABEL = "label"; + public static final String STATE = "state"; + public static final String PUBLISH = "publish"; + public static final String OFFSET = "offset"; + public static final String LIMIT = "limit"; + public static final String REDIRECT = "redirect"; + public static final String GUEST = "guest"; + public static final String EXCLUDE_FROM_DASHBOARD = "excludeFromDashboard"; + public static final String SEQUENCE = "sequence"; + public static final String VOICE_BRIDGE = "voiceBridge"; + public static final String WEB_VOICE = "webVoice"; + public static final String LEARNING_DASHBOARD_CLEANUP_DELAY_IN_MINUTES = "learningDashboardCleanupDelayInMinutes"; + public static final String WEBCAMS_ONLY_FOR_MODERATOR = "webcamsOnlyForModerator"; + public static final String MEETING_CAMERA_CAP = "meetingCameraCap"; + public static final String USER_CAMERA_CAP = "userCameraCap"; + public static final String MAX_PINNED_CAMERAS = "maxPinnedCameras"; + public static final String MEETING_EXPIRE_IF_NO_USER_JOINED_IN_MINUTES = "meetingExpireIfNoUserJoinedInMinutes"; + public static final String MEETING_EXPIRE_WHEN_LAST_USER_LEFT_IN_MINUTES = "meetingExpireWhenLastUserLeftInMinutes"; + public static final String WEB_VOICE_CONF = "webVoiceConf"; + public static final String USER_ID = "userID"; + public static final String WELCOME = "welcome"; + public static final String HTML5_INSTANCE_ID = "html5InstanceId"; + public static final String AVATAR_URL = "avatarURL"; + public static final String ROLE = "role"; + public static final String GROUPS = "groups"; + public static final String DISABLED_FEATURES = "disabledFeatures"; + public static final String NOTIFY_RECORDING_IS_ON = "notifyRecordingIsOn"; + + public static final String PRE_UPLOAD_PRESENTATION_OVERRIDE_DEFAULT = "preUploadedPresentationOverrideDefault"; + public static final String PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION = "presentationUploadExternalDescription"; + public static final String PRESENTATION_UPLOAD_EXTERNAL_URL = "presentationUploadExternalUrl"; + + public static final String BREAKOUT_ROOMS_CAPTURE_SLIDES = "breakoutRoomsCaptureSlides"; + public static final String BREAKOUT_ROOMS_CAPTURE_NOTES = "breakoutRoomsCaptureNotes"; + public static final String BREAKOUT_ROOMS_CAPTURE_SLIDES_FILENAME = "breakoutRoomsCaptureSlidesFilename"; + public static final String BREAKOUT_ROOMS_CAPTURE_NOTES_FILENAME = "breakoutRoomsCaptureNotesFilename"; + public static final String BREAKOUT_ROOMS_RECORD = "breakoutRoomsRecord"; + public static final String BREAKOUT_ROOMS_PRIVATE_CHAT_ENABLED = "breakoutRoomsPrivateChatEnabled"; + + public static final String LOCK_SETTINGS_DISABLE_CAM = "lockSettingsDisableCam"; + public static final String LOCK_SETTINGS_DISABLE_MIC = "lockSettingsDisableMic"; + public static final String LOCK_SETTINGS_DISABLE_PRIVATE_CHAT = "lockSettingsDisablePrivateChat"; + public static final String LOCK_SETTINGS_DISABLE_PUBLIC_CHAT = "lockSettingsDisablePublicChat"; + public static final String DEPRECATED_LOCK_SETTINGS_DISABLE_NOTES = "lockSettingsDisableNote"; + public static final String LOCK_SETTINGS_DISABLE_NOTES = "lockSettingsDisableNotes"; + public static final String LOCK_SETTINGS_HIDE_USER_LIST = "lockSettingsHideUserList"; + public static final String LOCK_SETTINGS_LOCK_ON_JOIN = "lockSettingsLockOnJoin"; + public static final String LOCK_SETTINGS_LOCK_ON_JOIN_CONFIGURABLE = "lockSettingsLockOnJoinConfigurable"; + public static final String LOCK_SETTINGS_HIDE_VIEWERS_CURSOR = "lockSettingsHideViewersCursor"; + + // New param passed on create call to callback when meeting ends. + // This is a duplicate of the endCallbackUrl meta param as we want this + // param to stay on the server and not propagated to client and recordings. + public static final String MEETING_ENDED_CALLBACK_URL = "meetingEndedURL"; + + // Param to end the meeting when there are no moderators after a certain period + // of time. + // Needed for classes where teacher gets disconnected and can't get back in. + // Prevents + // students from running amok. + public static final String END_WHEN_NO_MODERATOR = "endWhenNoModerator"; + public static final String END_WHEN_NO_MODERATOR_DELAY_IN_MINUTES = "endWhenNoModeratorDelayInMinutes"; + + // Webhooks parameters + public static final String CALLBACK_URL = "callbackURL"; + public static final String GET_RAW = "getRaw"; + public static final String HOOK_ID = "hookID"; + + private ApiParams() { + throw new IllegalStateException("ApiParams is a utility class. Instanciation is forbidden."); + } + +} diff --git a/src/main/java/org/bigbluebutton/api/ApiUserDataParams.java b/src/main/java/org/bigbluebutton/api/ApiUserDataParams.java new file mode 100644 index 0000000..6f1ccbd --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/ApiUserDataParams.java @@ -0,0 +1,62 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +// https://github.com/bigbluebutton/bigbluebutton/blob/develop/bigbluebutton-html5/imports/api/users-settings/server/methods/addUserSettings.js +// https://github.com/bigbluebutton/bigbluebutton/blob/develop/bigbluebutton-tests/puppeteer/customparameters/constants.js +public class ApiUserDataParams { + + // Meta prefix + public static String USERDATA_PREFIX = "userdata-"; + + // Predefined metas + public static String BBB_ASK_FOR_FEEDBACK_ON_LOGOUT = "bbb_ask_for_feedback_on_logout"; + public static String BBB_OVERRIDE_DEFAULT_LOCALE = "bbb_override_default_locale"; + public static String BBB_AUTO_JOIN_AUDIO = "bbb_auto_join_audio"; + public static String BBB_AUTO_SHARE_WEBCAM = "bbb_auto_share_webcam"; + public static String BBB_PREFERRED_CAMERA_PROFILE = "bbb_preferred_camera_profile"; + public static String BBB_CLIENT_TITLE = "bbb_client_title"; + public static String BBB_CUSTOM_STYLE = "bbb_custom_style"; + public static String BBB_CUSTOM_STYLE_URL = "bbb_custom_style_url"; + public static String BBB_SKIP_CHECK_AUDIO_ON_FIRST_JOIN = "bbb_skip_check_audio_on_first_join"; + public static String BBB_DISPLAY_BRANDING_AREA = "bbb_display_branding_area"; + public static String BBB_ENABLE_VIDEO = "bbb_enable_video"; + public static String BBB_RECORD_VIDEO = "bbb_record_video"; + public static String BBB_SKIP_VIDEO_PREVIEW = "bbb_skip_video_preview"; + public static String BBB_SKIP_VIDEO_PREVIEW_ON_FIRST_JOIN = "bbb_skip_video_preview_on_first_join"; + public static String BBB_MIRROR_OWN_WEBCAM = "bbb_mirror_own_webcam"; + public static String BBB_FORCE_RESTORE_PRESENTATION_ON_NEW_EVENTS = "bbb_force_restore_presentation_on_new_events"; + public static String BBB_FORCE_LISTEN_ONLY = "bbb_force_listen_only"; + public static String BBB_HIDE_PRESENTATION = "bbb_hide_presentation"; + public static String BBB_LISTEN_ONLY_MODE = "bbb_listen_only_mode"; + public static String BBB_MULTI_USER_PEN_ONLY = "bbb_multi_user_pen_only"; + public static String BBB_MULTI_USER_TOOLS = "bbb_multi_user_tools"; + public static String BBB_PRESENTER_TOOLS = "bbb_presenter_tools"; + public static String BBB_SHORTCUTS = "bbb_shortcuts"; + public static String BBB_SKIP_CHECK_AUDIO = "bbb_skip_check_audio"; + public static String BBB_HIDE_PRESENTATION_ON_JOIN = "bbb_hide_presentation_on_join"; + public static String BBB_SHOW_PARTICIPANTS_ON_LOGIN = "bbb_show_participants_on_login"; + public static String BBB_HIDE_ACTIONS_BAR = "bbb_hide_actions_bar"; + public static String BBB_HIDE_NAV_BAR = "bbb_hide_nav_bar"; + public static String BBB_CHANGE_LAYOUT = "bbb_change_layout"; + + private ApiUserDataParams() { + throw new IllegalStateException("ApiUserDataParams is a utility class. Instanciation is forbidden."); + } +} diff --git a/src/main/java/org/bigbluebutton/api/BigBlueButtonAPI.java b/src/main/java/org/bigbluebutton/api/BigBlueButtonAPI.java new file mode 100644 index 0000000..33b52ff --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/BigBlueButtonAPI.java @@ -0,0 +1,387 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.bigbluebutton.api.handlers.ApiResponseHandler; +import org.bigbluebutton.api.parameters.CreateMeetingParameters; +import org.bigbluebutton.api.parameters.DeleteRecordingsParameters; +import org.bigbluebutton.api.parameters.EndMeetingParameters; +import org.bigbluebutton.api.parameters.GetMeetingInfoParameters; +import org.bigbluebutton.api.parameters.GetRecordingTextTracksParameters; +import org.bigbluebutton.api.parameters.GetRecordingsParameters; +import org.bigbluebutton.api.parameters.HooksCreateParameters; +import org.bigbluebutton.api.parameters.HooksDestroyParameters; +import org.bigbluebutton.api.parameters.InsertDocumentParameters; +import org.bigbluebutton.api.parameters.IsMeetingRunningParameters; +import org.bigbluebutton.api.parameters.JoinMeetingParameters; +import org.bigbluebutton.api.parameters.PublishRecordingsParameters; +import org.bigbluebutton.api.parameters.PutRecordingTextTrackParameters; +import org.bigbluebutton.api.parameters.UpdateRecordingsParameters; +import org.bigbluebutton.api.responses.ApiVersionResponse; +import org.bigbluebutton.api.responses.CreateMeetingResponse; +import org.bigbluebutton.api.responses.DeleteRecordingsResponse; +import org.bigbluebutton.api.responses.EndMeetingResponse; +import org.bigbluebutton.api.responses.GetMeetingInfoResponse; +import org.bigbluebutton.api.responses.GetMeetingsResponse; +import org.bigbluebutton.api.responses.GetRecordingTextTracksResponse; +import org.bigbluebutton.api.responses.GetRecordingsResponse; +import org.bigbluebutton.api.responses.HooksCreateResponse; +import org.bigbluebutton.api.responses.HooksDestroyResponse; +import org.bigbluebutton.api.responses.HooksListResponse; +import org.bigbluebutton.api.responses.InsertDocumentResponse; +import org.bigbluebutton.api.responses.JoinMeetingResponse; +import org.bigbluebutton.api.responses.PublishRecordingsResponse; +import org.bigbluebutton.api.responses.PutRecordingTextTrackResponse; +import org.bigbluebutton.api.responses.UpdateRecordingsResponse; +import org.bigbluebutton.api.util.URLBuilder; +import org.xml.sax.SAXException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import lombok.Getter; +import lombok.Setter; + +public class BigBlueButtonAPI { + + @Getter + protected String securitySalt; + + @Getter + protected String baseServerURL; + + @Getter + @Setter + protected Integer timeout = 10; + + @Getter + @Setter + protected String hashingAlgorithm = HashingAlgorithms.SHA_256; + + protected URLBuilder urlBuilder; + + /** + * Jackson XML mapper to transform responses to objects + */ + private XmlMapper xmlMapper; + + public BigBlueButtonAPI() { + this(System.getenv("BBB_SERVER_BASE_URL"), System.getenv("BBB_SECURITY_SALT")); + } + + public BigBlueButtonAPI(String hashingAlgorithm) { + this(); + this.hashingAlgorithm = hashingAlgorithm; + } + + public BigBlueButtonAPI(String baseUrl, String securitySalt) { + this.baseServerURL = baseUrl; + this.securitySalt = securitySalt; + this.xmlMapper = new XmlMapper(); + xmlMapper.registerModule(new JavaTimeModule()); + xmlMapper.findAndRegisterModules(); + this.urlBuilder = new URLBuilder(this.baseServerURL, this.securitySalt, this.hashingAlgorithm); + } + + // API version + + public URI getApiVersionURL() throws URISyntaxException { + return urlBuilder.buildUrl(ApiMethod.ROOT); + } + + public ApiVersionResponse getAPIVersion() throws MalformedURLException, IOException, ParserConfigurationException, + SAXException, InterruptedException, URISyntaxException { + return xmlMapper.readValue(this.sendRequest(getApiVersionURL()), ApiVersionResponse.class); + } + + // Create meeting + + public URI getCreateMeetingURL(CreateMeetingParameters createMeetingParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.CREATE, createMeetingParams.getQueryParms()); + } + + public CreateMeetingResponse createMeeting(CreateMeetingParameters createMeetingParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + return sendApiRequest(getCreateMeetingURL(createMeetingParams), createMeetingParams.getPresentationsAsXML(), + CreateMeetingResponse.class); + } + + // Join meeting + + public URI getJoinMeetingURL(JoinMeetingParameters joinMeetingParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.JOIN, joinMeetingParams.getQueryParms()); + } + + public JoinMeetingResponse joinMeeting(JoinMeetingParameters joinMeetingParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getJoinMeetingURL(joinMeetingParams), JoinMeetingResponse.class); + } + + // End meeting + + public URI getEndMeetingURL(EndMeetingParameters endMeetingParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.END, endMeetingParams.getQueryParms()); + } + + public EndMeetingResponse endMeeting(EndMeetingParameters endMeetingParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getEndMeetingURL(endMeetingParams), EndMeetingResponse.class); + } + + // Insert document + + public URI getInsertDocumentUrl(InsertDocumentParameters insertDocumentParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.INSERT_DOCUMENT, insertDocumentParams.getQueryParms()); + } + + public InsertDocumentResponse insertDocument(InsertDocumentParameters insertDocumentParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getInsertDocumentUrl(insertDocumentParams), InsertDocumentResponse.class); + } + + // Is meeting running + + public URI getIsMeetingRunningUrl(IsMeetingRunningParameters isMeetingRunningParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.IS_MEETING_RUNNING, isMeetingRunningParams.getQueryParms()); + } + + public InsertDocumentResponse isMeetingRunning(IsMeetingRunningParameters isMeetingRunningParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getIsMeetingRunningUrl(isMeetingRunningParams), InsertDocumentResponse.class); + } + + // Get meetings + + public URI getMeetingsUrl() throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.GET_MEETINGS); + } + + public GetMeetingsResponse getMeetings() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getMeetingsUrl(), GetMeetingsResponse.class); + } + + // Get meeting info + + public URI getMeetingInfoUrl(GetMeetingInfoParameters getMeetingInfoParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.GET_MEETING_INFO, getMeetingInfoParams.getQueryParms()); + } + + public GetMeetingInfoResponse endMeeting(GetMeetingInfoParameters getMeetingInfoParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getMeetingInfoUrl(getMeetingInfoParams), GetMeetingInfoResponse.class); + } + + // Get recordings + + public URI getRecordingsUrl(GetRecordingsParameters getRecordingsParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.GET_RECORDINGS, getRecordingsParams.getQueryParms()); + } + + public GetRecordingsResponse getRecordings(GetRecordingsParameters getRecordingsParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getRecordingsUrl(getRecordingsParams), GetRecordingsResponse.class); + } + + // Publish recordings + + public URI getPublishRecordingsUrl(PublishRecordingsParameters publishRecordingsParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.PUBLISH_RECORDINGS, publishRecordingsParams.getQueryParms()); + } + + public PublishRecordingsResponse publishRecordings(PublishRecordingsParameters publishRecordingsParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getPublishRecordingsUrl(publishRecordingsParams), PublishRecordingsResponse.class); + } + + // Delete recordings + + public URI getDeleteRecordingsUrl(DeleteRecordingsParameters publishRecordingsParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.DELETE_RECORDINGS, publishRecordingsParams.getQueryParms()); + } + + public DeleteRecordingsResponse publishRecordings(DeleteRecordingsParameters publishRecordingsParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getDeleteRecordingsUrl(publishRecordingsParams), DeleteRecordingsResponse.class); + } + + // Update recordings + + public URI getUpdateRecordingsUrl(UpdateRecordingsParameters updateRecordingsParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.UPDATE_RECORDINGS, updateRecordingsParams.getQueryParms()); + } + + public UpdateRecordingsResponse updateRecordings(UpdateRecordingsParameters updateRecordingsParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getUpdateRecordingsUrl(updateRecordingsParams), UpdateRecordingsResponse.class); + } + + // Get recording text tracks + + public URI getRecordingTextTracksUrl(GetRecordingTextTracksParameters getRecordingTextTracksParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.GET_RECORDING_TEXT_TRACKS, getRecordingTextTracksParams.getQueryParms()); + } + + public GetRecordingTextTracksResponse getRecordingTextTracks( + GetRecordingTextTracksParameters getRecordingTextTracksParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getRecordingTextTracksUrl(getRecordingTextTracksParams), + GetRecordingTextTracksResponse.class); + } + + // Put recording text tracks + + public URI getPutRecordingTextTrackUrl(PutRecordingTextTrackParameters getRecordingTextTracksParams) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.PUT_RECORDING_TEXT_TRACK, getRecordingTextTracksParams.getQueryParms()); + } + + public PutRecordingTextTrackResponse putRecordingTextTrack( + PutRecordingTextTrackParameters getRecordingTextTracksParams) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getPutRecordingTextTrackUrl(getRecordingTextTracksParams), + PutRecordingTextTrackResponse.class); + } + + // Create hook + + public URI getHooksCreateUrl(HooksCreateParameters hooksCreateParames) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.HOOKS_CREATE, hooksCreateParames.getQueryParms()); + } + + public HooksCreateResponse hooksCreate(HooksCreateParameters hooksCreateParames) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getHooksCreateUrl(hooksCreateParames), HooksCreateResponse.class); + } + + // List hooks + + public URI getHooksListUrl() throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.HOOKS_LIST); + } + + public HooksListResponse hooksList() throws JsonMappingException, JsonProcessingException, MalformedURLException, + IOException, ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getHooksListUrl(), HooksListResponse.class); + } + + // Destroy hook + + public URI getHooksDestroyUrl(HooksDestroyParameters hooksDestroyParames) + throws URISyntaxException, UnsupportedEncodingException { + return urlBuilder.buildUrl(ApiMethod.HOOKS_CREATE, hooksDestroyParames.getQueryParms()); + } + + public HooksDestroyResponse hooksCreate(HooksDestroyParameters hooksDestroyParames) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return sendApiRequest(getHooksDestroyUrl(hooksDestroyParames), HooksDestroyResponse.class); + } + + // Common methods + + public T sendApiRequest(URI uri, Class responseType) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return xmlMapper.readValue(this.sendRequest(uri, null), responseType); + } + + public T sendApiRequest(URI uri, String payload, Class responseType) + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + return xmlMapper.readValue(this.sendRequest(uri, payload), responseType); + } + + protected String sendRequest(URI uri) throws MalformedURLException, IOException, ParserConfigurationException, + SAXException, InterruptedException { + return this.sendRequest(uri, null, "application/xml"); + } + + protected String sendRequest(URI uri, String payload) throws MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException { + return this.sendRequest(uri, payload, "application/xml"); + } + + protected String sendRequest(URI uri, String payload, String contentType) throws MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException { + // Open a connection to the API endpoint + HttpClient httpClient = HttpClientBuilder.create().build(); + HttpUriRequestBase httpRequest; + if (payload == null) { + httpRequest = new HttpGet(uri); + } else { + httpRequest = new HttpPost(uri); + // Set the payload as the request entity + StringEntity requestEntity = new StringEntity(payload); + httpRequest.setEntity(requestEntity); + httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, contentType); + } + + httpRequest.setHeader(HttpHeaders.CONTENT_ENCODING, StandardCharsets.UTF_8); + httpRequest.setHeader(HttpHeaders.TIMEOUT, this.timeout); + + ApiResponseHandler apiResponseHandler = new ApiResponseHandler(); + return httpClient.execute(httpRequest, apiResponseHandler); + } +} diff --git a/src/main/java/org/bigbluebutton/api/HashingAlgorithms.java b/src/main/java/org/bigbluebutton/api/HashingAlgorithms.java new file mode 100644 index 0000000..076a836 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/HashingAlgorithms.java @@ -0,0 +1,31 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +public class HashingAlgorithms { + + public static final String SHA_1 = "SHA-1"; + + public static final String SHA_256 = "SHA-256"; + + public static final String SHA_512 = "SHA-512"; + + public static final String SHA_384 = "SHA-384"; + +} diff --git a/src/main/java/org/bigbluebutton/api/data/Attendee.java b/src/main/java/org/bigbluebutton/api/data/Attendee.java new file mode 100644 index 0000000..36737f6 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Attendee.java @@ -0,0 +1,58 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.util.List; + +import org.bigbluebutton.api.deserializers.CustomDataDeserializer; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class Attendee { + @Getter + @JacksonXmlProperty(localName = "userID") + private String userId; + + @Getter + private String fullName; + + @Getter + private String role; + + @Getter + private Boolean isPresenter; + + @Getter + private Boolean isListeningOnly; + + @Getter + private Boolean hasJoinedVoice; + + @Getter + private Boolean hasVideo; + + @Getter + private String clientType; + + @JsonDeserialize(using = CustomDataDeserializer.class) + private List customData; +} diff --git a/src/main/java/org/bigbluebutton/api/data/CustomData.java b/src/main/java/org/bigbluebutton/api/data/CustomData.java new file mode 100644 index 0000000..e64dece --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/CustomData.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import lombok.Getter; +import lombok.Setter; + +public class CustomData { + @Getter + @Setter + private String name; + + @Getter + @Setter + private String value; + + public CustomData(String name, String value) { + this.name = name; + this.value = value; + } +} diff --git a/src/main/java/org/bigbluebutton/api/data/Hook.java b/src/main/java/org/bigbluebutton/api/data/Hook.java new file mode 100644 index 0000000..a76de8f --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Hook.java @@ -0,0 +1,44 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.net.URI; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class Hook { + @Getter + @JacksonXmlProperty(localName = "hookID") + private String hookId; + + @Getter + @JacksonXmlProperty(localName = "meetingID") + private String meetingId; + + @Getter + private URI callbackURL; + + @Getter + private Boolean permanentHook; + + @Getter + private Boolean rawData; +} diff --git a/src/main/java/org/bigbluebutton/api/data/Image.java b/src/main/java/org/bigbluebutton/api/data/Image.java new file mode 100644 index 0000000..a5e7617 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Image.java @@ -0,0 +1,41 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.net.URI; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; + +import lombok.Getter; + +public class Image { + + @Getter + private String alt; + + @Getter + @JacksonXmlText + private URI url; + + @Getter + private Integer height; + + @Getter + private Integer width; +} diff --git a/src/main/java/org/bigbluebutton/api/data/Meeting.java b/src/main/java/org/bigbluebutton/api/data/Meeting.java new file mode 100644 index 0000000..91b8388 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Meeting.java @@ -0,0 +1,239 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.time.Instant; +import java.time.ZonedDateTime; +import java.util.List; + +import org.bigbluebutton.api.deserializers.MetadataDeserializer; +import org.bigbluebutton.api.deserializers.ZonedDateTimeDeserializer; +import org.bigbluebutton.api.responses.BaseResponse; +import org.bigbluebutton.api.util.DateTimeUtil; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; +import lombok.Setter; + +@JsonIgnoreProperties(value = { "attendeePW", "moderatorPW" }) +public class Meeting extends BaseResponse { + @Getter + @Setter + private String meetingName; + + @JacksonXmlElementWrapper(localName = "attendees") + @JacksonXmlProperty(localName = "attendee") + @JsonProperty(required = false) + private List attendees; + + @Getter + @JacksonXmlProperty(localName = "meetingID") + private String meetingId; + + @Getter + @JacksonXmlProperty(localName = "internalMeetingID") + private String internalMeetingId; + + @Getter + private Instant createTime; + + @Getter + @JsonDeserialize(using = ZonedDateTimeDeserializer.class) + private ZonedDateTime createDate; + + @Getter + private String voiceBridge; + + @Getter + private String dialNumber; + + @Getter + private Boolean running; + + @Getter + private Integer duration; + + @Getter + private Boolean hasUserJoined; + + @Getter + private Boolean recording; + + @Getter + private Boolean hasBeenForciblyEnded; + + @Getter + private Instant startTime; + + @Getter + private Instant endTime; + + @Getter + private Integer participantCount; + + @Getter + private Integer listenerCount; + + @Getter + private Integer voiceParticipantCount; + + @Getter + private Integer videoCount; + + @Getter + private Integer maxUsers; + + @Getter + private Integer moderatorCount; + + @JsonDeserialize(using = MetadataDeserializer.class) + @JsonProperty(required = false) + private List metadata; + + @Getter + private Boolean isBreakout; + + @Getter + @JacksonXmlProperty(localName = "parentMeetingID") + private String parentMeetingId; + + @Getter + private Integer sequence; + + public static Meeting fromGetMeetingInfoResponse(JsonNode node) { + Meeting meeting = new Meeting(); + JsonNode meetingIdNode = node.get("meetingID"); + if (meetingIdNode != null) { + meeting.meetingId = meetingIdNode.asText(); + } + + JsonNode meetingNameNode = node.get("meetingName"); + if (meetingNameNode != null) { + meeting.meetingName = meetingNameNode.asText(); + } + + JsonNode createTimeNode = node.get("createTime"); + if (createTimeNode != null) { + meeting.createTime = Instant.ofEpochSecond(createTimeNode.asLong()); + } + + JsonNode createDateNode = node.get("createDate"); + if (createDateNode != null) { + meeting.createDate = DateTimeUtil.parseBigBlueButtonDate(createDateNode.asText()); + } + + JsonNode voiceBridgeNode = node.get("voiceBridge"); + if (voiceBridgeNode != null) { + meeting.voiceBridge = voiceBridgeNode.asText(); + } + + JsonNode dialNumberNode = node.get("dialNumber"); + if (dialNumberNode != null) { + meeting.dialNumber = dialNumberNode.asText(); + } + + JsonNode runningNode = node.get("running"); + if (runningNode != null) { + meeting.running = runningNode.asBoolean(); + } + + JsonNode durationNode = node.get("duration"); + if (durationNode != null) { + meeting.duration = durationNode.asInt(); + } + + JsonNode hasUserJoinedNode = node.get("hasUserJoined"); + if (hasUserJoinedNode != null) { + meeting.hasUserJoined = hasUserJoinedNode.asBoolean(); + } + + JsonNode recordingNode = node.get("recording"); + if (recordingNode != null) { + meeting.recording = recordingNode.asBoolean(); + } + + JsonNode hasBeenForciblyEndedNode = node.get("hasBeenForciblyEnded"); + if (hasBeenForciblyEndedNode != null) { + meeting.hasBeenForciblyEnded = hasBeenForciblyEndedNode.asBoolean(); + } + + JsonNode startTimeNode = node.get("startTime"); + if (startTimeNode != null) { + meeting.startTime = Instant.ofEpochSecond(startTimeNode.asLong()); + } + + JsonNode endTimeNode = node.get("endTime"); + if (endTimeNode != null) { + meeting.endTime = Instant.ofEpochSecond(endTimeNode.asLong()); + } + + JsonNode participantCountNode = node.get("participantCount"); + if (participantCountNode != null) { + meeting.participantCount = participantCountNode.asInt(); + } + + JsonNode listenerCountNode = node.get("listenerCount"); + if (listenerCountNode != null) { + meeting.listenerCount = listenerCountNode.asInt(); + } + + JsonNode voiceParticipantCountNode = node.get("voiceParticipantCount"); + if (voiceParticipantCountNode != null) { + meeting.voiceParticipantCount = voiceParticipantCountNode.asInt(); + } + + JsonNode videoCount = node.get("videoCount"); + if (videoCount != null) { + meeting.videoCount = videoCount.asInt(); + } + + JsonNode moderatorCountNode = node.get("moderatorCount"); + if (moderatorCountNode != null) { + meeting.moderatorCount = moderatorCountNode.asInt(); + } + + JsonNode isBreakoutNode = node.get("isBreakout"); + if (isBreakoutNode != null) { + meeting.isBreakout = isBreakoutNode.asBoolean(); + } + + JsonNode maxUsersNode = node.get("maxUsers"); + if (maxUsersNode != null) { + meeting.maxUsers = maxUsersNode.asInt(); + } + + JsonNode parentMeetingIDNode = node.get("parentMeetingID"); + if (parentMeetingIDNode != null) { + meeting.parentMeetingId = parentMeetingIDNode.asText(); + } + + JsonNode sequenceNode = node.get("sequence"); + if (sequenceNode != null) { + meeting.sequence = sequenceNode.asInt(); + } + + return meeting; + } +} diff --git a/src/main/java/org/bigbluebutton/api/data/Metadata.java b/src/main/java/org/bigbluebutton/api/data/Metadata.java new file mode 100644 index 0000000..8678157 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Metadata.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import lombok.Getter; +import lombok.Setter; + +public class Metadata { + @Getter + @Setter + private String name; + + @Getter + @Setter + private String value; + + public Metadata(String name, String value) { + this.name = name; + this.value = value; + } +} diff --git a/src/main/java/org/bigbluebutton/api/data/Playback.java b/src/main/java/org/bigbluebutton/api/data/Playback.java new file mode 100644 index 0000000..415dc18 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Playback.java @@ -0,0 +1,60 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.net.URI; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class Playback { + @Getter + private String type; + + @Getter + private URI url; + + @Getter + private Integer processingTime; + + @Getter + private Integer length; + + @Getter + private Integer size; + + @JsonProperty(required = false) + private Preview preview; + + public List getImages() { + return preview.getImages(); + } + + public static class Preview { + @Getter + @JacksonXmlElementWrapper(localName = "images") + @JacksonXmlProperty(localName = "image") + @JsonProperty(required = false) + private List images; + } +} diff --git a/src/main/java/org/bigbluebutton/api/data/Recording.java b/src/main/java/org/bigbluebutton/api/data/Recording.java new file mode 100644 index 0000000..5346586 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Recording.java @@ -0,0 +1,65 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import java.time.Instant; +import java.util.List; + +import org.bigbluebutton.api.deserializers.MetadataDeserializer; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class Recording { + + @Getter + @JacksonXmlProperty(localName = "recordID") + private String recordId; + + @Getter + @JacksonXmlProperty(localName = "meetingID") + private String meetingId; + + @Getter + private String name; + + @Getter + private Boolean published; + + @Getter + private String state; + + @Getter + private Instant startTime; + + @Getter + private Instant endTime; + + @JsonDeserialize(using = MetadataDeserializer.class) + @JsonProperty(required = false) + private List metadata; + + @JacksonXmlElementWrapper(localName = "playback") + @JacksonXmlProperty(localName = "format") + private List playbacks; +} diff --git a/src/main/java/org/bigbluebutton/api/data/Track.java b/src/main/java/org/bigbluebutton/api/data/Track.java new file mode 100644 index 0000000..06b1e35 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/data/Track.java @@ -0,0 +1,38 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.data; + +import lombok.Getter; + +public class Track { + @Getter + protected String href; + + @Getter + protected String kind; + + @Getter + protected String label; + + @Getter + protected String lang; + + @Getter + protected String source; +} diff --git a/src/main/java/org/bigbluebutton/api/deserializers/CustomDataDeserializer.java b/src/main/java/org/bigbluebutton/api/deserializers/CustomDataDeserializer.java new file mode 100644 index 0000000..7d2fab7 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/deserializers/CustomDataDeserializer.java @@ -0,0 +1,49 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.deserializers; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bigbluebutton.api.data.CustomData; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +public class CustomDataDeserializer extends JsonDeserializer> { + @Override + public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + List CustomDataEntries = new ArrayList<>(); + JsonNode CustomDataNode = jsonParser.getCodec().readTree(jsonParser); + + Iterator fieldNames = CustomDataNode.fieldNames(); + while (fieldNames.hasNext()) { + String fieldName = fieldNames.next(); + String fieldValue = CustomDataNode.get(fieldName).asText(); + CustomDataEntries.add(new CustomData(fieldName, fieldValue)); + } + + return CustomDataEntries; + } +} \ No newline at end of file diff --git a/src/main/java/org/bigbluebutton/api/deserializers/GetMeetingInfoResponseDeserializer.java b/src/main/java/org/bigbluebutton/api/deserializers/GetMeetingInfoResponseDeserializer.java new file mode 100644 index 0000000..0979a1f --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/deserializers/GetMeetingInfoResponseDeserializer.java @@ -0,0 +1,49 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.deserializers; + +import java.io.IOException; + +import org.bigbluebutton.api.responses.GetMeetingInfoResponse; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class GetMeetingInfoResponseDeserializer extends StdDeserializer { + + private static final long serialVersionUID = 5655122233138225747L; + + public GetMeetingInfoResponseDeserializer() { + this(null); + } + + public GetMeetingInfoResponseDeserializer(Class vc) { + super(vc); + } + + @Override + public GetMeetingInfoResponse deserialize(JsonParser parser, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + GetMeetingInfoResponse response = new GetMeetingInfoResponse(parser); + + return response; + } +} \ No newline at end of file diff --git a/src/main/java/org/bigbluebutton/api/deserializers/MetadataDeserializer.java b/src/main/java/org/bigbluebutton/api/deserializers/MetadataDeserializer.java new file mode 100644 index 0000000..d9725fd --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/deserializers/MetadataDeserializer.java @@ -0,0 +1,49 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.deserializers; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bigbluebutton.api.data.Metadata; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +public class MetadataDeserializer extends JsonDeserializer> { + @Override + public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + List metadataEntries = new ArrayList<>(); + JsonNode metadataNode = jsonParser.getCodec().readTree(jsonParser); + + Iterator fieldNames = metadataNode.fieldNames(); + while (fieldNames.hasNext()) { + String fieldName = fieldNames.next(); + String fieldValue = metadataNode.get(fieldName).asText(); + metadataEntries.add(new Metadata(fieldName, fieldValue)); + } + + return metadataEntries; + } +} \ No newline at end of file diff --git a/src/main/java/org/bigbluebutton/api/deserializers/PutRecordingTextTrackResponseDeserliazer.java b/src/main/java/org/bigbluebutton/api/deserializers/PutRecordingTextTrackResponseDeserliazer.java new file mode 100644 index 0000000..b219fbd --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/deserializers/PutRecordingTextTrackResponseDeserliazer.java @@ -0,0 +1,50 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.deserializers; + +import java.io.IOException; + +import org.bigbluebutton.api.responses.PutRecordingTextTrackResponse; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class PutRecordingTextTrackResponseDeserliazer extends StdDeserializer { + + private static final long serialVersionUID = 5655122233138225747L; + + public PutRecordingTextTrackResponseDeserliazer() { + this(null); + } + + public PutRecordingTextTrackResponseDeserliazer(Class vc) { + super(vc); + } + + @Override + public PutRecordingTextTrackResponse deserialize(JsonParser parser, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + PutRecordingTextTrackResponse response = PutRecordingTextTrackResponse + .fromPutRecordingTextTrackResponse(parser); + + return response; + } +} \ No newline at end of file diff --git a/src/main/java/org/bigbluebutton/api/deserializers/ZonedDateTimeDeserializer.java b/src/main/java/org/bigbluebutton/api/deserializers/ZonedDateTimeDeserializer.java new file mode 100644 index 0000000..c8133d8 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/deserializers/ZonedDateTimeDeserializer.java @@ -0,0 +1,38 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.deserializers; + +import java.io.IOException; +import java.time.ZonedDateTime; + +import org.bigbluebutton.api.util.DateTimeUtil; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +public class ZonedDateTimeDeserializer extends JsonDeserializer { + + @Override + public ZonedDateTime deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + return DateTimeUtil.parseBigBlueButtonDate(jp.getText()); + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/CaptionsKind.java b/src/main/java/org/bigbluebutton/api/enums/CaptionsKind.java new file mode 100644 index 0000000..5b839df --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/CaptionsKind.java @@ -0,0 +1,32 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum CaptionsKind { + SUBTITLES("subtitles"), CAPTIONS("captions"); + + @Getter + private String name; + + CaptionsKind(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/Feature.java b/src/main/java/org/bigbluebutton/api/enums/Feature.java new file mode 100644 index 0000000..851738f --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/Feature.java @@ -0,0 +1,39 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum Feature { + + BREAKOUT_ROOMS("breakoutRooms"), CAPTIONS("captions"), CHAT("chat"), + DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS("downloadPresentationWithAnnotations"), EXTERNAL_VIDEOS("externalVideos"), + IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS("importPresentationWithAnnotationsFromBreakoutRooms"), + IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS("importSharedNotesFromBreakoutRooms"), LAYOUTS("layouts"), + LEARNING_DASHBOARD("learningDashboard"), POLLS("polls"), SCREENSHARE("screenshare"), SHARED_NOTES("sharedNotes"), + VIRTUAL_BACKGROUNDS("virtualBackgrounds"), CUSTOM_VIRTUAL_BACKGROUNDS("customVirtualBackgrounds"), + LIVE_TRANSCRIPTION("liveTranscription"), PRESENTATION("presentation"); + + @Getter + private String name; + + Feature(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/GuestPolicy.java b/src/main/java/org/bigbluebutton/api/enums/GuestPolicy.java new file mode 100644 index 0000000..24e17d5 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/GuestPolicy.java @@ -0,0 +1,34 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum GuestPolicy { + + ALWAYS_ACCEPT("ALWAYS_ACCEPT"), ALWAYS_DENY("ALWAYS_DENY"), ASK_MODERATOR("ASK_MODERATOR"), + ALWAYS_ACCEPT_AUTH("ALWAYS_ACCEPT_AUTH"); + + @Getter + private String name; + + GuestPolicy(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/MeetingLayout.java b/src/main/java/org/bigbluebutton/api/enums/MeetingLayout.java new file mode 100644 index 0000000..e8e69d4 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/MeetingLayout.java @@ -0,0 +1,34 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum MeetingLayout { + + CUSTOM_LAYOUT("CUSTOM_LAYOUT"), SMART_LAYOUT("SMART_LAYOUT"), PRESENTATION_FOCUS("PRESENTATION_FOCUS"), + VIDEO_FOCUS("VIDEO_FOCUS"); + + @Getter + private String name; + + MeetingLayout(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/RecordingState.java b/src/main/java/org/bigbluebutton/api/enums/RecordingState.java new file mode 100644 index 0000000..710b871 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/RecordingState.java @@ -0,0 +1,34 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum RecordingState { + + ANY("any"), PROCESSING("processing"), PROCESSED("processed"), PUBLISHED("published"), UNPUBLISHED("unpublished"), + DELETED("deleted"); + + @Getter + private String name; + + RecordingState(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/enums/Role.java b/src/main/java/org/bigbluebutton/api/enums/Role.java new file mode 100644 index 0000000..3f55af0 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/enums/Role.java @@ -0,0 +1,33 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import lombok.Getter; + +public enum Role { + + MODERATOR("MODERATOR"), VIEWER("VIEWER"); + + @Getter + private String name; + + Role(String name) { + this.name = name; + } +} diff --git a/src/main/java/org/bigbluebutton/api/handlers/ApiResponseHandler.java b/src/main/java/org/bigbluebutton/api/handlers/ApiResponseHandler.java new file mode 100644 index 0000000..9c3acaa --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/handlers/ApiResponseHandler.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.handlers; + +import java.io.IOException; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.EntityUtils; + +public class ApiResponseHandler implements HttpClientResponseHandler { + + @Override + public String handleResponse(ClassicHttpResponse response) throws HttpException, IOException { + + // Get the status of the response + int status = response.getCode(); + if (status >= 200 && status < 300) { + HttpEntity entity = response.getEntity(); + if (entity == null) { + return ""; + } else { + return EntityUtils.toString(entity); + } + + } else { + return "" + status; + } + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/BaseParameters.java b/src/main/java/org/bigbluebutton/api/parameters/BaseParameters.java new file mode 100644 index 0000000..dac82ec --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/BaseParameters.java @@ -0,0 +1,61 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; + +public abstract class BaseParameters { + + protected void addStringValue(List params, String name, String value) + throws UnsupportedEncodingException { + if (value != null && !value.isEmpty()) { + params.add(new BasicNameValuePair(name, this.urlEncode(value))); + } + } + + protected void addIntegerValue(List params, String name, Integer value) + throws UnsupportedEncodingException { + if (value != null) { + params.add(new BasicNameValuePair(name, value.toString())); + } + } + + protected void addBooleanValue(List params, String name, Boolean value) { + if (value != null) { + params.add(new BasicNameValuePair(name, value.toString())); + } + } + + protected void addUriValue(List params, String name, URI value) { + if (value != null) { + params.add(new BasicNameValuePair(name, value.toString())); + } + } + + protected String urlEncode(String value) throws UnsupportedEncodingException { + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/CreateMeetingParameters.java b/src/main/java/org/bigbluebutton/api/parameters/CreateMeetingParameters.java new file mode 100644 index 0000000..154de6c --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/CreateMeetingParameters.java @@ -0,0 +1,330 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; +import org.bigbluebutton.api.enums.GuestPolicy; +import org.bigbluebutton.api.enums.MeetingLayout; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class CreateMeetingParameters extends MetaParameters implements Documentable { + + private DocumentableTrait documentableTrait = new DocumentableTrait(); + + @Getter + protected String name; + + @Getter + protected String meetingId; + + @Getter + @Setter + protected String welcome; + + @Getter + @Setter + protected String dialNumber; + + @Getter + @Setter + protected String voiceBridge; + + @Getter + @Setter + protected Integer maxParticipants; + + @Getter + protected URI logoutURL; + + @Getter + @Setter + protected Boolean record; + + @Getter + @Setter + protected Integer duration; + + @Getter + @Setter + protected Boolean isBreakout; + + @Getter + @Setter + protected Integer sequence; + + @Getter + @Setter + protected Boolean freeJoin; + + @Getter + @Setter + protected Boolean breakoutRoomsPrivateChatEnabled; + + @Getter + @Setter + protected Boolean breakoutRoomsRecord; + + @Getter + @Setter + protected String moderatorOnlyMessage; + + @Getter + @Setter + protected Boolean autoStartRecording; + + @Getter + @Setter + protected Boolean allowStartStopRecording; + + @Getter + @Setter + protected Boolean webcamsOnlyForModeratorBoolean; + + @Getter + @Setter + protected String bannerText; + + @Getter + @Setter + protected String bannerColor; + + @Getter + @Setter + protected Boolean muteOnStart; + + @Getter + @Setter + protected Boolean allowModsToUnmuteUsers; + + @Getter + @Setter + protected Boolean lockSettingsDisableCam; + + @Getter + @Setter + protected Boolean lockSettingsDisableMic; + + @Getter + @Setter + protected Boolean lockSettingsDisablePrivateChat; + + @Getter + @Setter + protected Boolean lockSettingsDisablePublicChat; + + @Getter + @Setter + protected Boolean lockSettingsDisableNote; + + @Getter + @Setter + protected Boolean lockSettingsLockOnJoin; + + @Getter + @Setter + protected Boolean lockSettingsLockOnJoinConfigurable; + + @Getter + @Setter + protected Boolean lockSettingsHideViewersCursor; + + @Getter + @Setter + protected GuestPolicy guestPolicy; + + @Getter + @Setter + protected Boolean meetingKeepEvents; + + @Getter + @Setter + protected Boolean endWhenNoModerator; + + @Getter + @Setter + protected Integer endWhenNoModeratorDelayInMinutes; + + @Getter + @Setter + protected MeetingLayout meetingLayout; + + @Getter + @Setter + protected Integer learningDashboardCleanupDelayInMinutes; + + @Getter + @Setter + protected Boolean allowModsToEjectCameras; + + @Getter + @Setter + protected Boolean allowRequestsWithoutSession; + + @Getter + @Setter + protected Integer userCameraCap; + + @Getter + @Setter + protected Integer meetingCameraCap; + + @Getter + @Setter + protected Integer meetingExpireIfNoUserJoinedInMinutes; + + @Getter + @Setter + protected Integer meetingExpireWhenLastUserLeftInMinutes; + + @Getter + @Setter + protected URI logo; + + @Getter + @Setter + protected Boolean preUploadedPresentationOverrideDefault; + + @Getter + @Setter + protected Boolean notifyRecordingIsOn; + + @Getter + @Setter + protected URI presentationUploadExternalUrl; + + @Getter + @Setter + protected String presentationUploadExternalDescription; + + public CreateMeetingParameters(String name, String meetingId) { + this.name = name; + this.meetingId = meetingId; + } + + public CreateMeetingParameters addMeta(String key, String value) { + metas.put(key, value); + return this; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.NAME, getName()); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + addStringValue(params, ApiParams.WELCOME, getWelcome()); + addStringValue(params, ApiParams.DIAL_NUMBER, getDialNumber()); + addStringValue(params, ApiParams.VOICE_BRIDGE, getVoiceBridge()); + addIntegerValue(params, ApiParams.MAX_PARTICIPANTS, getMaxParticipants()); + addUriValue(params, ApiParams.LOGOUT_URL, getLogoutURL()); + addBooleanValue(params, ApiParams.RECORD, getRecord()); + addIntegerValue(params, ApiParams.DURATION, getDuration()); + addBooleanValue(params, ApiParams.IS_BREAKOUT, getIsBreakout()); + addIntegerValue(params, ApiParams.SEQUENCE, getSequence()); + addBooleanValue(params, ApiParams.FREE_JOIN, getFreeJoin()); + addBooleanValue(params, ApiParams.BREAKOUT_ROOMS_PRIVATE_CHAT_ENABLED, getBreakoutRoomsPrivateChatEnabled()); + addBooleanValue(params, ApiParams.BREAKOUT_ROOMS_RECORD, getBreakoutRoomsRecord()); + addStringValue(params, ApiParams.MODERATOR_ONLY_MESSAGE, getModeratorOnlyMessage()); + addBooleanValue(params, ApiParams.AUTO_START_RECORDING, getAutoStartRecording()); + addBooleanValue(params, ApiParams.ALLOW_START_STOP_RECORDING, getAllowStartStopRecording()); + addBooleanValue(params, ApiParams.WEBCAMS_ONLY_FOR_MODERATOR, getWebcamsOnlyForModeratorBoolean()); + addStringValue(params, ApiParams.BANNER_TEXT, getBannerText()); + addStringValue(params, ApiParams.BANNER_COLOR, getBannerColor()); + addBooleanValue(params, ApiParams.MUTE_ON_START, getMuteOnStart()); + addBooleanValue(params, ApiParams.ALLOW_MODS_TO_UNMUTE_USERS, getAllowModsToUnmuteUsers()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_DISABLE_CAM, getLockSettingsDisableCam()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_DISABLE_MIC, getLockSettingsDisableMic()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_DISABLE_PRIVATE_CHAT, getLockSettingsDisablePrivateChat()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_DISABLE_PUBLIC_CHAT, getLockSettingsDisablePublicChat()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_DISABLE_NOTES, getLockSettingsDisableNote()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_LOCK_ON_JOIN, getLockSettingsLockOnJoin()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_LOCK_ON_JOIN_CONFIGURABLE, + getLockSettingsLockOnJoinConfigurable()); + addBooleanValue(params, ApiParams.LOCK_SETTINGS_HIDE_VIEWERS_CURSOR, getLockSettingsHideViewersCursor()); + if (getGuestPolicy() != null) { + addStringValue(params, ApiParams.GUEST_POLICY, getGuestPolicy().getName()); + } + addBooleanValue(params, ApiParams.MEETING_KEEP_EVENTS, getMeetingKeepEvents()); + addBooleanValue(params, ApiParams.END_WHEN_NO_MODERATOR, getEndWhenNoModerator()); + addIntegerValue(params, ApiParams.END_WHEN_NO_MODERATOR_DELAY_IN_MINUTES, + getEndWhenNoModeratorDelayInMinutes()); + if (getMeetingLayout() != null) { + addStringValue(params, ApiParams.MEETING_LAYOUT, getMeetingLayout().getName()); + } + addIntegerValue(params, ApiParams.LEARNING_DASHBOARD_CLEANUP_DELAY_IN_MINUTES, + getLearningDashboardCleanupDelayInMinutes()); + addBooleanValue(params, ApiParams.ALLOW_MODS_TO_EJECT_CAMERAS, getAllowModsToEjectCameras()); + addBooleanValue(params, ApiParams.ALLOW_REQUESTS_WITHOUT_SESSION, getAllowRequestsWithoutSession()); + addIntegerValue(params, ApiParams.USER_CAMERA_CAP, getUserCameraCap()); + addIntegerValue(params, ApiParams.MEETING_CAMERA_CAP, getMeetingCameraCap()); + addIntegerValue(params, ApiParams.MEETING_EXPIRE_IF_NO_USER_JOINED_IN_MINUTES, + getMeetingExpireIfNoUserJoinedInMinutes()); + addIntegerValue(params, ApiParams.MEETING_EXPIRE_WHEN_LAST_USER_LEFT_IN_MINUTES, + getMeetingExpireWhenLastUserLeftInMinutes()); + addStringValue(params, ApiParams.LOGO, getLogo().toString()); + addBooleanValue(params, ApiParams.PRE_UPLOAD_PRESENTATION_OVERRIDE_DEFAULT, + getPreUploadedPresentationOverrideDefault()); + addBooleanValue(params, ApiParams.NOTIFY_RECORDING_IS_ON, getNotifyRecordingIsOn()); + addUriValue(params, ApiParams.PRESENTATION_UPLOAD_EXTERNAL_URL, getPresentationUploadExternalUrl()); + addStringValue(params, ApiParams.PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION, + getPresentationUploadExternalDescription()); + // disabledFeatures + // groups + // pre-uploaded documents + + this.buildHTTPMeta(params); + return params; + } + + @Override + public Map getPresentations() { + return documentableTrait.getPresentations(); + } + + @Override + public CreateMeetingParameters addPresentation(String name, URI url) { + documentableTrait.addPresentation(name, url); + return this; + } + + @Override + public CreateMeetingParameters addPresentation(String name, File file) throws IOException { + documentableTrait.addPresentation(name, file); + return this; + } + + @Override + public String getPresentationsAsXML() throws ParserConfigurationException, TransformerException { + return documentableTrait.getPresentationsAsXML(); + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/DeleteRecordingsParameters.java b/src/main/java/org/bigbluebutton/api/parameters/DeleteRecordingsParameters.java new file mode 100644 index 0000000..f1f3e0f --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/DeleteRecordingsParameters.java @@ -0,0 +1,54 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class DeleteRecordingsParameters extends BaseParameters { + + @Getter + List recordIds = new ArrayList<>(); + + public DeleteRecordingsParameters(List recordIds) { + this.recordIds = recordIds; + } + + public DeleteRecordingsParameters(String recordId) { + this.recordIds.add(recordId); + } + + public void addRecordId(String recordId) { + recordIds.add(recordId); + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.RECORD_ID, String.join(",", recordIds)); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/Documentable.java b/src/main/java/org/bigbluebutton/api/parameters/Documentable.java new file mode 100644 index 0000000..e6264a7 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/Documentable.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +public interface Documentable { + Map getPresentations(); + + public T addPresentation(String name, URI url); + + public T addPresentation(String name, File file) throws IOException; + + public String getPresentationsAsXML() throws ParserConfigurationException, TransformerException; +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/DocumentableTrait.java b/src/main/java/org/bigbluebutton/api/parameters/DocumentableTrait.java new file mode 100644 index 0000000..3675d8f --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/DocumentableTrait.java @@ -0,0 +1,132 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.io.FileUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class DocumentableTrait implements Documentable { + + private Map presentations = new LinkedHashMap<>(); + + @Override + public Map getPresentations() { + return presentations; + } + + @Override + public DocumentableTrait addPresentation(String name, URI url) { + presentations.put(name, url.toString()); + return this; + } + + @Override + public DocumentableTrait addPresentation(String name, File file) throws IOException { + presentations.put(name, base64EncodeFile(file)); + return this; + } + + @Override + public String getPresentationsAsXML() throws ParserConfigurationException, TransformerException { + if (presentations.isEmpty()) { + return null; + } + + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.newDocument(); + + Element modulesElement = doc.createElement("modules"); + doc.appendChild(modulesElement); + + Element moduleElement = doc.createElement("module"); + moduleElement.setAttribute("name", "presentation"); + modulesElement.appendChild(moduleElement); + + for (Map.Entry entry : presentations.entrySet()) { + String nameOrUrl = entry.getKey(); + String content = entry.getValue(); + + Element documentElement = doc.createElement("document"); + + if (isURL(nameOrUrl)) { + documentElement.setAttribute("url", nameOrUrl); + if (isBase64(content)) { + documentElement.setAttribute("filename", content); + } + } else { + documentElement.setAttribute("name", nameOrUrl); + documentElement.setTextContent(content); + } + + moduleElement.appendChild(documentElement); + } + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + + transformer.transform(new DOMSource(doc), result); + + return writer.toString(); + } + + private boolean isURL(String str) { + try { + new URL(str); + return true; + } catch (MalformedURLException e) { + return false; + } + } + + private boolean isBase64(String str) { + byte[] decodedBytes = Base64.getDecoder().decode(str); + String decodedString = new String(decodedBytes, StandardCharsets.UTF_8); + // Check if the decoded string contains valid characters for Base64 data + return Base64.getEncoder().encodeToString(decodedString.getBytes(StandardCharsets.UTF_8)).equals(str); + } + + private String base64EncodeFile(File file) throws IOException { + byte[] fileContent = FileUtils.readFileToByteArray(file); + return Base64.getEncoder().encodeToString(fileContent); + } +} \ No newline at end of file diff --git a/src/main/java/org/bigbluebutton/api/parameters/EndMeetingParameters.java b/src/main/java/org/bigbluebutton/api/parameters/EndMeetingParameters.java new file mode 100644 index 0000000..b46f4d8 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/EndMeetingParameters.java @@ -0,0 +1,46 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class EndMeetingParameters extends BaseParameters { + + @Getter + protected String meetingId; + + public EndMeetingParameters(String meetingId) { + this.meetingId = meetingId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/GetMeetingInfoParameters.java b/src/main/java/org/bigbluebutton/api/parameters/GetMeetingInfoParameters.java new file mode 100644 index 0000000..1a22547 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/GetMeetingInfoParameters.java @@ -0,0 +1,46 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class GetMeetingInfoParameters extends BaseParameters { + + @Getter + protected String meetingId; + + public GetMeetingInfoParameters(String meetingId) { + this.meetingId = meetingId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/GetRecordingTextTracksParameters.java b/src/main/java/org/bigbluebutton/api/parameters/GetRecordingTextTracksParameters.java new file mode 100644 index 0000000..3bf7108 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/GetRecordingTextTracksParameters.java @@ -0,0 +1,47 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class GetRecordingTextTracksParameters extends MetaParameters { + + @Getter + protected String recordId; + + public GetRecordingTextTracksParameters(String recordId) { + this.recordId = recordId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.RECORD_ID, getRecordId()); + this.buildHTTPMeta(params); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/GetRecordingsParameters.java b/src/main/java/org/bigbluebutton/api/parameters/GetRecordingsParameters.java new file mode 100644 index 0000000..814b178 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/GetRecordingsParameters.java @@ -0,0 +1,77 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; +import org.bigbluebutton.api.enums.RecordingState; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class GetRecordingsParameters extends MetaParameters { + + @Getter + List meetingIds = new ArrayList<>(); + + @Getter + List recordIds = new ArrayList<>(); + + @Getter + protected String recordId; + + @Getter + protected List states; + + @Getter + protected Integer offset; + + @Getter + protected Integer limit; + + public void addMeetingId(String meetingId) { + meetingIds.add(meetingId); + } + + public void addRecordId(String recordId) { + recordIds.add(recordId); + } + + public void addState(RecordingState state) { + states.add(state); + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.MEETING_ID, String.join(",", meetingIds)); + addStringValue(params, ApiParams.RECORD_ID, String.join(",", recordIds)); + addStringValue(params, ApiParams.STATE, + String.join(",", states.stream().collect(Collectors.mapping(Enum::name, Collectors.joining(","))))); + addIntegerValue(params, ApiParams.OFFSET, getOffset()); + addIntegerValue(params, ApiParams.LIMIT, getLimit()); + this.buildHTTPMeta(params); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/HooksCreateParameters.java b/src/main/java/org/bigbluebutton/api/parameters/HooksCreateParameters.java new file mode 100644 index 0000000..d9e32f4 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/HooksCreateParameters.java @@ -0,0 +1,55 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class HooksCreateParameters extends BaseParameters { + + @Getter + protected URI callbackUrl; + + @Getter + protected String meetingId; + + @Getter + protected Boolean getRaw; + + public HooksCreateParameters(URI url) { + this.callbackUrl = url; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addUriValue(params, ApiParams.CALLBACK_URL, getCallbackUrl()); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + addBooleanValue(params, ApiParams.GET_RAW, getGetRaw()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/HooksDestroyParameters.java b/src/main/java/org/bigbluebutton/api/parameters/HooksDestroyParameters.java new file mode 100644 index 0000000..95db812 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/HooksDestroyParameters.java @@ -0,0 +1,46 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class HooksDestroyParameters extends BaseParameters { + + @Getter + protected String hookId; + + public HooksDestroyParameters(String hookId) { + this.hookId = hookId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.HOOK_ID, getHookId()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/InsertDocumentParameters.java b/src/main/java/org/bigbluebutton/api/parameters/InsertDocumentParameters.java new file mode 100644 index 0000000..9c7812b --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/InsertDocumentParameters.java @@ -0,0 +1,77 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class InsertDocumentParameters extends BaseParameters implements Documentable { + + private DocumentableTrait documentableTrait = new DocumentableTrait(); + + @Getter + protected String meetingId; + + public InsertDocumentParameters(String meetingId) { + this.meetingId = meetingId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + return params; + } + + @Override + public Map getPresentations() { + return documentableTrait.getPresentations(); + } + + @Override + public InsertDocumentParameters addPresentation(String name, URI url) { + documentableTrait.addPresentation(name, url); + return this; + } + + @Override + public InsertDocumentParameters addPresentation(String name, File file) throws IOException { + documentableTrait.addPresentation(name, file); + return this; + } + + @Override + public String getPresentationsAsXML() throws ParserConfigurationException, TransformerException { + return documentableTrait.getPresentationsAsXML(); + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/IsMeetingRunningParameters.java b/src/main/java/org/bigbluebutton/api/parameters/IsMeetingRunningParameters.java new file mode 100644 index 0000000..5d206b3 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/IsMeetingRunningParameters.java @@ -0,0 +1,46 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class IsMeetingRunningParameters extends BaseParameters { + + @Getter + protected String meetingId; + + public IsMeetingRunningParameters(String meetingId) { + this.meetingId = meetingId; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/JoinMeetingParameters.java b/src/main/java/org/bigbluebutton/api/parameters/JoinMeetingParameters.java new file mode 100644 index 0000000..3accca7 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/JoinMeetingParameters.java @@ -0,0 +1,102 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; +import org.bigbluebutton.api.enums.MeetingLayout; +import org.bigbluebutton.api.enums.Role; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class JoinMeetingParameters extends UserDataParameters { + + @Getter + protected String fullName; + + @Getter + protected String meetingId; + + @Getter + protected Role role; + + @Getter + @Setter + protected String createTime; + + @Getter + @Setter + protected String userId; + + @Getter + @Setter + protected String webVoiceConf; + + @Getter + @Setter + protected MeetingLayout defaultLayout; + + @Getter + @Setter + protected String avatarURL; + + @Getter + @Setter + protected Boolean redirect; + + @Getter + @Setter + protected Boolean guest; + + @Getter + @Setter + protected Boolean excludeFromDashboard; + + public JoinMeetingParameters(String fullName, String meetingId, Role role) { + this.fullName = fullName; + this.meetingId = meetingId; + this.role = role; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.FULL_NAME, getFullName()); + addStringValue(params, ApiParams.MEETING_ID, getMeetingId()); + addStringValue(params, ApiParams.ROLE, getRole().getName()); + addStringValue(params, ApiParams.CREATE_TIME, getCreateTime()); + addStringValue(params, ApiParams.WEB_VOICE_CONF, getWebVoiceConf()); + if (getDefaultLayout() != null) { + addStringValue(params, ApiParams.DEFAULT_LAYOUT, getDefaultLayout().getName()); + } + addStringValue(params, ApiParams.AVATAR_URL, getAvatarURL()); + addBooleanValue(params, ApiParams.REDIRECT, getRedirect()); + addBooleanValue(params, ApiParams.EXCLUDE_FROM_DASHBOARD, getExcludeFromDashboard()); + + this.buildHTTPUserData(params); + + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/MetaParameters.java b/src/main/java/org/bigbluebutton/api/parameters/MetaParameters.java new file mode 100644 index 0000000..8c45516 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/MetaParameters.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.util.HashMap; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.bigbluebutton.api.ApiMetaParams; + +public abstract class MetaParameters extends BaseParameters { + + protected HashMap metas; + + public MetaParameters() { + metas = new HashMap<>(); + } + + public String getMeta(String name) { + return metas.get(name); + } + + public BaseParameters addMeta(String key, String value) { + metas.put(key, value); + return this; + } + + protected void buildHTTPMeta(List params) { + metas.forEach((key, value) -> params.add(new BasicNameValuePair(ApiMetaParams.META_PREFIX + key, value))); + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/PublishRecordingsParameters.java b/src/main/java/org/bigbluebutton/api/parameters/PublishRecordingsParameters.java new file mode 100644 index 0000000..853ac15 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/PublishRecordingsParameters.java @@ -0,0 +1,60 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class PublishRecordingsParameters extends BaseParameters { + + @Getter + List recordIds = new ArrayList<>(); + + @Getter + protected Boolean publish; + + public void addRecordId(String recordId) { + recordIds.add(recordId); + } + + public PublishRecordingsParameters(List recordIds, Boolean publish) { + this.recordIds = recordIds; + this.publish = publish; + } + + public PublishRecordingsParameters(String recordId, Boolean publish) { + this.recordIds.add(recordId); + this.publish = publish; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.RECORD_ID, String.join(",", recordIds)); + addBooleanValue(params, ApiParams.PUBLISH, getPublish()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/PutRecordingTextTrackParameters.java b/src/main/java/org/bigbluebutton/api/parameters/PutRecordingTextTrackParameters.java new file mode 100644 index 0000000..0819a52 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/PutRecordingTextTrackParameters.java @@ -0,0 +1,62 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; +import org.bigbluebutton.api.enums.CaptionsKind; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class PutRecordingTextTrackParameters extends BaseParameters { + + @Getter + protected String recordId; + + @Getter + protected CaptionsKind kind; + + @Getter + protected String lang; + + @Getter + protected String label; + + public PutRecordingTextTrackParameters(String meetingId, CaptionsKind kind, String lang, String label) { + this.recordId = meetingId; + this.kind = kind; + this.lang = lang; + this.label = label; + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.RECORD_ID, getRecordId()); + addStringValue(params, ApiParams.KIND, getKind().getName()); + addStringValue(params, ApiParams.LANG, getLang()); + addStringValue(params, ApiParams.LABEL, getLabel()); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/UpdateRecordingsParameters.java b/src/main/java/org/bigbluebutton/api/parameters/UpdateRecordingsParameters.java new file mode 100644 index 0000000..d6e18e7 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/UpdateRecordingsParameters.java @@ -0,0 +1,55 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.bigbluebutton.api.ApiParams; + +import lombok.Getter; +import lombok.experimental.Accessors; + +@Accessors(chain = true) +public class UpdateRecordingsParameters extends MetaParameters { + + @Getter + List recordIds = new ArrayList<>(); + + public UpdateRecordingsParameters(List recordIds) { + this.recordIds = recordIds; + } + + public UpdateRecordingsParameters(String recordId) { + this.recordIds.add(recordId); + } + + public void addRecordId(String recordId) { + recordIds.add(recordId); + } + + public List getQueryParms() throws UnsupportedEncodingException { + List params = new ArrayList(); + addStringValue(params, ApiParams.RECORD_ID, String.join(",", recordIds)); + this.buildHTTPMeta(params); + return params; + } +} diff --git a/src/main/java/org/bigbluebutton/api/parameters/UserDataParameters.java b/src/main/java/org/bigbluebutton/api/parameters/UserDataParameters.java new file mode 100644 index 0000000..274a1b4 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/parameters/UserDataParameters.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.parameters; + +import java.util.HashMap; +import java.util.List; + +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.bigbluebutton.api.ApiUserDataParams; + +public abstract class UserDataParameters extends BaseParameters { + + protected HashMap userData; + + public UserDataParameters() { + userData = new HashMap<>(); + } + + public String getMeta(String name) { + return userData.get(name); + } + + public void addMeta(String key, String value) { + userData.put(key, value); + } + + protected void buildHTTPUserData(List params) { + userData.forEach( + (key, value) -> params.add(new BasicNameValuePair(ApiUserDataParams.USERDATA_PREFIX + key, value))); + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/APIReturnCode.java b/src/main/java/org/bigbluebutton/api/responses/APIReturnCode.java new file mode 100644 index 0000000..1e43013 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/APIReturnCode.java @@ -0,0 +1,32 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public enum APIReturnCode { + SUCCESS("SUCCESS"), FAILED("FAILED"); + + @Getter + private String returnCode; + + APIReturnCode(String returnCode) { + this.returnCode = returnCode; + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/ApiVersionResponse.java b/src/main/java/org/bigbluebutton/api/responses/ApiVersionResponse.java new file mode 100644 index 0000000..c6721ee --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/ApiVersionResponse.java @@ -0,0 +1,36 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; +import lombok.Setter; + +public class ApiVersionResponse extends BaseResponse { + @Getter + @Setter + private String version; + + @Getter + @Setter + private String apiVersion; + + @Getter + @Setter + private String bbbVersion; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/BaseResponse.java b/src/main/java/org/bigbluebutton/api/responses/BaseResponse.java new file mode 100644 index 0000000..c318e2d --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/BaseResponse.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +import lombok.Getter; + +@JacksonXmlRootElement(localName = "response") +@JsonRootName(value = "response") +public abstract class BaseResponse { + @Getter + @JacksonXmlProperty(localName = "returncode") + @JsonProperty(value = "returncode", required = false) + protected String returnCode; + + @Getter + @JsonProperty("message") + protected String message; + + @Getter + @JsonProperty("messageKey") + protected String messageKey; + + public Boolean success() { + return returnCode.equals(APIReturnCode.SUCCESS.getReturnCode()); + } + + public Boolean failed() { + return returnCode.equals(APIReturnCode.FAILED.getReturnCode()); + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/CreateMeetingResponse.java b/src/main/java/org/bigbluebutton/api/responses/CreateMeetingResponse.java new file mode 100644 index 0000000..337c82b --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/CreateMeetingResponse.java @@ -0,0 +1,71 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.time.Instant; +import java.time.ZonedDateTime; + +import org.bigbluebutton.api.deserializers.ZonedDateTimeDeserializer; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +@JsonIgnoreProperties(value = { "attendeePW", "moderatorPW" }) +public class CreateMeetingResponse extends BaseResponse { + @Getter + @JacksonXmlProperty(localName = "meetingID") + private String meetingId; + + @Getter + @JacksonXmlProperty(localName = "internalMeetingID") + private String internalMeetingId; + + @Getter + @JacksonXmlProperty(localName = "parentMeetingID") + private String parentMeetingId; + + @Getter + private Instant createTime; + + @Getter + private String voiceBridge; + + @Getter + private String dialNumber; + + @Getter + @JsonDeserialize(using = ZonedDateTimeDeserializer.class) + private ZonedDateTime createDate; + + @Getter + private Boolean hasUserJoined; + + @Getter + private Integer duration; + + @Getter + private Boolean hasBeenForciblyEnded; + + public Boolean hasParent() { + return getParentMeetingId().equals("bbb-none"); + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/DeleteRecordingsResponse.java b/src/main/java/org/bigbluebutton/api/responses/DeleteRecordingsResponse.java new file mode 100644 index 0000000..404fa17 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/DeleteRecordingsResponse.java @@ -0,0 +1,27 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public class DeleteRecordingsResponse extends BaseResponse { + + @Getter + protected Boolean deleted; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/EndMeetingResponse.java b/src/main/java/org/bigbluebutton/api/responses/EndMeetingResponse.java new file mode 100644 index 0000000..1e565d7 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/EndMeetingResponse.java @@ -0,0 +1,22 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +public class EndMeetingResponse extends BaseResponse { +} diff --git a/src/main/java/org/bigbluebutton/api/responses/GetMeetingInfoResponse.java b/src/main/java/org/bigbluebutton/api/responses/GetMeetingInfoResponse.java new file mode 100644 index 0000000..d9cff31 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/GetMeetingInfoResponse.java @@ -0,0 +1,52 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.io.IOException; + +import org.bigbluebutton.api.data.Meeting; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.JsonNode; + +import lombok.Getter; + +public class GetMeetingInfoResponse extends BaseResponse { + @Getter + private Meeting meeting; + + public GetMeetingInfoResponse(JsonParser parser) throws IOException { + ObjectCodec codec = parser.getCodec(); + JsonNode node = codec.readTree(parser); + + JsonNode returnCodeNode = node.get("returncode"); + if (returnCodeNode != null) { + this.returnCode = returnCodeNode.asText(); + } + + JsonNode messageNode = node.get("message"); + if (messageNode != null) { + this.message = messageNode.asText(); + } + + // Create the Meeting object and set it in the response + this.meeting = Meeting.fromGetMeetingInfoResponse(node); + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/GetMeetingsResponse.java b/src/main/java/org/bigbluebutton/api/responses/GetMeetingsResponse.java new file mode 100644 index 0000000..7956d9c --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/GetMeetingsResponse.java @@ -0,0 +1,35 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.util.List; + +import org.bigbluebutton.api.data.Meeting; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JacksonXmlRootElement(localName = "response") +public class GetMeetingsResponse extends BaseResponse { + + @JacksonXmlElementWrapper(localName = "meetings") + @JacksonXmlProperty(localName = "meeting") + private List meetings; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponse.java b/src/main/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponse.java new file mode 100644 index 0000000..f47c804 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponse.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.util.List; + +import org.bigbluebutton.api.data.Track; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class GetRecordingTextTracksResponse extends BaseResponse { + @Getter + protected InternalResponse response; + + public List getTracks() { + return response.getTracks(); + } + + public static class InternalResponse { + @Getter + @JacksonXmlProperty(localName = "returncode") + @JsonProperty("returncode") + protected String returnCode; + + @Getter + @JsonProperty("tracks") + private List tracks; + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/GetRecordingsResponse.java b/src/main/java/org/bigbluebutton/api/responses/GetRecordingsResponse.java new file mode 100644 index 0000000..2bfacab --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/GetRecordingsResponse.java @@ -0,0 +1,32 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.util.List; + +import org.bigbluebutton.api.data.Recording; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +public class GetRecordingsResponse extends BaseResponse { + @JacksonXmlElementWrapper(localName = "recordings") + @JacksonXmlProperty(localName = "recording") + private List recordings; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/HooksCreateResponse.java b/src/main/java/org/bigbluebutton/api/responses/HooksCreateResponse.java new file mode 100644 index 0000000..4acc38e --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/HooksCreateResponse.java @@ -0,0 +1,35 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class HooksCreateResponse extends BaseResponse { + @Getter + @JacksonXmlProperty(localName = "hookID") + private String hookId; + + @Getter + private Boolean permanentHook; + + @Getter + private Boolean rawData; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/HooksDestroyResponse.java b/src/main/java/org/bigbluebutton/api/responses/HooksDestroyResponse.java new file mode 100644 index 0000000..c322a8a --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/HooksDestroyResponse.java @@ -0,0 +1,27 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public class HooksDestroyResponse extends BaseResponse { + + @Getter + private Boolean removed; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/HooksListResponse.java b/src/main/java/org/bigbluebutton/api/responses/HooksListResponse.java new file mode 100644 index 0000000..5eedacb --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/HooksListResponse.java @@ -0,0 +1,35 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.util.List; + +import org.bigbluebutton.api.data.Hook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class HooksListResponse extends BaseResponse { + @Getter + @JacksonXmlElementWrapper(localName = "hooks") + @JacksonXmlProperty(localName = "hook") + private List hooks; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/InsertDocumentResponse.java b/src/main/java/org/bigbluebutton/api/responses/InsertDocumentResponse.java new file mode 100644 index 0000000..8f81d7a --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/InsertDocumentResponse.java @@ -0,0 +1,23 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +public class InsertDocumentResponse extends BaseResponse { + +} diff --git a/src/main/java/org/bigbluebutton/api/responses/IsMeetingRunningResponse.java b/src/main/java/org/bigbluebutton/api/responses/IsMeetingRunningResponse.java new file mode 100644 index 0000000..7876e27 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/IsMeetingRunningResponse.java @@ -0,0 +1,26 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public class IsMeetingRunningResponse extends BaseResponse { + @Getter + protected Boolean running; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/JoinMeetingResponse.java b/src/main/java/org/bigbluebutton/api/responses/JoinMeetingResponse.java new file mode 100644 index 0000000..7db5d7a --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/JoinMeetingResponse.java @@ -0,0 +1,56 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.net.URI; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import lombok.Getter; + +public class JoinMeetingResponse extends BaseResponse { + @Getter + @JacksonXmlProperty(localName = "meeting_id") + @JsonProperty(required = false) + private String meetingId; + + @Getter + @JacksonXmlProperty(localName = "user_id") + @JsonProperty(required = false) + private String userId; + + @Getter + @JsonProperty(required = false) + @JacksonXmlProperty(localName = "auth_token") + private String authToken; + + @Getter + @JacksonXmlProperty(localName = "session_token") + @JsonProperty(required = false) + private String sessionToken; + + @Getter + @JsonProperty(required = false) + private String guestStatus; + + @Getter + @JsonProperty(required = false) + private URI url; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/PublishRecordingsResponse.java b/src/main/java/org/bigbluebutton/api/responses/PublishRecordingsResponse.java new file mode 100644 index 0000000..bb57978 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/PublishRecordingsResponse.java @@ -0,0 +1,26 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public class PublishRecordingsResponse extends BaseResponse { + @Getter + private Boolean published; +} diff --git a/src/main/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponse.java b/src/main/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponse.java new file mode 100644 index 0000000..c529524 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponse.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import java.io.IOException; + +import org.bigbluebutton.api.deserializers.PutRecordingTextTrackResponseDeserliazer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import lombok.Getter; + +@JsonDeserialize(using = PutRecordingTextTrackResponseDeserliazer.class) +public class PutRecordingTextTrackResponse extends BaseResponse { + @Getter + protected String recordId; + + public static PutRecordingTextTrackResponse fromPutRecordingTextTrackResponse(JsonParser parser) + throws IOException { + PutRecordingTextTrackResponse response = new PutRecordingTextTrackResponse(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode responseNode = rootNode.get("response"); + + if (responseNode != null) { + response.messageKey = responseNode.get("messageKey").asText(); + response.message = responseNode.get("message").asText(); + response.recordId = responseNode.get("recordId").asText(); + response.returnCode = responseNode.get("returncode").asText(); + } + + return response; + } +} diff --git a/src/main/java/org/bigbluebutton/api/responses/UpdateRecordingsResponse.java b/src/main/java/org/bigbluebutton/api/responses/UpdateRecordingsResponse.java new file mode 100644 index 0000000..8d6b374 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/responses/UpdateRecordingsResponse.java @@ -0,0 +1,27 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import lombok.Getter; + +public class UpdateRecordingsResponse extends BaseResponse { + + @Getter + private Boolean updated; +} diff --git a/src/main/java/org/bigbluebutton/api/util/DateTimeUtil.java b/src/main/java/org/bigbluebutton/api/util/DateTimeUtil.java new file mode 100644 index 0000000..64added --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/util/DateTimeUtil.java @@ -0,0 +1,38 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.util; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public final class DateTimeUtil { + public static final DateTimeFormatter TZ_DATE_FORMATTER = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss z yyyy"); + + private DateTimeUtil() { + throw new IllegalStateException("DateTimeUtil is a utility class. Instanciation is forbidden."); + } + + public static ZonedDateTime parseBigBlueButtonDate(String dateString) { + LocalDateTime localDateTime = LocalDateTime.parse(dateString, TZ_DATE_FORMATTER); + String[] parts = dateString.split(" "); + return ZonedDateTime.of(localDateTime, ZoneId.of(parts[parts.length - 2])); + } +} diff --git a/src/main/java/org/bigbluebutton/api/util/URLBuilder.java b/src/main/java/org/bigbluebutton/api/util/URLBuilder.java new file mode 100644 index 0000000..bdc1911 --- /dev/null +++ b/src/main/java/org/bigbluebutton/api/util/URLBuilder.java @@ -0,0 +1,86 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.util; + +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.net.URIBuilder; +import org.apache.hc.core5.net.URLEncodedUtils; +import org.bigbluebutton.api.ApiMethod; +import org.bigbluebutton.api.HashingAlgorithms; + +import lombok.Getter; + +public class URLBuilder { + + @Getter + private URI baseUri; + + private final String apiPrefix = "api"; + + @Getter + private String sharedSecret; + + @Getter + private String hashingAlgorithm; + + public URLBuilder(String uri, String sharedSecret, String hashingAlgorithm) { + this(URI.create(uri), sharedSecret, hashingAlgorithm); + } + + public URLBuilder(URI uri, String sharedSecret, String hashingAlgorithm) { + this.baseUri = uri; + this.sharedSecret = sharedSecret; + this.hashingAlgorithm = hashingAlgorithm; + } + + public URI buildUrl(ApiMethod apiMethod) throws URISyntaxException { + return this.buildUrl(apiMethod, null); + } + + public URI buildUrl(ApiMethod apiMethod, List params) throws URISyntaxException { + URIBuilder builder = new URIBuilder(baseUri + apiPrefix + "/" + apiMethod.getName()).addParameters(params); + String checksum = this.calculateChecksum(apiMethod, builder.getQueryParams()); + return builder.addParameter("checksum", checksum).build(); + } + + private String calculateChecksum(ApiMethod apiMethod, List queryParams) { + switch (hashingAlgorithm) { + case HashingAlgorithms.SHA_1: + return DigestUtils.sha1Hex(apiMethod.getName() + + URLEncodedUtils.format(queryParams, StandardCharsets.UTF_8) + this.sharedSecret); + case HashingAlgorithms.SHA_256: + return DigestUtils.sha256Hex(apiMethod.getName() + + URLEncodedUtils.format(queryParams, StandardCharsets.UTF_8) + this.sharedSecret); + case HashingAlgorithms.SHA_512: + return DigestUtils.sha512Hex(apiMethod.getName() + + URLEncodedUtils.format(queryParams, StandardCharsets.UTF_8) + this.sharedSecret); + case HashingAlgorithms.SHA_384: + return DigestUtils.sha384Hex(apiMethod.getName() + + URLEncodedUtils.format(queryParams, StandardCharsets.UTF_8) + this.sharedSecret); + default: + throw new IllegalArgumentException("Unsupported hashing algorithm: " + hashingAlgorithm); + } + } +} diff --git a/src/test/java/org/bigbluebutton/api/ApiMetaParamsTest.java b/src/test/java/org/bigbluebutton/api/ApiMetaParamsTest.java new file mode 100644 index 0000000..ee32b74 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/ApiMetaParamsTest.java @@ -0,0 +1,41 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ApiMetaParamsTest extends BaseTestCase { + + @Test + @DisplayName("Test API meta parameters names") + void apiMethodNamesShouldMatch() { + + assertEquals(ApiMetaParams.META_PREFIX, "meta_"); + assertEquals(ApiMetaParams.END_CALLBACK_URL, "endCallbackUrl"); + assertEquals(ApiMetaParams.BBB_RECORDING_READY_URL, "bbb-recording-ready-url"); + assertEquals(ApiMetaParams.CANVAS_RECORDING_READY_URL, "canvas-recording-ready-url"); + assertEquals(ApiMetaParams.BBB_ANONYMIZE_CHAT, "bbb-anonymize-chat"); + assertEquals(ApiMetaParams.BBB_ANONYMIZE_MODERATORS, "bbb-anonymize-moderators"); + assertEquals(ApiMetaParams.HACK_RECORD_VIEWER_VIDEO, "hack-record-viewer-video"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/ApiMethodTest.java b/src/test/java/org/bigbluebutton/api/ApiMethodTest.java new file mode 100644 index 0000000..cdf0124 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/ApiMethodTest.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ApiMethodTest extends BaseTestCase { + + @Test + @DisplayName("Test API method names") + void apiMethodNamesShouldMatch() { + assertEquals(ApiMethod.CREATE.getName(), "create"); + assertEquals(ApiMethod.JOIN.getName(), "join"); + assertEquals(ApiMethod.INSERT_DOCUMENT.getName(), "insertDocument"); + assertEquals(ApiMethod.ENTER.getName(), "enter"); + assertEquals(ApiMethod.END.getName(), "end"); + assertEquals(ApiMethod.IS_MEETING_RUNNING.getName(), "isMeetingRunning"); + assertEquals(ApiMethod.GET_MEETING_INFO.getName(), "getMeetingInfo"); + assertEquals(ApiMethod.GET_MEETINGS.getName(), "getMeetings"); + assertEquals(ApiMethod.SIGN_OUT.getName(), "signOut"); + assertEquals(ApiMethod.GET_RECORDINGS.getName(), "getRecordings"); + assertEquals(ApiMethod.PUBLISH_RECORDINGS.getName(), "publishRecordings"); + assertEquals(ApiMethod.DELETE_RECORDINGS.getName(), "deleteRecordings"); + assertEquals(ApiMethod.UPDATE_RECORDINGS.getName(), "updateRecordings"); + assertEquals(ApiMethod.GET_RECORDING_TEXT_TRACKS.getName(), "getRecordingTextTracks"); + assertEquals(ApiMethod.PUT_RECORDING_TEXT_TRACK.getName(), "putRecordingTextTrack"); + assertEquals(ApiMethod.HOOKS_CREATE.getName(), "hooks/create"); + assertEquals(ApiMethod.HOOKS_LIST.getName(), "hooks/list"); + assertEquals(ApiMethod.HOOKS_DESTROY.getName(), "hooks/destroy"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/ApiParamsTest.java b/src/test/java/org/bigbluebutton/api/ApiParamsTest.java new file mode 100644 index 0000000..428e01c --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/ApiParamsTest.java @@ -0,0 +1,114 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ApiParamsTest extends BaseTestCase { + + @Test + @DisplayName("Test API parameters names") + void apiMethodNamesShouldMatch() { + assertEquals(ApiParams.ALLOW_MODS_TO_EJECT_CAMERAS.toString(), "allowModsToEjectCameras"); + assertEquals(ApiParams.ALLOW_MODS_TO_UNMUTE_USERS.toString(), "allowModsToUnmuteUsers"); + assertEquals(ApiParams.ALLOW_REQUESTS_WITHOUT_SESSION.toString(), "allowRequestsWithoutSession"); + assertEquals(ApiParams.ALLOW_START_STOP_RECORDING.toString(), "allowStartStopRecording"); + assertEquals(ApiParams.AUTO_START_RECORDING.toString(), "autoStartRecording"); + assertEquals(ApiParams.AVATAR_URL.toString(), "avatarURL"); + assertEquals(ApiParams.BANNER_COLOR.toString(), "bannerColor"); + assertEquals(ApiParams.BANNER_TEXT.toString(), "bannerText"); + assertEquals(ApiParams.BREAKOUT_ROOMS_CAPTURE_NOTES.toString(), "breakoutRoomsCaptureNotes"); + assertEquals(ApiParams.BREAKOUT_ROOMS_CAPTURE_NOTES_FILENAME.toString(), "breakoutRoomsCaptureNotesFilename"); + assertEquals(ApiParams.BREAKOUT_ROOMS_CAPTURE_SLIDES.toString(), "breakoutRoomsCaptureSlides"); + assertEquals(ApiParams.BREAKOUT_ROOMS_PRIVATE_CHAT_ENABLED.toString(), "breakoutRoomsPrivateChatEnabled"); + assertEquals(ApiParams.BREAKOUT_ROOMS_RECORD.toString(), "breakoutRoomsRecord"); + assertEquals(ApiParams.CALLBACK_URL.toString(), "callbackURL"); + assertEquals(ApiParams.CHECKSUM.toString(), "checksum"); + assertEquals(ApiParams.COPYRIGHT.toString(), "copyright"); + assertEquals(ApiParams.CREATE_TIME.toString(), "createTime"); + assertEquals(ApiParams.DEFAULT_LAYOUT.toString(), "defaultLayout"); + assertEquals(ApiParams.DEPRECATED_LOCK_SETTINGS_DISABLE_NOTES.toString(), "lockSettingsDisableNote"); + assertEquals(ApiParams.DIAL_NUMBER.toString(), "dialNumber"); + assertEquals(ApiParams.DISABLED_FEATURES.toString(), "disabledFeatures"); + assertEquals(ApiParams.DURATION.toString(), "duration"); + assertEquals(ApiParams.END_WHEN_NO_MODERATOR.toString(), "endWhenNoModerator"); + assertEquals(ApiParams.END_WHEN_NO_MODERATOR_DELAY_IN_MINUTES.toString(), "endWhenNoModeratorDelayInMinutes"); + assertEquals(ApiParams.EXCLUDE_FROM_DASHBOARD.toString(), "excludeFromDashboard"); + assertEquals(ApiParams.FREE_JOIN.toString(), "freeJoin"); + assertEquals(ApiParams.FULL_NAME.toString(), "fullName"); + assertEquals(ApiParams.GET_RAW.toString(), "getRaw"); + assertEquals(ApiParams.GROUPS.toString(), "groups"); + assertEquals(ApiParams.GUEST.toString(), "guest"); + assertEquals(ApiParams.GUEST_POLICY.toString(), "guestPolicy"); + assertEquals(ApiParams.HOOK_ID.toString(), "hookID"); + assertEquals(ApiParams.HTML5_INSTANCE_ID.toString(), "html5InstanceId"); + assertEquals(ApiParams.IS_BREAKOUT.toString(), "isBreakout"); + assertEquals(ApiParams.LEARNING_DASHBOARD_CLEANUP_DELAY_IN_MINUTES.toString(), + "learningDashboardCleanupDelayInMinutes"); + assertEquals(ApiParams.LIMIT.toString(), "limit"); + assertEquals(ApiParams.LOCK_SETTINGS_DISABLE_CAM.toString(), "lockSettingsDisableCam"); + assertEquals(ApiParams.LOCK_SETTINGS_DISABLE_MIC.toString(), "lockSettingsDisableMic"); + assertEquals(ApiParams.LOCK_SETTINGS_DISABLE_NOTES.toString(), "lockSettingsDisableNotes"); + assertEquals(ApiParams.LOCK_SETTINGS_DISABLE_PRIVATE_CHAT.toString(), "lockSettingsDisablePrivateChat"); + assertEquals(ApiParams.LOCK_SETTINGS_DISABLE_PUBLIC_CHAT.toString(), "lockSettingsDisablePublicChat"); + assertEquals(ApiParams.LOGO.toString(), "logo"); + assertEquals(ApiParams.LOGOUT_TIMER.toString(), "logoutTimer"); + assertEquals(ApiParams.LOGOUT_URL.toString(), "logoutURL"); + assertEquals(ApiParams.MAX_PARTICIPANTS.toString(), "maxParticipants"); + assertEquals(ApiParams.MAX_PINNED_CAMERAS.toString(), "maxPinnedCameras"); + assertEquals(ApiParams.MEETING_CAMERA_CAP.toString(), "meetingCameraCap"); + assertEquals(ApiParams.MEETING_ENDED_CALLBACK_URL.toString(), "meetingEndedURL"); + assertEquals(ApiParams.MEETING_EXPIRE_IF_NO_USER_JOINED_IN_MINUTES.toString(), + "meetingExpireIfNoUserJoinedInMinutes"); + assertEquals(ApiParams.MEETING_EXPIRE_WHEN_LAST_USER_LEFT_IN_MINUTES.toString(), + "meetingExpireWhenLastUserLeftInMinutes"); + assertEquals(ApiParams.MEETING_ID.toString(), "meetingID"); + assertEquals(ApiParams.MEETING_KEEP_EVENTS.toString(), "meetingKeepEvents"); + assertEquals(ApiParams.MEETING_LAYOUT.toString(), "meetingLayout"); + assertEquals(ApiParams.META.toString(), "meta"); + assertEquals(ApiParams.MODERATOR_ONLY_MESSAGE.toString(), "moderatorOnlyMessage"); + assertEquals(ApiParams.MUTE_ON_START.toString(), "muteOnStart"); + assertEquals(ApiParams.NAME.toString(), "name"); + assertEquals(ApiParams.NOTIFY_RECORDING_IS_ON.toString(), "notifyRecordingIsOn"); + assertEquals(ApiParams.OFFSET.toString(), "offset"); + assertEquals(ApiParams.PARENT_MEETING_ID.toString(), "parentMeetingID"); + assertEquals(ApiParams.PRE_UPLOAD_PRESENTATION_OVERRIDE_DEFAULT.toString(), + "preUploadedPresentationOverrideDefault"); + assertEquals(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_DESCRIPTION.toString(), + "presentationUploadExternalDescription"); + assertEquals(ApiParams.PRESENTATION_UPLOAD_EXTERNAL_URL.toString(), "presentationUploadExternalUrl"); + assertEquals(ApiParams.PUBLISH.toString(), "publish"); + assertEquals(ApiParams.RECORD.toString(), "record"); + assertEquals(ApiParams.RECORD_ID.toString(), "recordID"); + assertEquals(ApiParams.REDIRECT.toString(), "redirect"); + assertEquals(ApiParams.ROLE.toString(), "role"); + assertEquals(ApiParams.SEQUENCE.toString(), "sequence"); + assertEquals(ApiParams.USER_CAMERA_CAP.toString(), "userCameraCap"); + assertEquals(ApiParams.USER_ID.toString(), "userID"); + assertEquals(ApiParams.VOICE_BRIDGE.toString(), "voiceBridge"); + assertEquals(ApiParams.WEB_VOICE.toString(), "webVoice"); + assertEquals(ApiParams.WEB_VOICE_CONF.toString(), "webVoiceConf"); + assertEquals(ApiParams.WEBCAMS_ONLY_FOR_MODERATOR.toString(), "webcamsOnlyForModerator"); + assertEquals(ApiParams.WELCOME.toString(), "welcome"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/ApiUserDataParamsTest.java b/src/test/java/org/bigbluebutton/api/ApiUserDataParamsTest.java new file mode 100644 index 0000000..21316af --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/ApiUserDataParamsTest.java @@ -0,0 +1,64 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ApiUserDataParamsTest extends BaseTestCase { + + @Test + @DisplayName("Test API user data parameters names") + void apiMethodNamesShouldMatch() { + + assertEquals(ApiUserDataParams.BBB_ASK_FOR_FEEDBACK_ON_LOGOUT, "bbb_ask_for_feedback_on_logout"); + assertEquals(ApiUserDataParams.BBB_OVERRIDE_DEFAULT_LOCALE, "bbb_override_default_locale"); + assertEquals(ApiUserDataParams.BBB_AUTO_JOIN_AUDIO, "bbb_auto_join_audio"); + assertEquals(ApiUserDataParams.BBB_AUTO_SHARE_WEBCAM, "bbb_auto_share_webcam"); + assertEquals(ApiUserDataParams.BBB_PREFERRED_CAMERA_PROFILE, "bbb_preferred_camera_profile"); + assertEquals(ApiUserDataParams.BBB_CLIENT_TITLE, "bbb_client_title"); + assertEquals(ApiUserDataParams.BBB_CUSTOM_STYLE, "bbb_custom_style"); + assertEquals(ApiUserDataParams.BBB_CUSTOM_STYLE_URL, "bbb_custom_style_url"); + assertEquals(ApiUserDataParams.BBB_SKIP_CHECK_AUDIO_ON_FIRST_JOIN, "bbb_skip_check_audio_on_first_join"); + assertEquals(ApiUserDataParams.BBB_DISPLAY_BRANDING_AREA, "bbb_display_branding_area"); + assertEquals(ApiUserDataParams.BBB_ENABLE_VIDEO, "bbb_enable_video"); + assertEquals(ApiUserDataParams.BBB_RECORD_VIDEO, "bbb_record_video"); + assertEquals(ApiUserDataParams.BBB_SKIP_VIDEO_PREVIEW, "bbb_skip_video_preview"); + assertEquals(ApiUserDataParams.BBB_SKIP_VIDEO_PREVIEW_ON_FIRST_JOIN, "bbb_skip_video_preview_on_first_join"); + assertEquals(ApiUserDataParams.BBB_MIRROR_OWN_WEBCAM, "bbb_mirror_own_webcam"); + assertEquals(ApiUserDataParams.BBB_FORCE_RESTORE_PRESENTATION_ON_NEW_EVENTS, + "bbb_force_restore_presentation_on_new_events"); + assertEquals(ApiUserDataParams.BBB_FORCE_LISTEN_ONLY, "bbb_force_listen_only"); + assertEquals(ApiUserDataParams.BBB_HIDE_PRESENTATION, "bbb_hide_presentation"); + assertEquals(ApiUserDataParams.BBB_LISTEN_ONLY_MODE, "bbb_listen_only_mode"); + assertEquals(ApiUserDataParams.BBB_MULTI_USER_PEN_ONLY, "bbb_multi_user_pen_only"); + assertEquals(ApiUserDataParams.BBB_MULTI_USER_TOOLS, "bbb_multi_user_tools"); + assertEquals(ApiUserDataParams.BBB_PRESENTER_TOOLS, "bbb_presenter_tools"); + assertEquals(ApiUserDataParams.BBB_SHORTCUTS, "bbb_shortcuts"); + assertEquals(ApiUserDataParams.BBB_SKIP_CHECK_AUDIO, "bbb_skip_check_audio"); + assertEquals(ApiUserDataParams.BBB_HIDE_PRESENTATION_ON_JOIN, "bbb_hide_presentation_on_join"); + assertEquals(ApiUserDataParams.BBB_SHOW_PARTICIPANTS_ON_LOGIN, "bbb_show_participants_on_login"); + assertEquals(ApiUserDataParams.BBB_HIDE_ACTIONS_BAR, "bbb_hide_actions_bar"); + assertEquals(ApiUserDataParams.BBB_HIDE_NAV_BAR, "bbb_hide_nav_bar"); + assertEquals(ApiUserDataParams.BBB_CHANGE_LAYOUT, "bbb_change_layout"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/BigBlueButtonAPITest.java b/src/test/java/org/bigbluebutton/api/BigBlueButtonAPITest.java new file mode 100644 index 0000000..d83c29a --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/BigBlueButtonAPITest.java @@ -0,0 +1,123 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.bigbluebutton.api.parameters.CreateMeetingParameters; +import org.bigbluebutton.api.parameters.EndMeetingParameters; +import org.bigbluebutton.api.responses.APIReturnCode; +import org.bigbluebutton.api.responses.ApiVersionResponse; +import org.bigbluebutton.api.responses.CreateMeetingResponse; +import org.bigbluebutton.api.responses.EndMeetingResponse; +import org.bigbluebutton.api.test.BigBlueButtonTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; + +public class BigBlueButtonAPITest extends BigBlueButtonTestCase { + + private BigBlueButtonAPI bbbAPI; + + @BeforeEach + public void setUp() { + super.setUp(); + bbbAPI = new BigBlueButtonAPI(); + } + + @Test + @DisplayName("API version") + public void fetchAPIVersion() throws MalformedURLException, IOException, ParserConfigurationException, SAXException, + InterruptedException, URISyntaxException { + ApiVersionResponse apiVersion = bbbAPI.getAPIVersion(); + assertEquals(apiVersion.getReturnCode(), "SUCCESS"); + assertEquals(apiVersion.getApiVersion(), "2.0"); + assertEquals(apiVersion.getVersion(), "2.0"); + assertEquals(apiVersion.getBbbVersion(), ""); + } + + @Test + @DisplayName("Create meeting") + public void shouldCreateMeeting() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + CreateMeetingParameters createMeetingParms = generateCreateMeetingParams(); + CreateMeetingResponse createMeetingResponse = bbbAPI.createMeeting(createMeetingParms); + assertEquals(createMeetingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(createMeetingResponse.getMeetingId(), createMeetingParms.getMeetingId()); + } + + @Test + @DisplayName("Create meeting with a presentation") + public void shouldCreateMeetingWithAPresetnation() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + CreateMeetingParameters createMeetingParms = generateCreateMeetingParams(); + createMeetingParms.addPresentation(faker.country().name() + ".pdf", + URI.create("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")); + CreateMeetingResponse createMeetingResponse = bbbAPI.createMeeting(createMeetingParms); + assertEquals(createMeetingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(createMeetingResponse.getMeetingId(), createMeetingParms.getMeetingId()); + } + + @Test + @DisplayName("Create meeting with an image as presentation") + public void shouldCreateMeetingWithAnImage() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + CreateMeetingParameters createMeetingParms = generateCreateMeetingParams(); + createMeetingParms.addPresentation(faker.country().name() + ".jpg", + URI.create("https://picsum.photos/3840/2160/?random")); + CreateMeetingResponse createMeetingResponse = bbbAPI.createMeeting(createMeetingParms); + assertEquals(createMeetingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(createMeetingResponse.getMeetingId(), createMeetingParms.getMeetingId()); + } + + @Test + @DisplayName("End a non-existing meeting") + public void shouldNotFindMeetingToEnd() throws JsonMappingException, JsonProcessingException, MalformedURLException, + IOException, ParserConfigurationException, SAXException, InterruptedException, URISyntaxException { + EndMeetingParameters endMeetingParms = generateEndMeetingParams(); + EndMeetingResponse endMeetingResponse = bbbAPI.endMeeting(endMeetingParms); + assertEquals(endMeetingResponse.getReturnCode(), APIReturnCode.FAILED.getReturnCode()); + } + + @Test + @DisplayName("End a real existing meeting") + public void shouldEndRealMeeting() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + String meetingId = realMeeting().getMeetingId(); + Thread.sleep(500); + EndMeetingResponse endMeetingResponse = bbbAPI.endMeeting(new EndMeetingParameters(meetingId)); + assertEquals(endMeetingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/enums/FeatureTest.java b/src/test/java/org/bigbluebutton/api/enums/FeatureTest.java new file mode 100644 index 0000000..6c510f3 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/enums/FeatureTest.java @@ -0,0 +1,50 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class FeatureTest extends BaseTestCase { + + @Test + @DisplayName("Test feature names") + void featureNamesShouldMatch() { + assertEquals(Feature.BREAKOUT_ROOMS.getName(), "breakoutRooms"); + assertEquals(Feature.CAPTIONS.getName(), "captions"); + assertEquals(Feature.CHAT.getName(), "chat"); + assertEquals(Feature.DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS.getName(), "downloadPresentationWithAnnotations"); + assertEquals(Feature.EXTERNAL_VIDEOS.getName(), "externalVideos"); + assertEquals(Feature.IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS.getName(), + "importPresentationWithAnnotationsFromBreakoutRooms"); + assertEquals(Feature.IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS.getName(), "importSharedNotesFromBreakoutRooms"); + assertEquals(Feature.LAYOUTS.getName(), "layouts"); + assertEquals(Feature.LEARNING_DASHBOARD.getName(), "learningDashboard"); + assertEquals(Feature.POLLS.getName(), "polls"); + assertEquals(Feature.SCREENSHARE.getName(), "screenshare"); + assertEquals(Feature.SHARED_NOTES.getName(), "sharedNotes"); + assertEquals(Feature.VIRTUAL_BACKGROUNDS.getName(), "virtualBackgrounds"); + assertEquals(Feature.CUSTOM_VIRTUAL_BACKGROUNDS.getName(), "customVirtualBackgrounds"); + assertEquals(Feature.LIVE_TRANSCRIPTION.getName(), "liveTranscription"); + assertEquals(Feature.PRESENTATION.getName(), "presentation"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/enums/GuestPolicyTest.java b/src/test/java/org/bigbluebutton/api/enums/GuestPolicyTest.java new file mode 100644 index 0000000..8a83bbf --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/enums/GuestPolicyTest.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class GuestPolicyTest extends BaseTestCase { + + @Test + @DisplayName("Test guest policy names") + void featureNamesShouldMatch() { + assertEquals(GuestPolicy.ALWAYS_ACCEPT.getName(), "ALWAYS_ACCEPT"); + assertEquals(GuestPolicy.ALWAYS_DENY.getName(), "ALWAYS_DENY"); + assertEquals(GuestPolicy.ASK_MODERATOR.getName(), "ASK_MODERATOR"); + assertEquals(GuestPolicy.ALWAYS_ACCEPT_AUTH.getName(), "ALWAYS_ACCEPT_AUTH"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/enums/MeetingLayoutTest.java b/src/test/java/org/bigbluebutton/api/enums/MeetingLayoutTest.java new file mode 100644 index 0000000..8497da8 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/enums/MeetingLayoutTest.java @@ -0,0 +1,37 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class MeetingLayoutTest extends BaseTestCase { + + @Test + @DisplayName("Test meeting layout names") + void featureNamesShouldMatch() { + assertEquals(MeetingLayout.CUSTOM_LAYOUT.getName(), "CUSTOM_LAYOUT"); + assertEquals(MeetingLayout.PRESENTATION_FOCUS.getName(), "PRESENTATION_FOCUS"); + assertEquals(MeetingLayout.SMART_LAYOUT.getName(), "SMART_LAYOUT"); + assertEquals(MeetingLayout.VIDEO_FOCUS.getName(), "VIDEO_FOCUS"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/enums/RecordingStateTest.java b/src/test/java/org/bigbluebutton/api/enums/RecordingStateTest.java new file mode 100644 index 0000000..cc5f545 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/enums/RecordingStateTest.java @@ -0,0 +1,39 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class RecordingStateTest extends BaseTestCase { + + @Test + @DisplayName("Test recording states") + void featureNamesShouldMatch() { + assertEquals(RecordingState.ANY.getName(), "any"); + assertEquals(RecordingState.DELETED.getName(), "deleted"); + assertEquals(RecordingState.PROCESSED.getName(), "processed"); + assertEquals(RecordingState.PROCESSING.getName(), "processing"); + assertEquals(RecordingState.PUBLISHED.getName(), "published"); + assertEquals(RecordingState.UNPUBLISHED.getName(), "unpublished"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/enums/RoleTest.java b/src/test/java/org/bigbluebutton/api/enums/RoleTest.java new file mode 100644 index 0000000..853691c --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/enums/RoleTest.java @@ -0,0 +1,35 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.enums; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class RoleTest extends BaseTestCase { + + @Test + @DisplayName("Test role names") + void featureNamesShouldMatch() { + assertEquals(Role.MODERATOR.getName(), "MODERATOR"); + assertEquals(Role.VIEWER.getName(), "VIEWER"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/logging/MemoryAppender.java b/src/test/java/org/bigbluebutton/api/logging/MemoryAppender.java new file mode 100644 index 0000000..75b2ebd --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/logging/MemoryAppender.java @@ -0,0 +1,60 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.logging; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.slf4j.event.Level; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; + +public class MemoryAppender extends ListAppender { + public void reset() { + this.list.clear(); + } + + public boolean contains(String string, Level level) { + return this.list.stream() + .anyMatch(event -> event.toString().contains(string) && event.getLevel().equals(level)); + } + + public int countEventsForLogger(String loggerName) { + return (int) this.list.stream().filter(event -> event.getLoggerName().contains(loggerName)).count(); + } + + public List search(String string) { + return this.list.stream().filter(event -> event.toString().contains(string)).collect(Collectors.toList()); + } + + public List search(String string, Level level) { + return this.list.stream().filter(event -> event.toString().contains(string) && event.getLevel().equals(level)) + .collect(Collectors.toList()); + } + + public int getSize() { + return this.list.size(); + } + + public List getLoggedEvents() { + return Collections.unmodifiableList(this.list); + } +} \ No newline at end of file diff --git a/src/test/java/org/bigbluebutton/api/responses/APIReturnCodeTest.java b/src/test/java/org/bigbluebutton/api/responses/APIReturnCodeTest.java new file mode 100644 index 0000000..a9d3916 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/APIReturnCodeTest.java @@ -0,0 +1,40 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.bigbluebutton.api.test.BaseTestCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class APIReturnCodeTest extends BaseTestCase { + + @Test + @DisplayName("Failed API return code") + void failedReturnCodeShouldMatch() { + assertEquals(APIReturnCode.FAILED.getReturnCode(), "FAILED"); + } + + @Test + @DisplayName("Success API return code") + void successReturnCodeShouldMatch() { + assertEquals(APIReturnCode.SUCCESS.getReturnCode(), "SUCCESS"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/ApiVersionResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/ApiVersionResponseTest.java new file mode 100644 index 0000000..4e13b59 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/ApiVersionResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class ApiVersionResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/api_version.xml"; + + super.setUp(); + } + + @Test + @DisplayName("API version response content") + void testApiVersionResponseContent() throws StreamReadException, DatabindException, IOException { + ApiVersionResponse apiVersionResponse = xmlMapper.readValue(xmlInput, ApiVersionResponse.class); + assertEquals(apiVersionResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/CreateMeetingResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/CreateMeetingResponseTest.java new file mode 100644 index 0000000..97e3f63 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/CreateMeetingResponseTest.java @@ -0,0 +1,66 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.bigbluebutton.api.util.DateTimeUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class CreateMeetingResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/create_meeting.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Create meeting response content") + void testCreateMeetingResponseContent() throws StreamReadException, DatabindException, IOException { + CreateMeetingResponse createResponse = xmlMapper.readValue(xmlInput, CreateMeetingResponse.class); + assertEquals(createResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(createResponse.getMeetingId(), "random-1665177"); + assertEquals(createResponse.getInternalMeetingId(), "1a6938c707cdf5d052958672d66c219c30690c47-1524212045514"); + assertEquals(createResponse.getParentMeetingId(), "bbb-none"); + assertEquals(createResponse.getCreateTime().getEpochSecond(), 1453283819419L); + assertEquals(createResponse.getVoiceBridge(), "76286"); + assertEquals(createResponse.getDialNumber(), "613-555-1234"); + assertEquals(createResponse.getCreateDate().format(DateTimeUtil.TZ_DATE_FORMATTER), + "Wed Jan 20 04:56:59 CET 2016"); + assertFalse(createResponse.getHasUserJoined()); + assertEquals(createResponse.getDuration(), 20); + assertFalse(createResponse.getHasBeenForciblyEnded()); + assertEquals(createResponse.getMessageKey(), "duplicateWarning"); + assertEquals(createResponse.getMessage(), + "This conference was already in existence and may currently be in progress."); + assertTrue(createResponse.hasParent()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/DeleteRecordingsResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/DeleteRecordingsResponseTest.java new file mode 100644 index 0000000..f991706 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/DeleteRecordingsResponseTest.java @@ -0,0 +1,52 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class DeleteRecordingsResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/delete_recordings.xml"; + + super.setUp(); + } + + @Test + @DisplayName("API delete recording scontent") + void testEndDeleteRecordingsResponseContent() throws StreamReadException, DatabindException, IOException { + DeleteRecordingsResponse deleteRecordingsResponse = xmlMapper.readValue(xmlInput, + DeleteRecordingsResponse.class); + assertEquals(deleteRecordingsResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertTrue(deleteRecordingsResponse.success()); + assertTrue(deleteRecordingsResponse.getDeleted()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/EndMeetingResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/EndMeetingResponseTest.java new file mode 100644 index 0000000..fa9d1a9 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/EndMeetingResponseTest.java @@ -0,0 +1,36 @@ +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class EndMeetingResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/end_meeting.xml"; + + super.setUp(); + } + + @Test + @DisplayName("API end meeting response content") + void testEndMeetingResponseContent() throws StreamReadException, DatabindException, IOException { + EndMeetingResponse endMeetingResponse = xmlMapper.readValue(xmlInput, EndMeetingResponse.class); + assertEquals(endMeetingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertTrue(endMeetingResponse.success()); + assertFalse(endMeetingResponse.failed()); + assertFalse(endMeetingResponse.getMessage().isEmpty()); + assertFalse(endMeetingResponse.getMessageKey().isEmpty()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/GetMeetingInfoResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/GetMeetingInfoResponseTest.java new file mode 100644 index 0000000..1bba885 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/GetMeetingInfoResponseTest.java @@ -0,0 +1,62 @@ +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.deserializers.GetMeetingInfoResponseDeserializer; +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.bigbluebutton.api.util.DateTimeUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public class GetMeetingInfoResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/get_meeting_info.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Get meeting info response content") + void testGetMeetingInfoResponseContent() throws StreamReadException, DatabindException, IOException { + xmlMapper.registerModule(new SimpleModule().addDeserializer(GetMeetingInfoResponse.class, + new GetMeetingInfoResponseDeserializer())); + GetMeetingInfoResponse getMeetingInfoResponse = xmlMapper.readValue(xmlInput, GetMeetingInfoResponse.class); + assertEquals(getMeetingInfoResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(getMeetingInfoResponse.getMeeting().getMeetingId(), "117b12ae2656972d330b6bad58878541-28-15"); + assertEquals(getMeetingInfoResponse.getMeeting().getMeetingName(), + "Mock meeting for testing getMeetingInfo API method"); + assertEquals(getMeetingInfoResponse.getMeeting().getCreateDate().format(DateTimeUtil.TZ_DATE_FORMATTER), + "Fri Jan 20 04:56:59 CET 2023"); + assertEquals(getMeetingInfoResponse.getMeeting().getCreateTime().getEpochSecond(), 1453206317376L); + assertEquals(getMeetingInfoResponse.getMeeting().getVoiceBridge(), "70100"); + assertEquals(getMeetingInfoResponse.getMeeting().getDialNumber(), "613-555-1234"); + assertTrue(getMeetingInfoResponse.getMeeting().getRunning()); + assertEquals(getMeetingInfoResponse.getMeeting().getDuration(), 20); + assertTrue(getMeetingInfoResponse.getMeeting().getHasUserJoined()); + assertTrue(getMeetingInfoResponse.getMeeting().getRecording()); + assertFalse(getMeetingInfoResponse.getMeeting().getHasBeenForciblyEnded()); + assertEquals(getMeetingInfoResponse.getMeeting().getStartTime().getEpochSecond(), 1453206317380L); + assertEquals(getMeetingInfoResponse.getMeeting().getEndTime().getEpochSecond(), 1453206325002L); + assertEquals(getMeetingInfoResponse.getMeeting().getParticipantCount(), 2); + assertEquals(getMeetingInfoResponse.getMeeting().getListenerCount(), 1); + assertEquals(getMeetingInfoResponse.getMeeting().getVoiceParticipantCount(), 2); + assertEquals(getMeetingInfoResponse.getMeeting().getVideoCount(), 1); + assertEquals(getMeetingInfoResponse.getMeeting().getModeratorCount(), 2); + assertTrue(getMeetingInfoResponse.getMeeting().getIsBreakout()); + assertEquals(getMeetingInfoResponse.getMeeting().getMaxUsers(), 20); + assertEquals(getMeetingInfoResponse.getMeeting().getSequence(), 1); + assertEquals(getMeetingInfoResponse.getMeeting().getParentMeetingId(), + "b97b512f2c92c0ffe7a3476152525807daa1c676-1524213151782"); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/GetMeetingsResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/GetMeetingsResponseTest.java new file mode 100644 index 0000000..fc42052 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/GetMeetingsResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class GetMeetingsResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/get_meetings.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Get meetings response content") + void testGetMeetingsResponseContent() throws StreamReadException, DatabindException, IOException { + GetMeetingsResponse getMeetingInfoResponse = xmlMapper.readValue(xmlInput, GetMeetingsResponse.class); + assertEquals(getMeetingInfoResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponseTest.java new file mode 100644 index 0000000..c72d025 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/GetRecordingTextTracksResponseTest.java @@ -0,0 +1,49 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.JsonResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class GetRecordingTextTracksResponseTest extends JsonResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/get_recording_text_tracks.json"; + + super.setUp(); + } + + @Test + @DisplayName("Get recording text tracks content") + void testRecordingsTextTracksResponseContent() throws StreamReadException, DatabindException, IOException { + GetRecordingTextTracksResponse getMeetingInfoResponse = jsonMapper.readValue(jsonInput, + GetRecordingTextTracksResponse.class); + assertEquals(getMeetingInfoResponse.response.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/GetRecordingsResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/GetRecordingsResponseTest.java new file mode 100644 index 0000000..98316fc --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/GetRecordingsResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class GetRecordingsResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/get_recordings.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Get recordings response content") + void testRecordingsResponseContent() throws StreamReadException, DatabindException, IOException { + GetRecordingsResponse getRecordingsResponse = xmlMapper.readValue(xmlInput, GetRecordingsResponse.class); + assertEquals(getRecordingsResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/HooksCreateResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/HooksCreateResponseTest.java new file mode 100644 index 0000000..94f2477 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/HooksCreateResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class HooksCreateResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/hooks_create.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Hooks create api response content") + void testIsHooksCreateResponseContent() throws StreamReadException, DatabindException, IOException { + HooksCreateResponse hooksCreateResponse = xmlMapper.readValue(xmlInput, HooksCreateResponse.class); + assertEquals(hooksCreateResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/HooksDestroyResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/HooksDestroyResponseTest.java new file mode 100644 index 0000000..4e93905 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/HooksDestroyResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class HooksDestroyResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/hooks_destroy.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Hooks destroy api response content") + void testHooksDestroyResponseContent() throws StreamReadException, DatabindException, IOException { + HooksDestroyResponse hooksCreateResponse = xmlMapper.readValue(xmlInput, HooksDestroyResponse.class); + assertEquals(hooksCreateResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/HooksListResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/HooksListResponseTest.java new file mode 100644 index 0000000..64e7a72 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/HooksListResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class HooksListResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/hooks_list.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Hooks list api response content") + void testIsMeetingRunningResponseContent() throws StreamReadException, DatabindException, IOException { + HooksListResponse hooksCreateResponse = xmlMapper.readValue(xmlInput, HooksListResponse.class); + assertEquals(hooksCreateResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/InsertDocumentResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/InsertDocumentResponseTest.java new file mode 100644 index 0000000..75c0b51 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/InsertDocumentResponseTest.java @@ -0,0 +1,48 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class InsertDocumentResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/insert_document.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Insert document api response content") + void testInsertDocumentResponseContent() throws StreamReadException, DatabindException, IOException { + InsertDocumentResponse insertDocumentResponse = xmlMapper.readValue(xmlInput, InsertDocumentResponse.class); + assertEquals(insertDocumentResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/IsMeetingRunningResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/IsMeetingRunningResponseTest.java new file mode 100644 index 0000000..1d0302e --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/IsMeetingRunningResponseTest.java @@ -0,0 +1,50 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +class IsMeetingRunningResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/is_meeting_running.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Meeting running api response content") + void testIsMeetingRunningResponseContent() throws StreamReadException, DatabindException, IOException { + IsMeetingRunningResponse isMeetingRunningResponse = xmlMapper.readValue(xmlInput, + IsMeetingRunningResponse.class); + assertEquals(isMeetingRunningResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(isMeetingRunningResponse.getRunning(), true); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/JoineMeetingResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/JoineMeetingResponseTest.java new file mode 100644 index 0000000..6fa3f15 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/JoineMeetingResponseTest.java @@ -0,0 +1,39 @@ +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.URI; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +public class JoineMeetingResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/join_meeting.xml"; + + super.setUp(); + } + + @Test + @DisplayName("Join meeting response content") + void testJoinMeetingResponseContent() throws StreamReadException, DatabindException, IOException { + JoinMeetingResponse joinmeeingResponse = xmlMapper.readValue(xmlInput, JoinMeetingResponse.class); + assertEquals(joinmeeingResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertEquals(joinmeeingResponse.getMeetingId(), "bec8af173fae4d1f45d8ed6ea7c0b1ffb93af020-1464618265614"); + assertEquals(joinmeeingResponse.getUserId(), "ao6ehbtvbmhz"); + assertEquals(joinmeeingResponse.getAuthToken(), "huzbpgthac7s"); + assertEquals(joinmeeingResponse.getSessionToken(), "rbe7bbkjzx5mnoda"); + assertEquals(joinmeeingResponse.getGuestStatus(), "ALLOW"); + assertEquals(joinmeeingResponse.getUrl(), URI + .create("https://bigblubutton-server.sample/client/BigBlueButton.html?sessionToken=BKepJSKk39jtwDC9")); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/PublishRecordingsResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/PublishRecordingsResponseTest.java new file mode 100644 index 0000000..0a4e612 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/PublishRecordingsResponseTest.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class PublishRecordingsResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/publish_recordings.xml"; + + super.setUp(); + } + + @Test + @DisplayName("API publish recording scontent") + void testEndDeleteRecordingsResponseContent() throws StreamReadException, DatabindException, IOException { + PublishRecordingsResponse publishRecordingsResponse = xmlMapper.readValue(xmlInput, + PublishRecordingsResponse.class); + assertEquals(publishRecordingsResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertTrue(publishRecordingsResponse.success()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponseTest.java new file mode 100644 index 0000000..9af5e7f --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/PutRecordingTextTrackResponseTest.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.JsonResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class PutRecordingTextTrackResponseTest extends JsonResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/put_recording_text_track_success.json"; + + super.setUp(); + } + + @Test + @DisplayName("API put recording text track scontent") + void testPutRecordingTextTrackResponseContent() throws StreamReadException, DatabindException, IOException { + PutRecordingTextTrackResponse putRecordingTextTrackResponse = jsonMapper.readValue(jsonInput, + PutRecordingTextTrackResponse.class); + assertEquals(putRecordingTextTrackResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertTrue(putRecordingTextTrackResponse.success()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/responses/UpdateRecordingsResponseTest.java b/src/test/java/org/bigbluebutton/api/responses/UpdateRecordingsResponseTest.java new file mode 100644 index 0000000..fa7e0f1 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/responses/UpdateRecordingsResponseTest.java @@ -0,0 +1,51 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.responses; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.bigbluebutton.api.test.XMLResponseTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; + +public class UpdateRecordingsResponseTest extends XMLResponseTestCase { + + @BeforeEach + public void setUp() { + xmlResponseFile = "fixtures/update_recordings.xml"; + + super.setUp(); + } + + @Test + @DisplayName("API publish recording scontent") + void testEndDeleteRecordingsResponseContent() throws StreamReadException, DatabindException, IOException { + UpdateRecordingsResponse updateRecordingsResponse = xmlMapper.readValue(xmlInput, + UpdateRecordingsResponse.class); + assertEquals(updateRecordingsResponse.getReturnCode(), APIReturnCode.SUCCESS.getReturnCode()); + assertTrue(updateRecordingsResponse.success()); + } +} diff --git a/src/test/java/org/bigbluebutton/api/test/BaseTestCase.java b/src/test/java/org/bigbluebutton/api/test/BaseTestCase.java new file mode 100644 index 0000000..406e403 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/test/BaseTestCase.java @@ -0,0 +1,42 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.test; + +import org.bigbluebutton.api.logging.MemoryAppender; +import org.junit.jupiter.api.BeforeEach; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; + +import ch.qos.logback.classic.LoggerContext; + +public abstract class BaseTestCase { + + private MemoryAppender memoryAppender; + + @BeforeEach + public void setUp() { + Logger logger = (Logger) LoggerFactory.getLogger(this.getClass()); + memoryAppender = new MemoryAppender(); + memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory()); + logger.atLevel(Level.DEBUG); + memoryAppender.start(); + } + +} diff --git a/src/test/java/org/bigbluebutton/api/test/BigBlueButtonTestCase.java b/src/test/java/org/bigbluebutton/api/test/BigBlueButtonTestCase.java new file mode 100644 index 0000000..60222c3 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/test/BigBlueButtonTestCase.java @@ -0,0 +1,142 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.test; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.bigbluebutton.api.ApiParams; +import org.bigbluebutton.api.BigBlueButtonAPI; +import org.bigbluebutton.api.enums.GuestPolicy; +import org.bigbluebutton.api.enums.MeetingLayout; +import org.bigbluebutton.api.enums.Role; +import org.bigbluebutton.api.parameters.CreateMeetingParameters; +import org.bigbluebutton.api.parameters.EndMeetingParameters; +import org.bigbluebutton.api.parameters.JoinMeetingParameters; +import org.bigbluebutton.api.responses.CreateMeetingResponse; +import org.junit.jupiter.api.BeforeEach; +import org.xml.sax.SAXException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.github.javafaker.Faker; + +public class BigBlueButtonTestCase extends BaseTestCase { + + protected Faker faker; + + @BeforeEach + public void setUp() { + super.setUp(); + faker = new Faker(); + } + + protected CreateMeetingResponse realMeeting() + throws JsonMappingException, JsonProcessingException, MalformedURLException, IOException, + ParserConfigurationException, SAXException, InterruptedException, URISyntaxException, TransformerException { + CreateMeetingParameters createMeetingParms = generateCreateMeetingParams(); + + BigBlueButtonAPI bbbApi = new BigBlueButtonAPI(); + + CreateMeetingResponse response = bbbApi.createMeeting(createMeetingParms); + return response; + } + + protected CreateMeetingParameters generateCreateMeetingParams() { + Map mockCreate = mockCreateMeetingParams(); + CreateMeetingParameters createParams = new CreateMeetingParameters((String) mockCreate.get(ApiParams.NAME), + (String) mockCreate.get(ApiParams.MEETING_ID)).setAllowModsToEjectCameras(faker.bool().bool()) + .setAllowModsToUnmuteUsers(faker.bool().bool()).setAllowRequestsWithoutSession(faker.bool().bool()) + .setAllowStartStopRecording(faker.bool().bool()).setAutoStartRecording(faker.bool().bool()) + .setBannerColor(faker.color().hex()).setBannerText(faker.lorem().sentence()) + .setBreakoutRoomsPrivateChatEnabled(faker.bool().bool()).setBreakoutRoomsRecord(faker.bool().bool()) + .setDialNumber(faker.phoneNumber().phoneNumber()).setDuration(faker.number().numberBetween(0, 10)) + .setEndWhenNoModerator(faker.bool().bool()) + .setEndWhenNoModeratorDelayInMinutes(faker.number().numberBetween(2, 5)) + .setFreeJoin(faker.bool().bool()) + .setGuestPolicy(GuestPolicy.values()[new Random().nextInt(GuestPolicy.values().length)]) + .setIsBreakout(faker.bool().bool()) + .setLearningDashboardCleanupDelayInMinutes(faker.number().numberBetween(0, 120)) + .setLockSettingsDisableCam(faker.bool().bool()).setLockSettingsDisableMic(faker.bool().bool()) + .setLockSettingsDisableNote(faker.bool().bool()).setLockSettingsDisablePrivateChat(faker.bool().bool()) + .setLockSettingsDisablePublicChat(faker.bool().bool()) + .setLockSettingsHideViewersCursor(faker.bool().bool()).setLockSettingsLockOnJoin(faker.bool().bool()) + .setLockSettingsLockOnJoinConfigurable(faker.bool().bool()).setLogo(URI.create(faker.internet().url())) + .setMaxParticipants(faker.number().numberBetween(0, 200)) + .setMeetingCameraCap(faker.number().numberBetween(8, 20)) + .setMeetingExpireIfNoUserJoinedInMinutes(faker.number().numberBetween(0, 10)) + .setMeetingExpireWhenLastUserLeftInMinutes(faker.number().numberBetween(2, 8)) + .setMeetingKeepEvents(faker.bool().bool()) + .setMeetingLayout(MeetingLayout.values()[new Random().nextInt(MeetingLayout.values().length)]) + .setModeratorOnlyMessage(faker.lorem().paragraph()).setMuteOnStart(faker.bool().bool()) + .setNotifyRecordingIsOn(faker.bool().bool()) + .setPresentationUploadExternalDescription(faker.lorem().sentence()) + .setPresentationUploadExternalUrl(URI.create(faker.internet().url())) + .setPreUploadedPresentationOverrideDefault(faker.bool().bool()).setRecord(faker.bool().bool()) + .setSequence(faker.number().numberBetween(1, 5)).setUserCameraCap(faker.number().numberBetween(3, 5)) + .setVoiceBridge(faker.phoneNumber().extension()).setWebcamsOnlyForModeratorBoolean(faker.bool().bool()) + .setWelcome(faker.lorem().paragraph()) + .addMeta(faker.country().countryCode3(), faker.country().capital()); + return createParams; + } + + protected EndMeetingParameters generateEndMeetingParams() { + Map mockEnd = mockEndMeetingParams(); + EndMeetingParameters endParams = new EndMeetingParameters((String) mockEnd.get(ApiParams.MEETING_ID)); + return endParams; + } + + protected JoinMeetingParameters generateJoinMeetingParams() { + Map mockJoin = mockJoinMeetingParams(); + JoinMeetingParameters joinParams = new JoinMeetingParameters((String) mockJoin.get(ApiParams.FULL_NAME), + (String) mockJoin.get(ApiParams.MEETING_ID), (Role) mockJoin.get(ApiParams.ROLE)); + return joinParams; + } + + protected Map mockCreateMeetingParams() { + Map paramsMap = new HashMap<>(); + paramsMap.put(ApiParams.NAME, faker.educator().course()); + paramsMap.put(ApiParams.MEETING_ID, faker.code().isbn10()); + return paramsMap; + } + + protected Map mockEndMeetingParams() { + Map paramsMap = new HashMap<>(); + + paramsMap.put(ApiParams.MEETING_ID, faker.code().isbn10()); + return paramsMap; + } + + protected Map mockJoinMeetingParams() { + Map paramsMap = new HashMap<>(); + paramsMap.put(ApiParams.FULL_NAME, faker.name().fullName()); + paramsMap.put(ApiParams.ROLE, Role.values()[new Random().nextInt(Role.values().length)]); + paramsMap.put(ApiParams.MEETING_ID, faker.code().isbn10()); + return paramsMap; + } + +} diff --git a/src/test/java/org/bigbluebutton/api/test/JsonResponseTestCase.java b/src/test/java/org/bigbluebutton/api/test/JsonResponseTestCase.java new file mode 100644 index 0000000..c97ad6f --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/test/JsonResponseTestCase.java @@ -0,0 +1,57 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.test; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.jupiter.api.BeforeEach; + +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +public abstract class JsonResponseTestCase extends BaseTestCase { + + protected String xmlResponseFile; + + protected byte[] jsonInput; + + protected JsonMapper jsonMapper; + + @BeforeEach + public void setUp() { + super.setUp(); + try { + jsonInput = Files.readAllBytes(Paths.get( + new File(getClass().getClassLoader().getResource(xmlResponseFile).getFile()).getAbsolutePath())); + } catch (IOException e) { + // TODO Auto-generated catch block + fail("Failed loading fixutre: " + xmlResponseFile); + } + + jsonMapper = new JsonMapper(); + jsonMapper.registerModule(new JavaTimeModule()); + jsonMapper.findAndRegisterModules(); + } + +} diff --git a/src/test/java/org/bigbluebutton/api/test/XMLResponseTestCase.java b/src/test/java/org/bigbluebutton/api/test/XMLResponseTestCase.java new file mode 100644 index 0000000..2adb8f8 --- /dev/null +++ b/src/test/java/org/bigbluebutton/api/test/XMLResponseTestCase.java @@ -0,0 +1,57 @@ +/* + * BigBlueButton open source conferencing system - https://www.bigbluebutton.org/. + * + * Copyright (c) 2023 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see . + */ + +package org.bigbluebutton.api.test; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.jupiter.api.BeforeEach; + +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +public abstract class XMLResponseTestCase extends BaseTestCase { + + protected String xmlResponseFile; + + protected byte[] xmlInput; + + protected XmlMapper xmlMapper; + + @BeforeEach + public void setUp() { + super.setUp(); + try { + xmlInput = Files.readAllBytes(Paths.get( + new File(getClass().getClassLoader().getResource(xmlResponseFile).getFile()).getAbsolutePath())); + } catch (IOException e) { + // TODO Auto-generated catch block + fail("Failed loading fixutre: " + xmlResponseFile); + } + + xmlMapper = new XmlMapper(); + xmlMapper.registerModule(new JavaTimeModule()); + xmlMapper.findAndRegisterModules(); + } + +} diff --git a/src/test/resources/fixtures/api_version.xml b/src/test/resources/fixtures/api_version.xml new file mode 100644 index 0000000..a1d42e7 --- /dev/null +++ b/src/test/resources/fixtures/api_version.xml @@ -0,0 +1,6 @@ + + SUCCESS + 2.0 + 2.0 + 2.6.5 + diff --git a/src/test/resources/fixtures/bbb_logo.png b/src/test/resources/fixtures/bbb_logo.png new file mode 100644 index 0000000..00dcf94 Binary files /dev/null and b/src/test/resources/fixtures/bbb_logo.png differ diff --git a/src/test/resources/fixtures/create_meeting.xml b/src/test/resources/fixtures/create_meeting.xml new file mode 100644 index 0000000..c92e0c6 --- /dev/null +++ b/src/test/resources/fixtures/create_meeting.xml @@ -0,0 +1,17 @@ + + SUCCESS + random-1665177 + 1a6938c707cdf5d052958672d66c219c30690c47-1524212045514 + bbb-none + tK6J5cJv3hMLNx5IBePa + 34Heu0uiZYqCZXX9C4m2 + 1453283819419 + 76286 + 613-555-1234 + Wed Jan 20 04:56:59 CET 2016 + false + 20 + false + duplicateWarning + This conference was already in existence and may currently be in progress. + diff --git a/src/test/resources/fixtures/delete_recordings.xml b/src/test/resources/fixtures/delete_recordings.xml new file mode 100644 index 0000000..8d290a9 --- /dev/null +++ b/src/test/resources/fixtures/delete_recordings.xml @@ -0,0 +1,4 @@ + + SUCCESS + true + diff --git a/src/test/resources/fixtures/end_meeting.xml b/src/test/resources/fixtures/end_meeting.xml new file mode 100644 index 0000000..ef445e9 --- /dev/null +++ b/src/test/resources/fixtures/end_meeting.xml @@ -0,0 +1,7 @@ + + SUCCESS + sentEndMeetingRequest + A request to end the meeting was sent. Please wait a few seconds, and then use the getMeetingInfo or + isMeetingRunning API calls to verify that it was ended. + + diff --git a/src/test/resources/fixtures/get_meeting_info.xml b/src/test/resources/fixtures/get_meeting_info.xml new file mode 100644 index 0000000..e07d512 --- /dev/null +++ b/src/test/resources/fixtures/get_meeting_info.xml @@ -0,0 +1,95 @@ + + + SUCCESS + Mock meeting for testing getMeetingInfo API method + 117b12ae2656972d330b6bad58878541-28-15 + 178757fcedd9449054536162cdfe861ddebc70ba-1453206317376 + 1453206317376 + Fri Jan 20 04:56:59 CET 2023 + 70100 + 613-555-1234 + dbfc7207321527bbb870c82028 + 4bfbbeeb4a65cacaefe3676633 + true + 20 + true + true + false + 1453206317380 + 1453206325002 + 2 + 1 + 2 + 1 + 20 + 2 + + + amslzbgzzddp + Ernie Abernathy + MODERATOR + true + false + true + true + HTML5 + + + + xi7y7gpmyq1g + Barrett Kutch + MODERATOR + false + false + true + false + FLASH + + true + #FF0033 + a:focus{color:#0181eb} + + + + srfd2uad4x9s + Peter Parker + VIEWER + false + false + true + true + HTML5 + + + + 6ntb564ibhnq + Bruce Wayne + VIEWER + false + true + false + false + HTML5 + + + + true + b97b512f2c92c0ffe7a3476152525807daa1c676-1524213151782 + 1 + + Best BBB Developers Club + Moodle + + http://bigbluebutton.org/moodle/mod/bigbluebuttonbn/bbb_broker.php?action=recording_ready + + moodle-mod_bigbluebuttonbn (2015080609) + 3.0.2 (Build: 20160111) + + bigbluebutton.org + + Bigbluebutton "Mock meeting for testing getMeetingInfo" + + + + + \ No newline at end of file diff --git a/src/test/resources/fixtures/get_meetings.xml b/src/test/resources/fixtures/get_meetings.xml new file mode 100644 index 0000000..9817f5b --- /dev/null +++ b/src/test/resources/fixtures/get_meetings.xml @@ -0,0 +1,99 @@ + + SUCCESS + + + Prof. Josie Reichert IV + 5cf490a7-2c9a-3571-a48c-134ef58d47c2 + bf32e77309232abb44627ddbb5edd47e0e13e7b8-1554729625768 + 1554729625768 + Mon Apr 08 15:20:25 CET 2019 + 25304 + (985) 807-9923 + =g.TrpDM=xB.oOW5h|m + $is=CM}xF;108o!Jqd + false + 1913 + false + true + false + 1554729625807 + 0 + 0 + 0 + 0 + 0 + 14 + 0 + + + + Alessandra Funk + http://www.schiller.info/ut-perspiciatis-et-vero-dolorum-repellendus-nesciunt-commodi-voluptate + + + false + + + Barbara Schiller + b2e7555d-b7c6-3b9f-b3ae-4c5754f64427 + 8299be7b3bc6693c3b747fe5178a5f7b6e417ac7-1554729632085 + 1554729632085 + Mon Apr 08 15:20:32 CET 2019 + 81776 + 1-971-223-6118 x5746 + SlD;CE + 03_bF+p+Fjm|M3 + false + 2873 + false + false + false + 1554729632096 + 0 + 0 + 0 + 0 + 0 + 25 + 0 + + + + Prof. Maud Corkery II + http://www.hegmann.biz/explicabo-praesentium-labore-dolor + + false + + + Marty Lueilwitz + 56e1ae16-3dfc-390d-b0d8-5aa844a25874 + b97b512f2c92c0ffe7a3476152525807daa1c676-1524213158682 + 1453210075799 + Tue Jan 19 08:27:55 CET 2016 + 49518 + 580.124.3937x93615 + f~kxYJeAV~G?Jb+E:ggn + n:"zWc##Bi.y,d^s,mMF + true + 2206 + true + false + false + 1524213049434 + 0 + 5 + 2 + 1 + 3 + 14 + 1 + + + + Consuelo Gleichner IV + http://www.muller.biz/autem-dolor-aut-nam-doloribus-molestiae + + false + + + \ No newline at end of file diff --git a/src/test/resources/fixtures/get_recording_text_tracks.json b/src/test/resources/fixtures/get_recording_text_tracks.json new file mode 100644 index 0000000..89df7e4 --- /dev/null +++ b/src/test/resources/fixtures/get_recording_text_tracks.json @@ -0,0 +1,28 @@ +{ + "response": { + "returncode": "SUCCESS", + "tracks": [ + { + "href": "http://captions.example.com/foo.json", + "kind": "captions", + "label": "English", + "lang": "en-US", + "source": "live" + }, + { + "href": "http://captions.example.com/foo.json", + "kind": "captions", + "label": "English", + "lang": "en-US", + "source": "live" + }, + { + "href": "http://captions.example.com/foo.json", + "kind": "captions", + "label": "English", + "lang": "en-US", + "source": "live" + } + ] + } +} diff --git a/src/test/resources/fixtures/get_recordings.xml b/src/test/resources/fixtures/get_recordings.xml new file mode 100644 index 0000000..7b945f4 --- /dev/null +++ b/src/test/resources/fixtures/get_recordings.xml @@ -0,0 +1,211 @@ + + SUCCESS + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1462807897120 + 1462812873004 + + + + + + + + + + + + + + + + + podcast + https://test-install.blindsidenetworks.com/podcast/f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120/audio.ogg + + 111 + 632 + 10500 + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120 + + 2973 + 532 + 168019 + + + Welcomehttps://test-install.blindsidenetworks.com/presentation/f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120/presentation/d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1632646357291/thumbnails/thumb-1.png + + Coursehttps://test-install.blindsidenetworks.com/presentation/f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120/presentation/d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1632646357291/thumbnails/thumb-2.png + + + + + + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1463153001071 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1463153001071 + 1463163335375 + + + + + + + + + + + + + + + + + presentation + https://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1463153001071 + + 126 + + + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1463067444315 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1463067444315 + 1463073048933 + + + + + + + + + + + + + + + + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1463067444315 + + 63 + + + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1463413631320 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1463413631320 + 1463419560951 + + + + + + + + + + + + + + + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1463413631320 + + 50 + + + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1462980100026 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1462980100026 + 1462986640649 + + + + + + + + + + + + + + + + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1462980100026 + + 86 + + + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1462894360422 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119[0] + + true + published + 1462894360422 + 1462899112563 + + + + + + + + + + + + + + + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1462894360422 + + 46 + + + + + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_create.xml b/src/test/resources/fixtures/hooks_create.xml new file mode 100644 index 0000000..5e97adf --- /dev/null +++ b/src/test/resources/fixtures/hooks_create.xml @@ -0,0 +1,6 @@ + + SUCCESS + 1 + false + false + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_create_error.xml b/src/test/resources/fixtures/hooks_create_error.xml new file mode 100644 index 0000000..40f5d93 --- /dev/null +++ b/src/test/resources/fixtures/hooks_create_error.xml @@ -0,0 +1,5 @@ + + FAILED + createHookError + An error happened while creating your hook. Check the logs. + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_create_existing.xml b/src/test/resources/fixtures/hooks_create_existing.xml new file mode 100644 index 0000000..62ec976 --- /dev/null +++ b/src/test/resources/fixtures/hooks_create_existing.xml @@ -0,0 +1,6 @@ + + SUCCESS + 1 + duplicateWarning + There is already a hook for this callback URL. + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_create_no_hook_id.xml b/src/test/resources/fixtures/hooks_create_no_hook_id.xml new file mode 100644 index 0000000..297fed8 --- /dev/null +++ b/src/test/resources/fixtures/hooks_create_no_hook_id.xml @@ -0,0 +1,5 @@ + + FAILED + missingParamHookID + You must specify a hookID in the parameters. + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_destroy.xml b/src/test/resources/fixtures/hooks_destroy.xml new file mode 100644 index 0000000..2b488e7 --- /dev/null +++ b/src/test/resources/fixtures/hooks_destroy.xml @@ -0,0 +1,4 @@ + + SUCCESS + true + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_destroy_error.xml b/src/test/resources/fixtures/hooks_destroy_error.xml new file mode 100644 index 0000000..6461637 --- /dev/null +++ b/src/test/resources/fixtures/hooks_destroy_error.xml @@ -0,0 +1,5 @@ + + FAILED + destroyHookError + An error happened while removing your hook. Check the logs. + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_destroy_not_found.xml b/src/test/resources/fixtures/hooks_destroy_not_found.xml new file mode 100644 index 0000000..810b17c --- /dev/null +++ b/src/test/resources/fixtures/hooks_destroy_not_found.xml @@ -0,0 +1,5 @@ + + FAILED + destroyMissingHook + The hook informed was not found. + \ No newline at end of file diff --git a/src/test/resources/fixtures/hooks_list.xml b/src/test/resources/fixtures/hooks_list.xml new file mode 100644 index 0000000..9e8fc9b --- /dev/null +++ b/src/test/resources/fixtures/hooks_list.xml @@ -0,0 +1,18 @@ + + SUCCESS + + + 1 + + + false + false + + + 2 + + false + false + + + \ No newline at end of file diff --git a/src/test/resources/fixtures/insert_document.xml b/src/test/resources/fixtures/insert_document.xml new file mode 100644 index 0000000..97d29a6 --- /dev/null +++ b/src/test/resources/fixtures/insert_document.xml @@ -0,0 +1,4 @@ + + SUCCESS + Presentation is being uploaded + diff --git a/src/test/resources/fixtures/insert_document_presentations.xml b/src/test/resources/fixtures/insert_document_presentations.xml new file mode 100644 index 0000000..7fcdca4 --- /dev/null +++ b/src/test/resources/fixtures/insert_document_presentations.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/src/test/resources/fixtures/is_meeting_running.xml b/src/test/resources/fixtures/is_meeting_running.xml new file mode 100644 index 0000000..9598f72 --- /dev/null +++ b/src/test/resources/fixtures/is_meeting_running.xml @@ -0,0 +1,4 @@ + + SUCCESS + true + diff --git a/src/test/resources/fixtures/join_meeting.xml b/src/test/resources/fixtures/join_meeting.xml new file mode 100644 index 0000000..836a133 --- /dev/null +++ b/src/test/resources/fixtures/join_meeting.xml @@ -0,0 +1,11 @@ + + SUCCESS + successfullyJoined + You have joined successfully. + bec8af173fae4d1f45d8ed6ea7c0b1ffb93af020-1464618265614 + ao6ehbtvbmhz + huzbpgthac7s + rbe7bbkjzx5mnoda + ALLOW + https://bigblubutton-server.sample/client/BigBlueButton.html?sessionToken=BKepJSKk39jtwDC9 + diff --git a/src/test/resources/fixtures/presentation_with_embedded_file.xml b/src/test/resources/fixtures/presentation_with_embedded_file.xml new file mode 100644 index 0000000..9a05a48 --- /dev/null +++ b/src/test/resources/fixtures/presentation_with_embedded_file.xml @@ -0,0 +1,7 @@ + + + + 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 + + + diff --git a/src/test/resources/fixtures/presentation_with_filename.xml b/src/test/resources/fixtures/presentation_with_filename.xml new file mode 100644 index 0000000..cea9572 --- /dev/null +++ b/src/test/resources/fixtures/presentation_with_filename.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/fixtures/presentation_with_url.xml b/src/test/resources/fixtures/presentation_with_url.xml new file mode 100644 index 0000000..9050bd6 --- /dev/null +++ b/src/test/resources/fixtures/presentation_with_url.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/fixtures/publish_recordings.xml b/src/test/resources/fixtures/publish_recordings.xml new file mode 100644 index 0000000..aa97292 --- /dev/null +++ b/src/test/resources/fixtures/publish_recordings.xml @@ -0,0 +1,4 @@ + + SUCCESS + true + diff --git a/src/test/resources/fixtures/put_recording_text_track_success.json b/src/test/resources/fixtures/put_recording_text_track_success.json new file mode 100644 index 0000000..b97735f --- /dev/null +++ b/src/test/resources/fixtures/put_recording_text_track_success.json @@ -0,0 +1,8 @@ +{ + "response": { + "messageKey": "upload_text_track_success", + "message": "Text track uploaded successfully", + "recordId": "baz", + "returncode": "SUCCESS" + } +} diff --git a/src/test/resources/fixtures/update_recordings.xml b/src/test/resources/fixtures/update_recordings.xml new file mode 100644 index 0000000..1852d80 --- /dev/null +++ b/src/test/resources/fixtures/update_recordings.xml @@ -0,0 +1,4 @@ + + SUCCESS + true + diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..96f024d --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,18 @@ + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + +