Skip to content

Commit

Permalink
Mailchimp upsert contacts/update tags in batch
Browse files Browse the repository at this point in the history
  • Loading branch information
VSydor authored and brmeyer committed Jul 13, 2023
1 parent c5a991a commit f355223
Show file tree
Hide file tree
Showing 2 changed files with 328 additions and 19 deletions.
131 changes: 130 additions & 1 deletion src/main/java/com/impactupgrade/nucleus/client/MailchimpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import com.ecwid.maleorang.MailchimpException;
import com.ecwid.maleorang.MailchimpObject;
import com.ecwid.maleorang.method.v3_0.batches.BatchStatus;
import com.ecwid.maleorang.method.v3_0.batches.GetBatchStatusMethod;
import com.ecwid.maleorang.method.v3_0.batches.StartBatchMethod;
import com.ecwid.maleorang.method.v3_0.lists.members.DeleteMemberMethod;
import com.ecwid.maleorang.method.v3_0.lists.members.EditMemberMethod;
import com.ecwid.maleorang.method.v3_0.lists.members.GetMemberMethod;
Expand All @@ -14,15 +17,20 @@
import com.ecwid.maleorang.method.v3_0.lists.merge_fields.EditMergeFieldMethod;
import com.ecwid.maleorang.method.v3_0.lists.merge_fields.GetMergeFieldsMethod;
import com.ecwid.maleorang.method.v3_0.lists.merge_fields.MergeFieldInfo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -80,6 +88,28 @@ public void upsertContact(String listId, MemberInfo contact) throws IOException,
}
}

public String upsertContactsBatch(String listId, List<MemberInfo> contacts) throws IOException, MailchimpException {
List<EditMemberMethod.CreateOrUpdate> upsertMemberMethods = contacts.stream()
.map(contact -> {
EditMemberMethod.CreateOrUpdate upsertMemberMethod = new EditMemberMethod.CreateOrUpdate(listId, contact.email_address);
upsertMemberMethod.status_if_new = contact.status;
upsertMemberMethod.mapping.putAll(contact.mapping);
upsertMemberMethod.merge_fields.mapping.putAll(contact.merge_fields.mapping);
upsertMemberMethod.interests.mapping.putAll(contact.interests.mapping);
upsertMemberMethod.tags = contact.tags;
return upsertMemberMethod;
})
.collect(Collectors.toList());

StartBatchMethod startBatchMethod = new StartBatchMethod(upsertMemberMethods);
BatchStatus batchStatus = client.execute(startBatchMethod);
return batchStatus.id;
}

public List<MemberInfo> getListMembers(String listId) throws IOException, MailchimpException {
return getListMembers(listId, null, null);
}

// public List<MemberInfo> getListMembers(String listId, String status) throws IOException, MailchimpException {
// return getListMembers(listId, status, null);
// }
Expand All @@ -96,7 +126,7 @@ public List<MemberInfo> getListMembers(String listId, String status, Calendar si
}
GetMembersMethod.Response getMemberResponse = client.execute(getMembersMethod);
List<MemberInfo> members = new ArrayList<>(getMemberResponse.members);
while(getMemberResponse.total_items > members.size()) {
while (getMemberResponse.total_items > members.size()) {
getMembersMethod.offset = members.size();
log.info("retrieving list {} contacts (offset {} of total {})", listId, getMembersMethod.offset, getMemberResponse.total_items);
getMemberResponse = client.execute(getMembersMethod);
Expand All @@ -119,6 +149,16 @@ public void archiveContact(String listId, String email) throws IOException, Mail
}
}

public String archiveContactsBatch(String listId, List<String> emails) throws IOException, MailchimpException {
List<DeleteMemberMethod> deleteMemberMethods = emails.stream()
.map(email -> new DeleteMemberMethod(listId, email))
.collect(Collectors.toList());

StartBatchMethod startBatchMethod = new StartBatchMethod(deleteMemberMethods);
BatchStatus batchStatus = client.execute(startBatchMethod);
return batchStatus.id;
}

// TODO: TEST THIS
public Set<String> getContactGroupIds(String listId, String contactEmail) throws IOException, MailchimpException {
MemberInfo contact = getContactInfo(listId, contactEmail);
Expand All @@ -131,6 +171,18 @@ public List<String> getContactTags(String listId, String contactEmail) throws IO
return tags.stream().map(t -> t.mapping.get(TAG_NAME).toString()).collect(Collectors.toList());
}

