Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions docs/content/docs/reference/components/google-meet_v1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -177,28 +177,32 @@ Name: listParticipants



Type: OBJECT
Type: ARRAY


#### Properties
Items Type: OBJECT


#### Properties
| Name | Type | Description |
|:------------:|:------------:|:-------------------:|
| participants | ARRAY <details> <summary> Items </summary> [&#123;STRING\(name), &#123;&#125;\(user), STRING\(earliestStartTime), STRING\(latestEndTime)&#125;] </details> | List of participants in one page. |
| name | STRING | Resource name of the participant.Format: conferenceRecords/&#123;conferenceRecord&#125;/participants/&#123;participant&#125; |
| user | OBJECT <details> <summary> Properties </summary> &#123;&#125; </details> | User can be of type: signedinUser, anonymousUser, phoneUser |
| earliestStartTime | STRING | Time when the participant first joined the meeting. |
| latestEndTime | STRING | Time when the participant left the meeting for the last time. This can be null if it's an active meeting. |





#### Output Example
```json
{
"participants" : [ {
"name" : "",
"user" : { },
"earliestStartTime" : "",
"latestEndTime" : ""
} ]
}
[ {
"name" : "",
"user" : { },
"earliestStartTime" : "",
"latestEndTime" : ""
} ]
```


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,24 @@
import static com.bytechef.component.definition.Context.Http.responseType;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.CONFERENCE_RECORDS;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.NAME;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.NEXT_PAGE_TOKEN;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_SIZE;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_TOKEN;

import com.bytechef.component.definition.ActionDefinition.OptionsFunction;
import com.bytechef.component.definition.Context;
import com.bytechef.component.definition.Context.Http;
import com.bytechef.component.definition.Parameters;
import com.bytechef.component.definition.TypeReference;
import com.bytechef.component.google.meet.util.GoogleMeetUtils;
import com.bytechef.google.commons.GoogleUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* @author Marija Horvat
* @author Monika Kušter
*/
public class GoogleMeetListParticipantsAction {

Expand All @@ -50,38 +58,50 @@ public class GoogleMeetListParticipantsAction {
.required(true))
.output(
outputSchema(
object()
.properties(
array("participants")
.description("List of participants in one page.")
.items(
object()
.properties(
string(NAME)
.description(
"Resource name of the participant.Format: " +
"conferenceRecords/{conferenceRecord}/participants/{participant}"),
object("user")
.description("User can be of type: signedinUser, anonymousUser, phoneUser"),
string("earliestStartTime")
.description("Time when the participant first joined the meeting."),
string("latestEndTime")
.description(
"Time when the participant left the meeting for the last time. This " +
"can be null if it's an active meeting."))))))
array()
.description("List of participants.")
.items(
object()
.properties(
string(NAME)
.description(
"Resource name of the participant.Format: " +
"conferenceRecords/{conferenceRecord}/participants/{participant}"),
object("user")
.description("User can be of type: signedinUser, anonymousUser, phoneUser"),
string("earliestStartTime")
.description("Time when the participant first joined the meeting."),
string("latestEndTime")
.description(
"Time when the participant left the meeting for the last time. This " +
"can be null if it's an active meeting.")))))
.perform(GoogleMeetListParticipantsAction::perform)
.processErrorResponse(GoogleUtils::processErrorResponse);

private GoogleMeetListParticipantsAction() {
}

