diff --git a/src/main/java/org/embulk/input/google_ads/GoogleAdsReporter.java b/src/main/java/org/embulk/input/google_ads/GoogleAdsReporter.java index 10b252b..df2e40d 100644 --- a/src/main/java/org/embulk/input/google_ads/GoogleAdsReporter.java +++ b/src/main/java/org/embulk/input/google_ads/GoogleAdsReporter.java @@ -7,9 +7,14 @@ import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.ads.googleads.lib.GoogleAdsClient; +import com.google.ads.googleads.v16.resources.CustomerName; +import com.google.ads.googleads.v16.services.CustomerServiceClient; import com.google.ads.googleads.v16.services.GoogleAdsRow; import com.google.ads.googleads.v16.services.GoogleAdsServiceClient; +import com.google.ads.googleads.v16.services.ListAccessibleCustomersRequest; import com.google.ads.googleads.v16.services.SearchGoogleAdsRequest; +import com.google.ads.googleads.v16.services.SearchGoogleAdsStreamRequest; +import com.google.ads.googleads.v16.services.SearchGoogleAdsStreamResponse; import com.google.auth.oauth2.UserCredentials; import com.google.common.base.CaseFormat; import com.google.protobuf.Descriptors; @@ -23,6 +28,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,10 +42,8 @@ public class GoogleAdsReporter private final Logger logger = LoggerFactory.getLogger(GoogleAdsReporter.class); private final PluginTask task; private final UserCredentials credentials; + private final ObjectMapper mapper = new ObjectMapper(); private GoogleAdsClient client; - private ObjectMapper mapper = new ObjectMapper(); - - private Iterable searchResult; public GoogleAdsReporter(PluginTask task) { @@ -60,7 +64,7 @@ private Iterable search(Map p String query = buildQuery(task, params); logger.info(query); SearchGoogleAdsRequest request = buildRequest(task, query); - GoogleAdsServiceClient googleAdsService = client.getVersion16().createGoogleAdsServiceClient(); + GoogleAdsServiceClient googleAdsService = client.getLatestVersion().createGoogleAdsServiceClient(); GoogleAdsServiceClient.SearchPagedResponse response = googleAdsService.search(request); return response.iteratePages(); } @@ -280,14 +284,77 @@ public List buildWhereClauseConditions(PluginTask task, Map getLoginCustomerId(task.getCustomerId()))); + } + + private Long getLoginCustomerId(String customerId) + { + List loginCustomerIds = getLoginCustomerIds(customerId); + if (loginCustomerIds.isEmpty()) { + throw new RuntimeException("login customer not found [customer id: " + customerId + "]"); + } + if (loginCustomerIds.size() > 1) { + logger.info("multiple login customers found [login customer ids: {}]", loginCustomerIds.stream().map(Object::toString).collect(Collectors.joining(", "))); + } + Long loginCustomerId = loginCustomerIds.get(0); + logger.info("use this customer [customer id: {}, login customer id: {}] to login", customerId, loginCustomerId); + return loginCustomerId; + } + + private List getLoginCustomerIds(String customerId) + { + try (CustomerServiceClient client = buildClient(null).getLatestVersion().createCustomerServiceClient()) { + return client.listAccessibleCustomers(ListAccessibleCustomersRequest.newBuilder().build()) + .getResourceNamesList() + .stream() + .map(CustomerName::parse) + .map(CustomerName::getCustomerId) + .map(this::getLoginCustomerClients) + .flatMap(Collection::stream) + .filter(loginCustomerClient -> loginCustomerClient.customerClientId.equals(customerId)) + .map(loginCustomerClient -> Long.valueOf(loginCustomerClient.loginCustomerId)) + .collect(Collectors.toList()); + } + } + + private List getLoginCustomerClients(String customerId) + { + try (GoogleAdsServiceClient client = buildClient(Long.valueOf(customerId)).getLatestVersion().createGoogleAdsServiceClient()) { + return client.searchStreamCallable().call(SearchGoogleAdsStreamRequest.newBuilder() + .setCustomerId(customerId) + .setQuery("SELECT customer_client.id FROM customer_client") + .build()) + .stream() + .map(SearchGoogleAdsStreamResponse::getResultsList) + .flatMap(Collection::stream) + .map(GoogleAdsRow::getCustomerClient) + .map(customerClient -> new LoginCustomerClient(customerId, customerClient.getId())) + .collect(Collectors.toList()); + } + } + + private static class LoginCustomerClient + { + LoginCustomerClient(String loginCustomerId, Long customerClientId) + { + this.loginCustomerId = loginCustomerId; + this.customerClientId = String.valueOf(customerClientId); + } + + final String loginCustomerId; + final String customerClientId; + } + + private GoogleAdsClient buildClient(Long loginCustomerId) { GoogleAdsClient.Builder builder = GoogleAdsClient.newBuilder() .setDeveloperToken(task.getDeveloperToken()) .setCredentials(credentials); - if (task.getLoginCustomerId().isPresent()) { - builder.setLoginCustomerId(Long.parseLong(task.getLoginCustomerId().get())); + if (loginCustomerId != null) { + builder.setLoginCustomerId(loginCustomerId); } - this.client = builder.build(); + return builder.build(); } private String buildWhereClauseConditionsForChangeEvent(String startDateTime) diff --git a/src/main/java/org/embulk/input/google_ads/PluginTask.java b/src/main/java/org/embulk/input/google_ads/PluginTask.java index ced63a8..bad94d8 100644 --- a/src/main/java/org/embulk/input/google_ads/PluginTask.java +++ b/src/main/java/org/embulk/input/google_ads/PluginTask.java @@ -15,7 +15,7 @@ public interface PluginTask extends Task @Config("login_customer_id") @ConfigDefault("null") - Optional getLoginCustomerId(); + Optional getLoginCustomerId(); @Config("client_id") String getClientId();