public Map<String, List<String>> getContactsTags(String listId) throws IOException, MailchimpException {
List<MemberInfo> memberInfos = getListMembers(listId);
Map<String, List<String>> tagsMap = memberInfos.stream()
.collect(Collectors.toMap(
memberInfo -> memberInfo.email_address, memberInfo -> {
List<MailchimpObject> tags = (List<MailchimpObject>) memberInfo.mapping.get(TAGS);
return tags.stream().map(t -> t.mapping.get(TAG_NAME).toString()).collect(Collectors.toList());
}
));
return tagsMap;
}

public void updateContactTags(String listId, String contactEmail, List<String> activeTags, List<String> inactiveTags) throws IOException, MailchimpException {
ArrayList<MailchimpObject> tags = new ArrayList<>();
for (String activeTag : activeTags) {
Expand All @@ -151,6 +203,46 @@ public void updateContactTags(String listId, String contactEmail, List<String> a
client.execute(editMemberMethod);
}

public String updateContactTagsBatch(String listId, List<EmailContact> emailContacts) throws IOException, MailchimpException {
List<EditMemberMethod.AddorRemoveTag> editMemberMethods =
emailContacts.stream()
.map(emailContact -> {
List<String> active = emailContact.activeTags;
List<String> inactive = emailContact.inactiveTags;
ArrayList<MailchimpObject> tags = new ArrayList<>();
if (CollectionUtils.isNotEmpty(active)) {
for (String activeTag : active) {
MailchimpObject tag = new MailchimpObject();
tag.mapping.put(TAG_STATUS, TAG_ACTIVE);
tag.mapping.put(TAG_NAME, activeTag);
tags.add(tag);
}
}
if (CollectionUtils.isNotEmpty(inactive)) {
for (String inactiveTag : inactive) {
MailchimpObject tag = new MailchimpObject();
tag.mapping.put(TAG_STATUS, TAG_INACTIVE);
tag.mapping.put(TAG_NAME, inactiveTag);
tags.add(tag);
}
}

EditMemberMethod.AddorRemoveTag editMemberMethod = new EditMemberMethod.AddorRemoveTag(listId, emailContact.email);
editMemberMethod.tags = tags;

return editMemberMethod;
}).collect(Collectors.toList());

StartBatchMethod startBatchMethod = new StartBatchMethod(editMemberMethods);
BatchStatus batchStatus = client.execute(startBatchMethod);
return batchStatus.id;
}

public BatchStatus getBatchStatus(String batchStatusId) throws IOException, MailchimpException {
GetBatchStatusMethod getBatchStatusMethod = new GetBatchStatusMethod(batchStatusId);
return client.execute(getBatchStatusMethod);
}

public List<MergeFieldInfo> getMergeFields(String listId) throws IOException, MailchimpException {
GetMergeFieldsMethod getMergeFields = new GetMergeFieldsMethod(listId);
getMergeFields.count = 1000; // the max
Expand All @@ -174,4 +266,41 @@ public String exceptionToString(MailchimpException e) {
}
return description;
}

public record EmailContact(String email, List<String> activeTags, List<String> inactiveTags) {};

@JsonIgnoreProperties(ignoreUnknown = true)
public static final class BatchOperation {
@JsonProperty("status_code")
public Integer status;
@JsonProperty("operation_id")
public String operationId;
public BatchOperationResponse response;
}

@JsonIgnoreProperties(ignoreUnknown = true)
public static final class BatchOperationResponse {
public String id;
@JsonProperty("merge_fields")
public Map<String, Object> mergeFields;
@JsonProperty("contact_id")
public String contactId;
@JsonProperty("email_address")
public String email;
@JsonProperty("full_name")
public String fullName;
@JsonProperty("tags_count")
public Integer tagsCount;
@JsonProperty("last_changed")
public Date lastChangedAt;
@JsonProperty("list_id")
public String listId;

// error response fields
public String instance;
public String detail;
public String type;
public String title;
public String status;
}
}
Loading

0 comments on commit f355223

Please sign in to comment.