public static Object perform(Parameters inputParameters, Parameters connectionParameters, Context context) {
return context
.http(http -> http.get(
"https://meet.googleapis.com/v2/%s/participants".formatted(
inputParameters.getRequiredString(CONFERENCE_RECORDS))))
.configuration(responseType(Http.ResponseType.JSON))
.execute()
.getBody();
public static List<?> perform(Parameters inputParameters, Parameters connectionParameters, Context context) {
List<Object> participants = new ArrayList<>();
String nextPageToken = null;

do {
Map<String, ?> body = context
.http(http -> http.get(
"https://meet.googleapis.com/v2/%s/participants".formatted(
inputParameters.getRequiredString(CONFERENCE_RECORDS))))
.queryParameters(PAGE_SIZE, 250, PAGE_TOKEN, nextPageToken)
.configuration(responseType(Http.ResponseType.JSON))
.execute()
.getBody(new TypeReference<>() {});

if (body.get("participants") instanceof List<?> list) {
participants.addAll(list);
}

nextPageToken = (String) body.get(NEXT_PAGE_TOKEN);
} while (nextPageToken != null);

return participants;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public class GoogleMeetConstants {
public static final String ACCESS_TYPE = "accessType";
public static final String CONFERENCE_RECORDS = "conferenceRecords";
public static final String NAME = "name";
public static final String NEXT_PAGE_TOKEN = "nextPageToken";
public static final String PAGE_SIZE = "pageSize";
public static final String PAGE_TOKEN = "pageToken";

public static final ModifiableObjectProperty MEETING_SPACE_OUTPUT_PROPERTY =
object()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import static com.bytechef.component.definition.ComponentDsl.option;
import static com.bytechef.component.definition.Context.Http.responseType;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.NEXT_PAGE_TOKEN;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_SIZE;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_TOKEN;

import com.bytechef.component.definition.Context;
import com.bytechef.component.definition.Context.Http;
Expand All @@ -30,30 +33,37 @@

/**
* @author Marija Horvat
* @author Monika Kušter
*/
public class GoogleMeetUtils {

public static List<Option<String>> getConferenceRecordsOptions(
Parameters inputParameters, Parameters connectionParameters, Map<String, String> dependencyPaths,
String searchText, Context context) {

Map<String, ?> body = context
.http(http -> http.get("https://meet.googleapis.com/v2/conferenceRecords"))
.configuration(responseType(Http.ResponseType.JSON))
.execute()
.getBody(new TypeReference<>() {});

List<Option<String>> options = new ArrayList<>();
String nextPageToken = null;

do {
Map<String, ?> body = context
.http(http -> http.get("https://meet.googleapis.com/v2/conferenceRecords"))
.queryParameters(PAGE_SIZE, 100, PAGE_TOKEN, nextPageToken)
.configuration(responseType(Http.ResponseType.JSON))
.execute()
.getBody(new TypeReference<>() {});

if (body.get("conferenceRecords") instanceof List<?> list) {
for (Object object : list) {
if (object instanceof Map<?, ?> map) {
String name = (String) map.get("name");
if (body.get("conferenceRecords") instanceof List<?> list) {
for (Object object : list) {
if (object instanceof Map<?, ?> map) {
String name = (String) map.get("name");

options.add(option(name.substring("conferenceRecords/".length()), name));
options.add(option(name.substring("conferenceRecords/".length()), name));
}
}
}
}

nextPageToken = (String) body.get(NEXT_PAGE_TOKEN);
} while (nextPageToken != null);

return options;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,103 @@

import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.CONFERENCE_RECORDS;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.NAME;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.NEXT_PAGE_TOKEN;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_SIZE;
import static com.bytechef.component.google.meet.constant.GoogleMeetConstants.PAGE_TOKEN;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentCaptor.forClass;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.bytechef.component.definition.Context;
import com.bytechef.component.definition.Context.ContextFunction;
import com.bytechef.component.definition.Context.Http;
import com.bytechef.component.definition.Context.Http.Configuration;
import com.bytechef.component.definition.Parameters;
import com.bytechef.component.definition.TypeReference;
import com.bytechef.component.test.definition.MockParametersFactory;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

/**
* @author Marija Horvat
* @author Monika Kušter
*/
class GoogleMeetListParticipantsActionTest {

private final ArgumentCaptor<Configuration.ConfigurationBuilder> configurationBuilderArgumentCaptor =
forClass(Configuration.ConfigurationBuilder.class);
@SuppressWarnings("unchecked")
private final ArgumentCaptor<ContextFunction<Http, Http.Executor>> httpFunctionArgumentCaptor =
forClass(ContextFunction.class);
private final Context mockedContext = mock(Context.class);
private final Http.Executor mockedExecutor = mock(Http.Executor.class);
private final Http mockedHttp = mock(Http.class);
private final Parameters mockedParameters = MockParametersFactory.create(Map.of(CONFERENCE_RECORDS, "test"));
private final Http.Response mockedResponse = mock(Http.Response.class);
private final Map<String, Object> responseMap = Map.of(
NAME, "test", "user", "test",
"earliestStartTime", "2025-10-04T10:00:00", "latestEndTime", "2025-10-04T12:00:00");
private final ArgumentCaptor<Object[]> objectsArgumentCaptor = forClass(Object[].class);
private final ArgumentCaptor<String> stringArgumentCaptor = forClass(String.class);

@Test
void testPerform() {
when(mockedContext.http(any()))
when(mockedContext.http(httpFunctionArgumentCaptor.capture()))
.thenAnswer(inv -> {
ContextFunction<Http, Http.Executor> value = httpFunctionArgumentCaptor.getValue();

return value.apply(mockedHttp);
});
when(mockedHttp.get(stringArgumentCaptor.capture()))
.thenReturn(mockedExecutor);
when(mockedExecutor.queryParameters(objectsArgumentCaptor.capture()))
.thenReturn(mockedExecutor);
when(mockedExecutor.configuration(any()))
when(mockedExecutor.configuration(configurationBuilderArgumentCaptor.capture()))
.thenReturn(mockedExecutor);
when(mockedExecutor.execute())
.thenReturn(mockedResponse);
when(mockedResponse.getBody())
.thenReturn(responseMap);
when(mockedResponse.getBody(any(TypeReference.class)))
.thenReturn(
Map.of("participants", List.of(Map.of(NAME, "first")), NEXT_PAGE_TOKEN, "t1"),
Map.of("participants", List.of(Map.of(NAME, "second"))));

Object result = GoogleMeetListParticipantsAction.perform(mockedParameters, mockedParameters, mockedContext);

assertEquals(responseMap, result);
assertEquals(List.of(Map.of(NAME, "first"), Map.of(NAME, "second")), result);

ContextFunction<Http, Http.Executor> capturedFunction = httpFunctionArgumentCaptor.getValue();

assertNotNull(capturedFunction);

Configuration.ConfigurationBuilder configurationBuilder = configurationBuilderArgumentCaptor.getValue();

Configuration configuration = configurationBuilder.build();

Http.ResponseType responseType = configuration.getResponseType();

assertEquals(Http.ResponseType.Type.JSON, responseType.getType());
assertEquals(
List.of(
"https://meet.googleapis.com/v2/test/participants", "https://meet.googleapis.com/v2/test/participants"),
stringArgumentCaptor.getAllValues());

List<Object[]> allQueryParams = objectsArgumentCaptor.getAllValues();

assertEquals(2, allQueryParams.size());

Object[] queryParameters1 = {
PAGE_SIZE, 250,
PAGE_TOKEN, null
};
Object[] queryParameters2 = {
PAGE_SIZE, 250,
PAGE_TOKEN, "t1"
};

assertArrayEquals(queryParameters1, allQueryParams.get(0));
assertArrayEquals(queryParameters2, allQueryParams.get(1));
}
}
Loading