- build get recordings api response
This commit is contained in:
parent
73b16db384
commit
72c42f9d70
@ -18,4 +18,27 @@ public class Breakout {
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String meetingId;
|
||||
|
||||
public void setParentMeetingId(String parentMeetingId) {
|
||||
this.parentMeetingId = parentMeetingId;
|
||||
}
|
||||
|
||||
public String getParentMeetingId() {
|
||||
return parentMeetingId;
|
||||
}
|
||||
|
||||
public void setSequence(int sequence) {
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public int getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public void setMeetingId(String meetingId) {
|
||||
this.meetingId = meetingId;
|
||||
}
|
||||
|
||||
public String getMeetingId() {
|
||||
return meetingId;
|
||||
}
|
||||
}
|
||||
|
53
bbb-common-web/src/main/java/org/bigbluebutton/api/domain/MeetingInfo.java
Executable file
53
bbb-common-web/src/main/java/org/bigbluebutton/api/domain/MeetingInfo.java
Executable file
@ -0,0 +1,53 @@
|
||||
package org.bigbluebutton.api.domain;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
|
||||
public class MeetingInfo {
|
||||
/**
|
||||
* <meeting id="random-2810069" name="random-2810069" breakout="false"/>
|
||||
*/
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String id;
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String externalId;
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private String name;
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
private boolean breakout;
|
||||
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setExternalId(String externalId) {
|
||||
this.externalId = externalId;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
return externalId;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setBreakout(boolean breakout) {
|
||||
this.breakout = breakout;
|
||||
}
|
||||
|
||||
public boolean isBreakout() {
|
||||
return breakout;
|
||||
}
|
||||
}
|
@ -8,11 +8,11 @@ public class Preview {
|
||||
@JacksonXmlProperty(localName = "image")
|
||||
private Image[] images;
|
||||
|
||||
// public void setImages(Image[] images) {
|
||||
// this.images = images;
|
||||
// }
|
||||
public void setImages(Image[] images) {
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
// public Image[] getImages() {
|
||||
// return images;
|
||||
// }
|
||||
public Image[] getImages() {
|
||||
return images;
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,12 @@ public class RecordingMetadata {
|
||||
@JacksonXmlProperty(localName = "end_time")
|
||||
private String endTime;
|
||||
|
||||
@JacksonXmlProperty(localName = "participants")
|
||||
private int participants;
|
||||
|
||||
@JacksonXmlProperty(localName = "meeting")
|
||||
private MeetingInfo meetingInfo;
|
||||
|
||||
private Breakout breakout;
|
||||
|
||||
@JacksonXmlElementWrapper(localName = "breakoutRooms")
|
||||
@ -98,6 +104,22 @@ public class RecordingMetadata {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setParticipants(int participants) {
|
||||
this.participants = participants;
|
||||
}
|
||||
|
||||
public int getParticipants() {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public void setMeeting(MeetingInfo meetingInfo) {
|
||||
this.meetingInfo = meetingInfo;
|
||||
}
|
||||
|
||||
public MeetingInfo getMeeting() {
|
||||
return meetingInfo;
|
||||
}
|
||||
|
||||
public void setBreakout(Breakout breakout) {
|
||||
this.breakout = breakout;
|
||||
}
|
||||
@ -106,6 +128,14 @@ public class RecordingMetadata {
|
||||
return breakout;
|
||||
}
|
||||
|
||||
public void setBreakoutRooms(BreakoutRoom[] breakoutRooms) {
|
||||
this.breakoutRooms = breakoutRooms;
|
||||
}
|
||||
|
||||
public BreakoutRoom[] getBreakoutRooms() {
|
||||
return breakoutRooms;
|
||||
}
|
||||
|
||||
public void setMeta(Metadata meta) {
|
||||
this.meta = meta;
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
package org.bigbluebutton.api.util;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import org.bigbluebutton.api.domain.RecordingMetadata;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.*;
|
||||
|
||||
public class RecordingMetadataReaderHelper {
|
||||
|
||||
@ -18,4 +22,30 @@ public class RecordingMetadataReaderHelper {
|
||||
br.close();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static RecordingMetadata getRecordingMetadata(File metadataXml) {
|
||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||
|
||||
JacksonXmlModule module = new JacksonXmlModule();
|
||||
// and then configure, for example:
|
||||
module.setDefaultUseWrapper(false);
|
||||
|
||||
XmlMapper mapper = new XmlMapper(module);
|
||||
|
||||
//Reading from xml file and creating XMLStreamReader
|
||||
XMLStreamReader reader = null;
|
||||
RecordingMetadata recMeta = null;
|
||||
try {
|
||||
reader = factory.createXMLStreamReader(new FileInputStream(metadataXml));
|
||||
recMeta = mapper.readValue(reader, RecordingMetadata.class);
|
||||
} catch (XMLStreamException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return recMeta;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import freemarker.template.*;
|
||||
import org.bigbluebutton.api.domain.RecordingMetadata;
|
||||
|
||||
public class ResponseBuilder {
|
||||
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
|
||||
@ -94,4 +95,30 @@ public class ResponseBuilder {
|
||||
|
||||
return xmlText.toString();
|
||||
}
|
||||
|
||||
public String buildGetRecordingsResponse(List<RecordingMetadata> recordings, String returnCode) {
|
||||
|
||||
Template ftl = null;
|
||||
try {
|
||||
ftl = cfg.getTemplate("get-recordings.ftl");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
StringWriter xmlText = new StringWriter();
|
||||
|
||||
Map root = new HashMap();
|
||||
root.put("returnCode", returnCode);
|
||||
root.put("recordings", recordings);
|
||||
|
||||
try {
|
||||
ftl.process(root, xmlText);
|
||||
} catch (TemplateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return xmlText.toString();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
<published>true</published>
|
||||
<start_time>1489173065780</start_time>
|
||||
<end_time>1489173199386</end_time>
|
||||
<participants>10</participants>
|
||||
<meeting id="f3ffe06acedf425565cc024c8ebe89a6552e8782-1489172964374" externalId="random-2810069" name="random-2810069" breakout="false"/>
|
||||
<breakout parentMeetingId="f3ffe06acedf425565cc024c8ebe89a6552e8782-1489172964374" sequence="2" meetingId="f2041d123b6a4b994e7ad87ee9d348496a73472c-1489173065780"/>
|
||||
<breakoutRooms>
|
||||
<breakoutRoom>32ee8bcccfad34f85c58a12f87fc4268130a4fd3-1489173065780</breakoutRoom>
|
||||
|
68
bbb-common-web/src/test/resources/get-recordings.ftl
Executable file
68
bbb-common-web/src/test/resources/get-recordings.ftl
Executable file
@ -0,0 +1,68 @@
|
||||
<#-- GET_RECORDINGS FreeMarker XML template -->
|
||||
<#compress>
|
||||
<response>
|
||||
<#-- Where code is a 'SUCCESS' or 'FAILED' String -->
|
||||
<returncode>${returnCode}</returncode>
|
||||
<recordings>
|
||||
<#list recordings as r>
|
||||
<recording>
|
||||
<recordID>${r.getId()}</recordID>
|
||||
<meetingID>${r.getMeeting().getId()?html}</meetingID>
|
||||
<externalMeetingID>${r.getMeeting().getExternalId()?html}</externalMeetingID>
|
||||
<name><![CDATA[${r.getMeeting().getName()}]]></name>
|
||||
<isBreakout>${r.getMeeting().isBreakout()?c}</isBreakout>
|
||||
<published>${r.getPublished()?string}</published>
|
||||
<state>${r.getState()?string}</state>
|
||||
<startTime><#if r.getStartTime()?? && r.getStartTime() != "">${r.getStartTime()}</#if></startTime>
|
||||
<endTime><#if r.getEndTime()?? && r.getEndTime() != "">${r.getEndTime()}</#if></endTime>
|
||||
<participants><#if r.getParticipants()??>${r.getParticipants()}</#if></participants>
|
||||
<#if r.getBreakout()??>
|
||||
<#assign breakout = r.getBreakout()>
|
||||
<breakout>
|
||||
<parentId>${breakout.getParentMeetingId()}</parentId>
|
||||
<sequence>${breakout.getSequence()?c}</sequence>
|
||||
</breakout>
|
||||
</#if>
|
||||
<#if r.getBreakoutRooms()??>
|
||||
<#list r.getBreakoutRooms()>
|
||||
<breakoutRooms>
|
||||
<#items as broom>
|
||||
<breakoutRoom>${broom.getValue()}</breakoutRoom>
|
||||
</#items>
|
||||
</breakoutRooms>
|
||||
</#list>
|
||||
</#if>
|
||||
<#assign m = r.getMeta().get()>
|
||||
<metadata>
|
||||
<#list m?keys as prop>
|
||||
<${prop}><![CDATA[${m[prop]}]]></${prop}>
|
||||
</#list>
|
||||
</metadata>
|
||||
<#assign pb = r.getPlayback()>
|
||||
<playback>
|
||||
<format>${pb.getFormat()}</format>
|
||||
<link>${pb.getLink()}</link>
|
||||
<processingTime>${pb.getProcessingTime()?c}</processingTime>
|
||||
<duration>${pb.getDuration()?c}</duration>
|
||||
<#if pb.getExtensions()??>
|
||||
<extensions>
|
||||
<#if pb.getExtensions().getPreview()??>
|
||||
<#assign prev = pb.getExtensions().getPreview()>
|
||||
<preview>
|
||||
<#list prev.getImages()>
|
||||
<images>
|
||||
<#items as image>
|
||||
<image width="${image.getWidth()}" height="${image.getHeight()}" alt="${image.getAlt()}">${image.getValue()}</image>
|
||||
</#items>
|
||||
</images>
|
||||
</#list>
|
||||
</preview>
|
||||
</#if>
|
||||
</extensions>
|
||||
</#if>
|
||||
</playback>
|
||||
</recording>
|
||||
</#list>
|
||||
</recordings>
|
||||
</response>
|
||||
</#compress>
|
@ -3,7 +3,7 @@ package org.bigbluebutton.api.util
|
||||
import java.io.File
|
||||
import java.util
|
||||
|
||||
import org.bigbluebutton.api.domain.{Meeting, User}
|
||||
import org.bigbluebutton.api.domain.{Meeting, RecordingMetadata, User}
|
||||
import org.scalatest._
|
||||
|
||||
class ResponseBuilderTest extends UnitSpec {
|
||||
@ -182,4 +182,18 @@ class ResponseBuilderTest extends UnitSpec {
|
||||
|
||||
assert(templateLoc.exists())
|
||||
}
|
||||
|
||||
it should "reply to getRecordings api call" in {
|
||||
val templateLoc = new File("src/test/resources")
|
||||
val builder = new ResponseBuilder(templateLoc)
|
||||
|
||||
val metadataXml = new File("src/test/resources/breakout-room-metadata.xml")
|
||||
val recMeta = RecordingMetadataReaderHelper.getRecordingMetadata(metadataXml);
|
||||
val recList = new util.ArrayList[RecordingMetadata]()
|
||||
recList.add(recMeta)
|
||||
def response = builder.buildGetRecordingsResponse(recList, "success")
|
||||
println(response)
|
||||
|
||||
assert(templateLoc.exists())
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import com.google.gson.Gson
|
||||
import org.bigbluebutton.api.domain.RecordingMetadata
|
||||
import org.bigbluebutton.api.util.ResponseBuilder
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
@ -1735,6 +1736,8 @@ class ApiController {
|
||||
return
|
||||
}
|
||||
|
||||
log.debug request.getQueryString()
|
||||
|
||||
// Do we agree on the checksum? If not, complain.
|
||||
if (! paramsProcessorUtil.isChecksumSame(API_CALL, params.checksum, request.getQueryString())) {
|
||||
errors.checksumError()
|
||||
@ -1764,8 +1767,12 @@ class ApiController {
|
||||
internalRecordIds = paramsProcessorUtil.convertToInternalMeetingId(externalMeetingIds);
|
||||
}
|
||||
|
||||
Map<String,Recording> recs = meetingService.getRecordings(internalRecordIds, states);
|
||||
recs = meetingService.filterRecordingsByMetadata(recs, ParamsProcessorUtil.processMetaParam(params));
|
||||
for(String intRecId : internalRecordIds){
|
||||
log.debug intRecId
|
||||
}
|
||||
|
||||
List<RecordingMetadata> recsList = meetingService.getRecordingsMetadata(internalRecordIds, states);
|
||||
List<RecordingMetadata>recs = meetingService.filterRecordingsByMetadata(recsList, ParamsProcessorUtil.processMetaParam(params));
|
||||
|
||||
if (recs.isEmpty()) {
|
||||
response.addHeader("Cache-Control", "no-cache")
|
||||
@ -1784,20 +1791,13 @@ class ApiController {
|
||||
return;
|
||||
}
|
||||
|
||||
def templateLoc = getServletContext().getRealPath("/WEB-INF/freemarker")
|
||||
ResponseBuilder responseBuilder = new ResponseBuilder(new File(templateLoc))
|
||||
|
||||
|
||||
def cfg = new Configuration()
|
||||
|
||||
// Load the XML template
|
||||
// TODO: Maybe there is a better way to define the templates path
|
||||
def wtl = new WebappTemplateLoader(getServletContext(), "/WEB-INF/freemarker")
|
||||
cfg.setTemplateLoader(wtl)
|
||||
def ftl = cfg.getTemplate("get-recordings.ftl")
|
||||
def xmlText = new StringWriter()
|
||||
ftl.process([code:RESP_CODE_SUCCESS, recs:recs.values()], xmlText)
|
||||
def xmlText = responseBuilder.buildGetRecordingsResponse(recsList, "success")
|
||||
withFormat {
|
||||
xml {
|
||||
render(text: xmlText.toString(), contentType: "text/xml")
|
||||
render(text: xmlText, contentType: "text/xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,8 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.bigbluebutton.api.domain.Meeting;
|
||||
import org.bigbluebutton.api.domain.Playback;
|
||||
import org.bigbluebutton.api.domain.Recording;
|
||||
import org.bigbluebutton.api.domain.User;
|
||||
import org.bigbluebutton.api.domain.UserSession;
|
||||
|
||||
import org.bigbluebutton.api.domain.*;
|
||||
import org.bigbluebutton.api.messaging.MessageListener;
|
||||
import org.bigbluebutton.api.messaging.MessagingService;
|
||||
import org.bigbluebutton.api.messaging.messages.CreateBreakoutRoom;
|
||||
@ -425,18 +422,30 @@ public class MeetingService implements MessageListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<RecordingMetadata> getRecordingsMetadata(List<String> idList, List<String> states) {
|
||||
List<RecordingMetadata> recsList = recordingService.getRecordingsMetadata(idList, states);
|
||||
return recsList;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Recording> getRecordings(List<String> idList, List<String> states) {
|
||||
List<Recording> recsList = recordingService.getRecordings(idList, states);
|
||||
Map<String, Recording> recs = reorderRecordings(recsList);
|
||||
return recs;
|
||||
}
|
||||
|
||||
public Map<String, Recording> filterRecordingsByMetadata(
|
||||
Map<String, Recording> recordings,
|
||||
public List<RecordingMetadata> filterRecordingsByMetadata(List<RecordingMetadata> recsList,
|
||||
Map<String, String> metadataFilters) {
|
||||
return recordingService.filterRecordingsByMetadata(recsList, metadataFilters);
|
||||
}
|
||||
|
||||
public Map<String, Recording> filterRecordingsByMetadata(Map<String, Recording> recordings,
|
||||
Map<String, String> metadataFilters) {
|
||||
return recordingService.filterRecordingsByMetadata(recordings, metadataFilters);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Map<String, Recording> reorderRecordings(List<Recording> olds) {
|
||||
Map<String, Recording> map = new HashMap<String, Recording>();
|
||||
for (Recording r : olds) {
|
||||
|
@ -34,6 +34,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bigbluebutton.api.domain.Recording;
|
||||
import org.bigbluebutton.api.domain.RecordingMetadata;
|
||||
import org.bigbluebutton.api.util.RecordingMetadataReaderHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -64,6 +66,38 @@ public class RecordingService {
|
||||
}
|
||||
}
|
||||
|
||||
public List<RecordingMetadata> getRecordingsMetadata(List<String> recordIDs, List<String> states) {
|
||||
List<RecordingMetadata> recs = new ArrayList<RecordingMetadata>();
|
||||
|
||||
Map<String, List<File>> allDirectories = getAllDirectories(states);
|
||||
if (recordIDs.isEmpty()) {
|
||||
for (Map.Entry<String, List<File>> entry : allDirectories.entrySet()) {
|
||||
recordIDs.addAll(getAllRecordingIds(entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
for (String recordID : recordIDs) {
|
||||
for (Map.Entry<String, List<File>> entry : allDirectories.entrySet()) {
|
||||
List<File> _recs = getRecordingsForPath(recordID, entry.getValue());
|
||||
Iterator<File> iterator = _recs.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RecordingMetadata r = getRecordingMetadata(iterator.next());
|
||||
if (r != null) {
|
||||
recs.add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recs;
|
||||
}
|
||||
|
||||
private RecordingMetadata getRecordingMetadata(File dir) {
|
||||
File file = new File(dir.getPath() + File.separatorChar + "metadata.xml");
|
||||
RecordingMetadata rec = RecordingMetadataReaderHelper.getRecordingMetadata(file);
|
||||
return rec;
|
||||
}
|
||||
|
||||
public List<Recording> getRecordings(List<String> recordIDs, List<String> states) {
|
||||
List<Recording> recs = new ArrayList<Recording>();
|
||||
|
||||
@ -119,6 +153,45 @@ public class RecordingService {
|
||||
return matchesMetadata;
|
||||
}
|
||||
|
||||
public boolean recordingMatchesMetadata(RecordingMetadata recording, Map<String, String> metadataFilters) {
|
||||
boolean matchesMetadata = true;
|
||||
for (Map.Entry<String, String> filter : metadataFilters.entrySet()) {
|
||||
String metadataValue = recording.getMeta().get().get(filter.getKey());
|
||||
if ( metadataValue == null ) {
|
||||
// The recording doesn't have metadata specified
|
||||
matchesMetadata = false;
|
||||
} else {
|
||||
String filterValue = filter.getValue();
|
||||
if( filterValue.charAt(0) == '%' && filterValue.charAt(filterValue.length()-1) == '%' && metadataValue.contains(filterValue.substring(1, filterValue.length()-1)) ){
|
||||
// Filter value embraced by two wild cards
|
||||
// AND the filter value is part of the metadata value
|
||||
} else if( filterValue.charAt(0) == '%' && metadataValue.endsWith(filterValue.substring(1, filterValue.length())) ) {
|
||||
// Filter value starts with a wild cards
|
||||
// AND the filter value ends with the metadata value
|
||||
} else if( filterValue.charAt(filterValue.length()-1) == '%' && metadataValue.startsWith(filterValue.substring(0, filterValue.length()-1)) ) {
|
||||
// Filter value ends with a wild cards
|
||||
// AND the filter value starts with the metadata value
|
||||
} else if( metadataValue.equals(filterValue) ) {
|
||||
// Filter value doesnt have wildcards
|
||||
// AND the filter value is the same as metadata value
|
||||
} else {
|
||||
matchesMetadata = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matchesMetadata;
|
||||
}
|
||||
|
||||
|
||||
public List<RecordingMetadata> filterRecordingsByMetadata(List<RecordingMetadata> recordings, Map<String, String> metadataFilters) {
|
||||
List<RecordingMetadata> resultRecordings = new ArrayList<RecordingMetadata>();
|
||||
for (RecordingMetadata entry : recordings) {
|
||||
if (recordingMatchesMetadata(entry, metadataFilters))
|
||||
resultRecordings.add(entry);
|
||||
}
|
||||
return resultRecordings;
|
||||
}
|
||||
|
||||
public Map<String, Recording> filterRecordingsByMetadata(Map<String, Recording> recordings, Map<String, String> metadataFilters) {
|
||||
Map<String, Recording> resultRecordings = new HashMap<String, Recording>();
|
||||
for (Map.Entry<String, Recording> entry : recordings.entrySet()) {
|
||||
|
84
bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl
Normal file → Executable file
84
bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl
Normal file → Executable file
@ -2,61 +2,63 @@
|
||||
<#compress>
|
||||
<response>
|
||||
<#-- Where code is a 'SUCCESS' or 'FAILED' String -->
|
||||
<returncode>${code}</returncode>
|
||||
<returncode>${returnCode}</returncode>
|
||||
<recordings>
|
||||
<#-- Where recs is a String -> Recording HashMap -->
|
||||
<#list recs as r>
|
||||
<#list recordings as r>
|
||||
<recording>
|
||||
<recordID>${r.getId()}</recordID>
|
||||
<meetingID><#if r.getMeetingID()?? && r.getMeetingID() != "">${r.getMeetingID()?html}</#if></meetingID>
|
||||
<name><#if r.getName()?? && r.getName() != ""><![CDATA[${r.getName()}]]></#if></name>
|
||||
<published>${r.isPublished()?string}</published>
|
||||
<meetingID>${r.getMeeting().getId()?html}</meetingID>
|
||||
<externalMeetingID>${r.getMeeting().getExternalId()?html}</externalMeetingID>
|
||||
<name><![CDATA[${r.getMeeting().getName()}]]></name>
|
||||
<isBreakout>${r.getMeeting().isBreakout()?c}</isBreakout>
|
||||
<published>${r.getPublished()?string}</published>
|
||||
<state>${r.getState()?string}</state>
|
||||
<startTime><#if r.getStartTime()?? && r.getStartTime() != "">${r.getStartTime()}</#if></startTime>
|
||||
<endTime><#if r.getEndTime()?? && r.getEndTime() != "">${r.getEndTime()}</#if></endTime>
|
||||
<participants><#if r.getNumParticipants()??>${r.getNumParticipants()}</#if></participants>
|
||||
<#assign m = r.getMetadata()>
|
||||
<participants><#if r.getParticipants()??>${r.getParticipants()}</#if></participants>
|
||||
<#if r.getBreakout()??>
|
||||
<#assign breakout = r.getBreakout()>
|
||||
<breakout>
|
||||
<parentId>${breakout.getParentMeetingId()}</parentId>
|
||||
<sequence>${breakout.getSequence()?c}</sequence>
|
||||
</breakout>
|
||||
</#if>
|
||||
<#if r.getBreakoutRooms()??>
|
||||
<#list r.getBreakoutRooms()>
|
||||
<breakoutRooms>
|
||||
<#items as broom>
|
||||
<breakoutRoom>${broom.getValue()}</breakoutRoom>
|
||||
</#items>
|
||||
</breakoutRooms>
|
||||
</#list>
|
||||
</#if>
|
||||
<#assign m = r.getMeta().get()>
|
||||
<metadata>
|
||||
<#list m?keys as prop>
|
||||
<${prop}><![CDATA[${m[prop]}]]></${prop}>
|
||||
</#list>
|
||||
</metadata>
|
||||
<#assign pb = r.getPlayback()>
|
||||
<playback>
|
||||
<#if r.getPlaybacks()??>
|
||||
<#list r.getPlaybacks() as p>
|
||||
<#if p?? && p.getFormat()??>
|
||||
<format>
|
||||
<type>${p.getFormat()}</type>
|
||||
<url>${p.getUrl()}</url>
|
||||
<length>${p.getLength()}</length>
|
||||
<#if p.getExtensions()??>
|
||||
<#list p.getExtensions() as extension>
|
||||
<${extension.getType()}>
|
||||
<#assign properties = extension.getProperties()>
|
||||
<#if extension.getType() == "preview">
|
||||
<#list properties?keys as property>
|
||||
<#if property == "images">
|
||||
<${property}>
|
||||
<#if properties[property]["image"]?? && properties[property]["image"]?is_hash>
|
||||
<#assign image = properties[property]["image"]>
|
||||
<image <#if image["attributes"]?? && image["attributes"]["width"]??>width="${image["attributes"]["width"]}"</#if> <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}"</#if> <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="<#escape x as x?xml>${image["attributes"]["alt"]}</#escape>"</#if>>${image["text"]}</image>
|
||||
<#elseif properties[property]["image"]?? && properties[property]["image"]?is_enumerable>
|
||||
<#list properties[property]["image"] as image>
|
||||
<image <#if image["attributes"]?? && image["attributes"]["width"]??>width="${image["attributes"]["width"]}"</#if> <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}"</#if> <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="<#escape x as x?xml>${image["attributes"]["alt"]}</#escape>"</#if>>${image["text"]}</image>
|
||||
<format>${pb.getFormat()}</format>
|
||||
<link>${pb.getLink()}</link>
|
||||
<processingTime>${pb.getProcessingTime()?c}</processingTime>
|
||||
<duration>${pb.getDuration()?c}</duration>
|
||||
<#if pb.getExtensions()??>
|
||||
<extensions>
|
||||
<#if pb.getExtensions().getPreview()??>
|
||||
<#assign prev = pb.getExtensions().getPreview()>
|
||||
<preview>
|
||||
<#list prev.getImages()>
|
||||
<images>
|
||||
<#items as image>
|
||||
<image width="${image.getWidth()}" height="${image.getHeight()}" alt="${image.getAlt()}">${image.getValue()}</image>
|
||||
</#items>
|
||||
</images>
|
||||
</#list>
|
||||
</preview>
|
||||
</#if>
|
||||
</${property}>
|
||||
<#else>
|
||||
<${property} />
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
</${extension.getType()}>
|
||||
</#list>
|
||||
</#if>
|
||||
</format>
|
||||
</#if>
|
||||
</#list>
|
||||
</extensions>
|
||||
</#if>
|
||||
</playback>
|
||||
</recording>
|
||||
|
@ -191,6 +191,8 @@ module BigBlueButton
|
||||
MODULE = 'module'
|
||||
EVENTNAME = 'eventName'
|
||||
MEETINGID = 'meetingId'
|
||||
MEETINGNAME = 'meetingName'
|
||||
ISBREAKOUT = 'isBreakout'
|
||||
|
||||
def initialize(redis)
|
||||
@redis = redis
|
||||
@ -206,6 +208,7 @@ module BigBlueButton
|
||||
|
||||
if (meeting_metadata != nil)
|
||||
xml.recording(:meeting_id => meeting_id, :bbb_version => version) {
|
||||
xml.meeting(:id => meeting_id, :externalId => meeting_metadata[MEETINGID], :name => meeting_metadata[MEETINGNAME], :breakout => meeting_metadata[ISBREAKOUT])
|
||||
xml.metadata(meeting_metadata)
|
||||
|
||||
if (@redis.has_breakout_metadata_for(meeting_id))
|
||||
|
@ -109,10 +109,15 @@ if not FileTest.directory?(target_dir)
|
||||
end_time = recording.at_xpath("end_time")
|
||||
end_time.content = real_end_time
|
||||
|
||||
if (meeting_xpath != nil)
|
||||
recording << meeting_xpath
|
||||
end
|
||||
|
||||
## Copy the breakout and breakout rooms node from
|
||||
## events.xml if present.
|
||||
breakout_xpath = @doc.xpath("//breakout")
|
||||
breakout_rooms_xpath = @doc.xpath("//breakoutRooms")
|
||||
meeting_xpath = @doc.xpath("//meeting")
|
||||
|
||||
if (breakout_xpath != nil)
|
||||
recording << breakout_xpath
|
||||
|
Loading…
Reference in New Issue
Block a user