GithubHelp home page GithubHelp logo

intercom / intercom-java Goto Github PK

View Code? Open in Web Editor NEW
61.0 181.0 69.0 643 KB

Java bindings for the Intercom API

Home Page: https://developers.intercom.io/reference

License: Apache License 2.0

Java 100.00%

intercom-java's Introduction

intercom-java

Circle CI Maven Central Intercom API Version

Java bindings for the Intercom API

Project Updates

Retirement of Bintray/JCenter

This project was previously publishing releases to JCenter, which is being retired by JFrog on May 1st 2021.

To allow continued access to past versions, we've migrated them to Maven Central.

Maintenance

We're currently building a new team to provide in-depth and dedicated SDK support.

In the meantime, we'll be operating on limited capacity, meaning all pull requests will be evaluated on a best effort basis and will be limited to critical issues.

We'll communicate all relevant updates as we build this new team and support strategy in the coming months.

Add a dependency

The distribution is hosted on mavenCentral. To use the client, you can add the mavenCentral repository to your dependencies.

Maven

Add the project declaration to your pom.xml:

<dependency>
  <groupId>io.intercom</groupId>
  <artifactId>intercom-java</artifactId>
  <version>2.8.2</version>
</dependency>

Gradle

Add mavenCentral to your repositories block:

repositories {
 mavenCentral()
}

and add the project to the dependencies block in your build.gradle:

dependencies {
  implementation 'io.intercom:intercom-java:2.8.2'
}  

SBT

Add mavenCentral to your resolvers in your build.sbt:

resolvers += "mavenCentral" at "https://repo1.maven.org/maven2"

and add the project to your libraryDependencies in your build.sbt:

libraryDependencies += "io.intercom" % "intercom-java" % "2.8.2"

Resources

Resources this API supports:

Authorization

If you already have an access token you can find it here. If you want to create or learn more about access tokens then you can find more info here.

# With an OAuth or Access token:
Intercom.setToken("da39a3ee5e6b4b0d3255bfef95601890afd80709");

If you are building a third party application you can get your OAuth token by setting-up-oauth for Intercom.

Usage

Users

// Create a user
User user = new User()
    .setEmail("[email protected]")
    .setUserId("1")
    .addCustomAttribute(CustomAttribute.newStringAttribute("role", "sergeant"))
    .addCustomAttribute(CustomAttribute.newBooleanAttribute("browncoat", true));
User created = User.create(user);

// Find user by id
user = User.find("541a144b201ebf2ec5000001");

// Find user by email
Map<String, String> params = Maps.newHashMap();
params.put("email", "[email protected]");
user = User.find(params);

// Find user by user_id
params = Maps.newHashMap();
params.put("user_id", "1");
user = User.find(params);

// Update custom_attributes for a user
user.addCustomAttribute(CustomAttribute.newStringAttribute("role", "captain"));
User.update(user);

// Iterate over all users (up to 10k records, to read all use Scroll API)
UserCollection users = User.list();
while(users.hasNext()) {
    System.out.println(users.next().getUserId());
}

// List users (sorting)
Map<String, String> params = Maps.newHashMap();
params.put("sort", "updated_at");
params.put("order", "asc");
UserCollection users = User.list(params);

// List users (created within the past X days)
Map<String, String> params = Maps.newHashMap();
params.put("created_since", "2");
UserCollection users = User.list(params);

// List users by tag
Map<String, String> params = Maps.newHashMap();
params.put("tag_id", "12345");
UserCollection users = User.list(params);

// List users by segment
Map<String, String> params = Maps.newHashMap();
params.put("segment_id", "1234567890abcdef12345678");
UserCollection users = User.list(params);

// Retrieve users via Scroll API
ScrollableUserCollection usersScroll = User.scroll();
List<User> users = usersScroll.getPage();
usersScroll = usersScroll.scroll();

// Archive a user by Intercom ID
User user = User.find("541a144b201ebf2ec5000001");
User.archive(user.getId());

// Archive a user by user_id
Map<String, String> params = Maps.newHashMap();
params.put("user_id", "1");
User.archive(params);

// Archive a user by email
Map<String, String> params = Maps.newHashMap();
params.put("email", "[email protected]");
User.archive(params);

// Permanently delete a user by Intercom ID
User.permanentDelete("541a144b201ebf2ec5000001");

Contacts

Contacts were added in version 1.1 of the client.

// Create a Contact
Contact contact = new Contact()
    .setEmail("[email protected]")
    .addCustomAttribute(newStringAttribute("role", "fence"));
Contact created = Contact.create(contact);

// Find a single contact by server supplied user id or id
contact = Contact.findByID("541a144b201ebf2ec5000002");
contact = Contact.findByUserID("e1a7d875-d83a-46f7-86f4-73be98a98584");

// Update a contact
contact.setName("Stitch Hessian");
Contact updated = Contact.update(contact);

// Update a contact by ID
Contact contact = new Contact().setID("541a144b201ebf2ec5000002").setName("Stitch Hessian");
Contact updated = Contact.update(contact);

// Update a contact by User ID
Contact contact = new Contact().setUserID("e1a7d875-d83a-46f7-86f4-73be98a98584").setName("Stitch Hessian");
Contact updated = Contact.update(contact);

// Read a contact list by email
ContactCollection contacts = Contact.listByEmail("[email protected]");
while(contacts.hasNext()) {
    System.out.println(contacts.next());
}

// Iterate over all contacts (up to 10k records, to read all use Scroll API)
ContactCollection allContacts = Contact.list();
while(allContacts.hasNext()) {
    System.out.println(allContacts.next());
}

// Retrieve contacts via Scroll API
ScrollableContactCollection contactsScroll = Contact.scroll();
List<Contact> contacts = contactsScroll.getPage();
contactsScroll = contactsScroll.scroll();

// List contacts (sorting)
Map<String, String> params = Maps.newHashMap();
params.put("sort", "created_at");
params.put("order", "asc");
ContactCollection contacts = Contact.list(params);

// Remove a contact
Contact.delete(contact);

// Remove a contact by id
Contact.delete(contact.getID());

// Remove a contact by user_id
Contact.deleteByUserID(contact.getUserID());

// Convert a contact
User converted = Contact.convert(contact, user);

Visitors

// Find visitor by ID
Visitor visitor = Visitor.findByID("5b69565fa737210d1c2127f1");

// Find visitor by User ID
Visitor visitor = Visitor.findByUserID("6a347bc9-0b96-4925-bbbc-1f8b11f94c50");

// Update a visitor
Visitor visitor = Visitor.findByID("5b69565fa737210d1c2127f1");
visitor.setName("Visitor's Name");
Visitor.update(visitor);

// Delete a visitor by ID
Visitor.delete("5b69565fa737210d1c2127f1");

// Delete a visitor
Visitor visitor = Visitor.findByUserID("6a347bc9-0b96-4925-bbbc-1f8b11f94c50");
Visitor.delete(visitor);

// Convert a visitor to a lead
Visitor visitor = Visitor.findByUserID("6a347bc9-0b96-4925-bbbc-1f8b11f94c50");
Contact contact = Visitor.convertToContact(visitor);

// Convert a visitor to a user
Visitor visitor = Visitor.findByUserID("6a347bc9-0b96-4925-bbbc-1f8b11f94c50");
User user = new User();
user.setUserId("1");
User convertUser = Visitor.convertToUser(visitor, user);

Companies

// Create a company
Company company = new Company();
    company.setName("Blue Sun");
    company.setCompanyID("1");
    company.setMonthlySpend(123.10f);
    company.setPlan(new Company.Plan("premium"));
    company.addCustomAttribute(CustomAttribute.newIntegerAttribute("foddstuff-items", 246));
    company.addCustomAttribute(CustomAttribute.newStringAttribute("bestseller", "fruity oaty bar"));
Company.create(company);

// Find a company by company_id
map = Maps.newHashMap();
map.put("company_id", "1");
Company company = Company.find(map);

// Find a company by name
map = Maps.newHashMap();
map.put("name", "Blue Sun");
Company company = Company.find(map);

// Find a company by id
Company company = Company.find("541a144b201ebf2ec5000001");

// Update a company
company.setName("Blue Sun Corporation");
Company.update(company);

// Iterate over all companies
CompanyCollection companies = Company.list();
while(companies.hasNext()) {
    System.out.println(companies.next().getName());
}

// Retrieve companies via Scroll API
ScrollableCompanyCollection companiesScroll = Company.scroll();
List<Company> companies = companiesScroll.getPage();
companiesScroll = companiesScroll.scroll();

// Get a list of users in a company
map = Maps.newHashMap();
map.put("company_id", "6");
UserCollection users = Company.listUsers(map);

// Add a user to one or more companies
User user = User.find("541a144b201ebf2ec5000001");
user.addCompany(company);
User.update(user);

Admins

// Iterate over all admins
AdminCollection admins = Admin.list();
while(admins.hasNext()) {
    System.out.println(admins.next().getName());
}

// Find admin by ID
Admin admin = Admin.find("123456");

// Set admin as away and enable away mode reassignment
Admin admin = Admin.setAwayMode("123456", true, true);

Events

// Create an event with a user ID
// This is only valid for users
Event event = new Event()
    .setEventName("bought-hat")
    .setUserID("1")
    .putMetadata("invitee_email", "[email protected]")
    .putMetadata("found_date", System.currentTimeMillis())
    .putMetadata("new_signup", true);
Event.create(event);

// Create an event with an email
// This is only valid for users
Event event = new Event()
    .setEventName("bought-hat")
    .setEmail("[email protected]");
Event.create(event);

// Create an event with an ID
// This is valid for both users and leads
Event event = new Event()
        .setEventName("bought-hat")
        .setId("599d6aeeda850883ed8ba7c2");
Event.create(event);


// List events of a user
Map<String, String> params = Maps.newHashMap();
params.put("type", "user");
params.put("user_id", "1");
// Alternatively list by Intercom ID
// params.put("intercom_user_id", "541a144b201ebf2ec5000001");
// Or by email
// params.put("email", "[email protected]");
EventCollection events = Event.list(params);
while (events.hasNext()) {
    System.out.println(events.next().getEventName());
}

// List event summaries of a user
Map<String, String> params = Maps.newHashMap();
params.put("type", "user");
params.put("user_id", "1");
// Alternatively list by Intercom ID
// params.put("intercom_user_id", "541a144b201ebf2ec5000001");
// Or by email
// params.put("email", "[email protected]");
EventSummaryCollection eventSummaryCollection = Event.listSummary(params);
for(EventSummary eventSummary : eventSummaryCollection.getEventSummaries()){
    System.out.println(eventSummary);
}

Tags

// create a tag
Tag tag = new Tag().setName("alliance");
tag = Tag.create(tag);

// update a tag
tag.setName("independent");
tag = Tag.update(tag);

// tag and untag users
User one = new User().setEmail("[email protected]");
User two = new User().setEmail("[email protected]").untag();
User.create(one);
User.create(two);
Tag.tag(tag, one, two);

// tag and untag contacts
Contact contact1 = Contact.findByID("5ab313046e4997e35bc13e7c");
Contact contact2 = Contact.findByUserID("697ea3e0-227d-4d70-b776-1652e94f9583").untag();
Tag.tag(tag, contact1, contact2);

// iterate over all tags
final TagCollection tags = Tag.list();
while (tags.hasNext()) {
    System.out.println(tags.next().getId());
}

// tag and untag companies
Company c1 = new Company().setCompanyID("1");
Company c2 = new Company().setCompanyID("2").untag();
Company.create(c1);
Company.create(c2);
Tag.tag(tag, c1, c2);

// delete a tag
Tag.delete(tag);

Segments

// Find a segment
Segment segment = Segment.find("1");

// Update a segment
segment.setName("new name");
Segment.update(segment);

// Iterate over all segments
SegmentCollection segments = Segment.list();
while(segments.hasNext()) {
    System.out.println(segments.next().getId());
}

Notes

// create a user note
User user = new User().setId("5310d8e8598c9a0b24000005");
Author author = new Author().setId("1");
Note note = new Note()
    .setUser(user)
    .setAuthor(author)
    .setBody("The note");
Note.create(note);

// Find a note by id
note = Note.find("1");

// Iterate over all notes for a user via their user_id
Map<String, String> params = Maps.newHashMap();
params.put("user_id", "1");
NoteCollection notes = Note.list(params);
while(notes.hasNext()) {
    System.out.println(notes.next().getBody());
}

// Iterate over all notes for a user via their email address
params = Maps.newHashMap();
params.put("email", "[email protected]");
notes = Note.list(params);
while(notes.hasNext()) {
    System.out.println(notes.next().getBody());
}

Conversations

// send a message to a user
User user = new User().setId("5310d8e8598c9a0b24000005");
Admin admin = new Admin().setId("1");
AdminMessage adminMessage = new AdminMessage()
    .setAdmin(admin)
    .setUser(user)
    .setSubject("This Land")
    .setBody("Har har har! Mine is an evil laugh!")
    .setMessageType("email")
    .setTemplate("plain");
Conversation.create(adminMessage);

// send a message from a user
UserMessage userMessage = new UserMessage()
    .setBody("Hey! Is there, is there a reward?")
    .setFrom(user);
Conversation.create(userMessage);

// send a message from a contact
ContactMessage contactMessage = new ContactMessage()
    .setBody("Hey! Is there, is there a reward?")
    .setFrom(contact);
Conversation.create(contactMessage);

//list all conversations
ConversationCollection conversations = Conversation.list();
while (conversations.hasNext()) {
    Conversation conversation = conversations.next();
}

// find admin conversations
Map<String, String> params = Maps.newHashMap();
params.put("type", "admin");
params.put("admin_id", "1");
ConversationCollection adminConversations = Conversation.list(params);
while (adminConversations.hasNext()) {
    Conversation conversation = adminConversations.next();
}

// find user conversations
params = Maps.newHashMap();
params.put("type", "user");
params.put("user_id", "1");
ConversationCollection userConversations = Conversation.list(params);
while (userConversations.hasNext()) {
    Conversation conversation = userConversations.next();
}

// find a conversation by id
final Conversation conversation = Conversation.find("66");
ConversationMessage conversationMessage = conversation.getConversationMessage();
ConversationPartCollection parts = conversation.getConversationPartCollection();
List<ConversationPart> partList = parts.getPage();
for (ConversationPart part : partList) {
    String partType = part.getPartType();
    Author author = part.getAuthor();
    String body = part.getBody();
}
ConversationPart part = conversation.getMostRecentConversationPart();
Admin assignee = conversation.getAssignee();
User user = conversation.getUser();

// Find all open conversations assigned to an admin and render as plaintext
params = Maps.newHashMap();
params.put("type", "admin");
params.put("admin_id", "7");
params.put("display_as", "plaintext");
ConversationCollection openForAdmin = Conversation.list(params);

// admin reply
Admin admin = new Admin().setId("1");
AdminReply adminReply = new AdminReply(admin);
adminReply.setBody("These apples are healthsome");
adminReply.setAttachmentUrls(new String[]{"http://www.example.com/attachment.jpg"}); // optional - list of attachments
Conversation.reply("66", adminReply);

// admin close
Admin admin = new Admin().setId("1");
AdminReply adminReply = new AdminReply(admin);
adminReply.setMessageType("close");
Conversation.reply("66", adminReply);

// admin snooze
Admin admin = new Admin().setId("1");
AdminReply adminReply = new AdminReply(admin);
adminReply.setSnoozedUntil(1549092382);
Conversation.reply("66", adminReply);

// admin open / unsnooze
Admin admin = new Admin().setId("1");
AdminReply adminReply = new AdminReply(admin);
adminReply.setMessageType("open");
Conversation.reply("66", adminReply);

// user reply
User user1 = new User().setId("5310d8e8598c9a0b24000005");
UserReply userReply = new UserReply(user1);
userReply.setBody("Mighty fine shindig");
userReply.setAttachmentUrls(new String[]{"http://www.example.com/attachment.jpg"}); // optional - list of attachments
System.out.println(MapperSupport.objectMapper().writeValueAsString(userReply));
Conversation.reply("66", userReply);

// run assignment rules
Conversation.runAssignmentRules("19240007891");

// mark conversation as read
Conversation.markAsRead("66");

Webhooks

// create a subscription
Subscription subscription = new Subscription();
subscription.setUrl(new URI("https://example.org/webhooks/1"));
subscription.addTopic(Subscription.Topic.USER_CREATED);
subscription.addTopic(Subscription.Topic.USER_TAG_CREATED);
Subscription.create(subscription);

// create a subscribtion and subscribe to events
Subscription subscription = new Subscription();
subscription.addTopic(Subscription.Topic.EVENT_CREATED);
Map<String,ArrayList<String>> metadata = new HashMap<String, ArrayList<String>>();
ArrayList<String> events = new ArrayList<String>(Arrays.asList("cart"));
metadata.put("event_names", events);
subscription.setMetadata(metadata);
subscription.setMetadata(metadata);
Subscription.create(subscription);

// update a subscription
Subscription subscription = Subscription.find("nsub_60ca7690-4020-11e4-b789-4961958e51bd");
subscription.addTopic(Subscription.Topic.COMPANY_CREATED);
Subscription updatedSubscription = Subscription.update(subscription);

// delete a subscription
Subscription subscription = new Subscription();
subscription.setId("nsub_83793feb-8394-4cb6-91d6-68ef4dd08a8e");
Subscription deletedSubscription = Subscription.delete(subscription);

// find a subscription
subscription = Subscription.find("nsub_60ca7690-4020-11e4-b789-4961958e51bd");

// ping a subscription by ID
Subscription.ping("nsub_60ca7690-4020-11e4-b789-4961958e51bd");
// ping a subscription by subscription object
subscription = Subscription.find("nsub_60ca7690-4020-11e4-b789-4961958e51bd");
Subscription.ping(subscription);

// list subscriptions
SubscriptionCollection list = Subscription.list();
while(list.hasNext()) {
    Subscription sub = list.next();
    String appID = sub.getAppID();
    String serviceType = sub.getServiceType();
    List<Subscription.Topic> topics = sub.getTopics();
    String hubSecret = sub.getHubSecret();
}

// notification sent feed
NotificationCollection sent = Subscription.sentFeed(subscription.getId());
while(sent.hasNext()) {
    Notification notification = sent.next();
    String id = notification.getId();
    String topic = notification.getTopic();
    NotificationData data = notification.getData();
    String type = data.getType();
    // raw map representation of the payload
    Map item = data.getItem();
}

// notification error feed
NotificationErrorCollection errors = Subscription.errorFeed(subscription.getId());
while (errors.hasNext()) {
    NotificationError notificationError = errors.next();
    RequestResponseCapture capture = notificationError.getCapture();
    URI requestURI = capture.getRequestURI();
    String requestMethod = capture.getRequestMethod();
    Map<String, String> requestHeaders = capture.getRequestHeaders();
    String requestEntity = capture.getRequestEntity();
    int statusCode = capture.getResponseStatusCode();
    Map<String, String> responseHeaders = capture.getResponseHeaders();
    String responseEntity = capture.getResponseEntity();
}

// consume a webhook notification
InputStream jsonStream = ...;
final Notification notification = Notification.readJSON(jsonStream);

String jsonString = ...;
final Notification notification = Notification.readJSON(jsonString);

Counts

// app totals
Counts.Totals totals = Counts.appTotals();
System.out.println("companies: " + totals.getCompany().getValue());
System.out.println("segments: :" + totals.getSegment().getValue());
System.out.println("tags: :" + totals.getTag().getValue());
System.out.println("users: :" + totals.getUser().getValue());

// conversation totals
Counts.Conversation conversationTotals = Counts.conversationTotals();
System.out.println("assigned: " + conversationTotals.getAssigned());
System.out.println("closed: :" + conversationTotals.getClosed());
System.out.println("open: :" + conversationTotals.getOpen());
System.out.println("unassigned: :" + conversationTotals.getUnassigned());

// admin open/close counts
Counts.Conversation adminCounts = Counts.conversationAdmins();
List<Admin> admins = adminCounts.getAdmins();
for (Admin admin : admins) {
    System.out.println(admin.getName() + ": " + admin.getClosed() + ", " + admin.getOpen());
}

// tag user counts
System.out.println("tag user counts: ");
List<Counts.CountItem> tags = Counts.userTags();
for (Counts.CountItem tag : tags) {
    System.out.println(tag.getName()+": " +tag.getValue());
}

// segment user counts
List<Counts.CountItem> segments = Counts.userSegments();
for (Counts.CountItem segment : segments) {
    System.out.println(segment.getName()+": " +segment.getValue());
}

// company user counts
List<Counts.CountItem> companyUsers = Counts.companyUsers();
for (Counts.CountItem company : companyUsers) {
    System.out.println(company.getName()+": " +company.getValue());
}

// company tag counts
List<Counts.CountItem> companyTags = Counts.companyTags();
for (Counts.CountItem tag : companyTags) {
    System.out.println(tag.getName()+": " +tag.getValue());
}

Idioms

HTTP requests

To signal local versus remote methods, calls that result in HTTP requests are performed using static methods, for example User.find(). The objects returned by static methods are built from server responses. The exception to the static idiom is where the next(), hasNext() and nextPage() methods on Collections are used to abstract over pagination.

Pagination

Some API classes have static list() methods that correspond to paginated API responses. These return a Collection object (eg UserCollection) which can be iterated in two ways

  • The collection's getPage(), hasNextPage() and nextPage() methods - these are useful when you want to fetch one or just a few pages directly.

  • Java's inbuilt iterator methods next() and hasNext() - these are useful when you want to fetch data without manually handling pagination.

  • User and Contact listing only works up to 10k records. To retrieve all records use the Scroll API via scroll()

Error handling

You do not need to deal with the HTTP response from an API call directly. If there is an unsuccessful response then an IntercomException or a subclass of IntercomException will be thrown. The exception will have Error objects that can be examined via getErrorCollection and getFirstError for more detail.

The API throws the following runtime exceptions -

  • AuthorizationException: for a 401 or 403 response
  • InvalidException: for a 422 response or a local validation failure
  • RateLimitException: for a 429 rate limit exceeded response
  • ClientException: for a general 4xx response
  • ServerException: for a 500 or 503 response
  • IntercomException: general exception

Configuration

HTTP

The client can be configured to accept any http stack that implements java.net.HttpURLConnection by implementing the HttpConnectorSupplier interface.

For example, to use OkHttp as a connection supplier, create a supplier class -

public class OkHttpSupplier implements HttpConnectorSupplier {
    private final OkUrlFactory urlFactory;

    public OkHttpSupplier(OkUrlFactory urlFactory) {
        this.urlFactory = urlFactory;
    }

    @Override
    public HttpURLConnection connect(URI uri) throws IOException {
        return urlFactory.open(uri.toURL());
    }
}

and hand a supplier to the Intercom object -

final OkHttpClient client = new OkHttpClient();
final OkUrlFactory factory = new OkUrlFactory(client);
final OkHttpSupplier supplier = new OkHttpSupplier(factory);
Intercom.setHttpConnectorSupplier(supplier);

Timeouts

The default connection and request timeouts can be set in milliseconds using the Intercom.setConnectionTimeout and Intercom.setRequestTimeout methods.

Target API Server

The base URI to target can be changed for testing purposes

URI baseURI = new URI("https://example.org/server");
Intercom.setApiBaseURI(baseURI);

intercom-java's People

Contributors

ahirsh avatar alexshultsg avatar askibola avatar bobjflong avatar brianw avatar catacraciun avatar choran avatar christianekstrand avatar danielcompton avatar dannyfallon avatar dehora avatar enrico-intercom avatar itchap avatar johnnynader avatar jonnyom avatar josler avatar karc avatar khalilovcmd avatar kraftysm avatar mmartinic avatar murtron avatar pjfanning avatar plippe avatar ruairik avatar savicprvoslav avatar seanhealy33 avatar skowt avatar thewheat avatar xanderatbackbonesystems avatar yousefed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

intercom-java's Issues

Missing dependency causes classloader ClassNotFoundException: com.google.common.collect.Maps

Version info

  • intercom-java version: 2.2.3
  • Java version: 1.8

Expected behavior

Actual behavior

Steps to reproduce

  1. Play framework 1.4.3
  2. add intercom to Play's dependencies.yml:
require:
    - play 1.4.3
    - io.intercom -> intercom-java 2.2.3
repositories:
    - jcenter:
       type:       http
       artifact: "http://jcenter.bintray.com/io/intercom/[module]/[revision]/[module]-[revision].jar"
       contains:
            - io.intercom -> *
  1. Add following test case to Java class:
import io.intercom.api.Contact;
public class ... {
  public static void doContact(){
    Contact contact= new Contact();
  }
}

Causes exception:

java.lang.NoClassDefFoundError: com/google/common/collect/Maps
	at io.intercom.api.Contact.<clinit>(Contact.java:21)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at org.apache.commons.javaflow.bytecode.transformation.asm.ContinuationMethodAnalyzer$1.getClass(ContinuationMethodAnalyzer.java:114)
	at org.objectweb.asm.tree.analysis.SimpleVerifier.isAssignableFrom(Unknown Source)
	at org.objectweb.asm.tree.analysis.SimpleVerifier.isSubTypeOf(Unknown Source)
	at org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(Unknown Source)
	at org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(Unknown Source)
	at org.objectweb.asm.tree.analysis.Frame.execute(Unknown Source)
	at org.apache.commons.javaflow.bytecode.transformation.asm.MonitoringFrame.execute(MonitoringFrame.java:72)
	at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source)
	at org.apache.commons.javaflow.bytecode.transformation.asm.ContinuationMethodAnalyzer$2.analyze(ContinuationMethodAnalyzer.java:131)
	at org.apache.commons.javaflow.bytecode.transformation.asm.ContinuationMethodAnalyzer.visitEnd(ContinuationMethodAnalyzer.java:142)
	at org.objectweb.asm.ClassReader.b(Unknown Source)
	at org.objectweb.asm.ClassReader.accept(Unknown Source)
	at org.objectweb.asm.ClassReader.accept(Unknown Source)
	at org.apache.commons.javaflow.bytecode.transformation.asm.AsmClassTransformer.transform(AsmClassTransformer.java:74)
	at org.apache.commons.javaflow.bytecode.transformation.asm.AsmClassTransformer.transform(AsmClassTransformer.java:41)
	at play.classloading.enhancers.ContinuationEnhancer.enhanceThisClass(ContinuationEnhancer.java:72)
	at play.CorePlugin.enhance(CorePlugin.java:306)
	at play.plugins.PluginCollection.enhance(PluginCollection.java:651)
	at play.classloading.ApplicationClasses$ApplicationClass.enhance(ApplicationClasses.java:242)
	at play.classloading.ApplicationClassloader.loadApplicationClass(ApplicationClassloader.java:165)
	at play.classloading.ApplicationClassloader.getAllClasses(ApplicationClassloader.java:425)
	at play.classloading.ApplicationClassloader.getAssignableClasses(ApplicationClassloader.java:466)
	at play.templates.GroovyTemplateCompiler.compile(GroovyTemplateCompiler.java:33)
	at play.templates.TemplateCompiler.compile(TemplateCompiler.java:28)
	at play.templates.TemplateLoader.load(TemplateLoader.java:81)
	at play.mvc.Router.parse(Router.java:171)
	at play.mvc.Router.load(Router.java:53)
	at play.mvc.Router.detectChanges(Router.java:232)
	at play.server.PlayHandler$NettyInvocation.init(PlayHandler.java:249)
	at play.Invoker$Invocation.run(Invoker.java:285)
	at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:303)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps

Probably it's caused by Ivy not resolving dependencies as expected by other dependency managers? So we need to specify deps manually.
In this case the documentation should reflect what packages this library depends on.

Size of library.

Version info

  • intercom-java version: 3.0.9

I am going through an Android app I am working on currently and trying to speed up the compile time on it. I am going through each of my dependencies and removing ones that have a high method count.

I noticed that Intercom Java is a pretty big size library. In fact, I used this tool to analyze my APK and Intercom comes in 2nd place for biggest dependency behind Android and the support libraries I am using.

screen shot 2016-12-02 at 9 32 14 pm

Is there any way I can skim down Intercom Java? Thank you!

Name is scrambled when updating company with special character in its name

Version info

  • intercom-java version: 2.0.0
  • Java version: 1.8

Expected behavior

We have companies with special characters in their names e.g. quotes or ampersands.
Updating such companies causes their name to include tons of & then fail with message name too long
image
error: custom_attributes invalid, length too long: name

Actual behavior

Steps to reproduce

      val company = Company.find(Map("company_id" -> companyStats.id.toString))
      if (company != null) {
        company.setName(companyStats.name)
        company.addCustomAttribute(CustomAttribute.newBooleanAttribute("hasDemoData", companyStats.hasDemoData))
        Company.update(company)

in case company name is Bony's Fashion for example

Logs

ClientException: page limit reached, please use scroll API

Please use the following template to submit your issue. Following this template will allow us to quickly investigate and help you with your issue. Please be aware that issues which do not conform to this template may be closed.

For feature requests please contact us at [email protected]

Version info

  • intercom-java version: 2.1.0
  • Java version: 1.8.x

Expected behavior

I got the exception while retrieving all the users for a segment.

Actual behavior

Exception in thread "main" io.intercom.api.ClientException: page limit reached, please use scroll API

Steps to reproduce

The segment had 10620 users at that time.

Logs

Exception in thread "main" io.intercom.api.ClientException: page limit reached, please use scroll API
at io.intercom.api.HttpClient.throwException(HttpClient.java:205)
at io.intercom.api.HttpClient.handleError(HttpClient.java:164)
at io.intercom.api.HttpClient.runRequest(HttpClient.java:150)
at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105)
at io.intercom.api.HttpClient.get(HttpClient.java:81)
at io.intercom.api.HttpClient.get(HttpClient.java:77)
at io.intercom.api.TypedDataCollection.fetchNextPage(TypedDataCollection.java:44)
at io.intercom.api.UserCollection.nextPage(UserCollection.java:33)
at io.intercom.api.UserCollection.nextPage(UserCollection.java:9)
at io.intercom.api.TypedDataCollectionIterator.hasNext(TypedDataCollectionIterator.java:19)
at io.intercom.api.UserCollection.hasNext(UserCollection.java:37)

Resource Not Found

I started using the Intercom API yesterday (intercom-java-1.3.1), I am simply using it to post admin conversations.

I have used it successfully to post many messages this morning, however now i'm getting a 404 Resource Not Found when I make a call to Conversation.create().

My code is posted below:

    Intercom.setAppID("...");
    Intercom.setApiKey("...");

    final User user = new User().setId("...");
    final Admin admin = new Admin().setId("...");
    final AdminMessage adminMessage = new AdminMessage().setAdmin(admin).setUser(user).setBody("...")
            .setMessageType("inapp").setTemplate("plain");
    Conversation.create(adminMessage);

As I stated this code has worked earlier today, however now it does not. Any assistance would be appreciated

Regards, Craig Handley ([email protected])

Proguard rules?

Hello,

I am trying to integrate this library in an Android project but I need the Proguard rules if possible.

This is what I have so far:

# Intercom
-keep class intercom.** { *; }
-keep class org.slf4j.**
-dontwarn org.slf4j.**
-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry
#-keep class org.apache.commons.codec.binary.**
-keep class org.apache.commons.** { *; }
-keep interface org.apache.commons.** { *; }

# Jackson 2
-keep class com.fasterxml.jackson.databind.ObjectMapper {
    public <methods>;
    protected <methods>;
}
-keep class com.fasterxml.jackson.databind.ObjectWriter {
    public ** writeValueAsString(**);
}
# Configuration for Guava 18.0
#
# disagrees with instructions provided by Guava project: https://code.google.com/p/guava-libraries/wiki/UsingProGuardWithGuava
-keep class com.google.common.io.Resources {
    public static <methods>;
}
-keep class com.google.common.collect.Lists {
    public static ** reverse(**);
}
-keep class com.google.common.base.Charsets {
    public static <fields>;
}

-keep class com.google.common.base.Joiner {
    public static com.google.common.base.Joiner on(java.lang.String);
    public ** join(...);
}

-keep class com.google.common.collect.MapMakerInternalMap$ReferenceEntry
-keep class com.google.common.cache.LocalCache$ReferenceEntry

# http://stackoverflow.com/questions/9120338/proguard-configuration-for-guava-with-obfuscation-and-optimization
-dontwarn javax.annotation.**
-dontwarn javax.inject.**
-dontwarn sun.misc.Unsafe

# Guava 19.0
-dontwarn java.lang.ClassValue
-dontwarn com.google.j2objc.annotations.Weak
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

But I am still getting an error during Runtime:
java.lang.NoSuchMethodError: No static method encodeBase64String([B)Ljava/lang/String; in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/ext.jar)

Do you have any idea for me please?

Unrecognized field "metadata" exception

Hi,

I am using Intercom client

compile 'io.intercom:intercom-java:1.3.0-b2'

and when I try to read a webhook I get an exception. It looks like the field metadata is not recognized and also not defined in the class Notification.

io.intercom.api.InvalidException: could not parse json string [Unrecognized field "metadata" (class io.intercom.api.Notification), not marked as ignorable (12 known properties: "data", "created_at", "first_sent_at", "self", "delivered_at", "topic", "delivery_attempts", "links", "app_id", "type", "id", "delivery_status"])
 at [Source: {
  "type" : "notification_event",
  "app_id" : "XXXXXX",
  "data" : {
    "type" : "notification_event_data",
    "item" : {
      "type" : "ping",
      "message" : "\"Usage is oxygen for ideas\" #interzen"
    }
  },
  "links" : { },
  "id" : null,
  "topic" : "ping",
  "delivery_status" : null,
  "delivery_attempts" : 1,
  "delivered_at" : 0,
  "first_sent_at" : 1447754089,
  "created_at" : 1447754089,
  "self" : null,
  "metadata" : { }
}; line: 20, column: 17] (through reference chain: io.intercom.api.Notification["metadata"])]
    at io.intercom.api.Notification.readJSON(Notification.java:20)

Can you please confirm this asap because of this is a bug I simply get the content myself.

Signed Up At resulted in Invalid Date

Setting signedUpAt doesn't set the date properly.

Version info

  • intercom-java version: 2.2.1
  • Java version: 1.8

Expected behavior

Date should be sent properly

Actual behavior

Intercom shows "Invalid Date" on "Signed Up" date

Steps to reproduce

  1. User.setSignedUpAt(System.currentTimeMillis())

Logs

Cannot update a Job

Hi,
I would like to set a closing_at, but something is wrong with:

val job = intercomApi.User.submit(jobItems.asJava)
job.setClosingAt(Instant.now.toEpochMilli / 1000 + 2)
intercomApi.Job.update(job)

This is the error I get on Job.update:

2015-11-24 15:39:46.867 [fyrestone-actors-akka.actor.default-dispatcher-2] DEBUG intercom-java - error json follows --
{"type":"error.list","errors":null}
-- 
2015-11-24 15:39:46.885 [fyrestone-actors-akka.actor.default-dispatcher-2] ERROR c.c.f.events.ServerEventsHandler - 
io.intercom.api.NotFoundException: Could not read error message from server
    at io.intercom.api.HttpClient.throwException(HttpClient.java:201) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.HttpClient.handleError(HttpClient.java:164) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.HttpClient.runRequest(HttpClient.java:150) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.HttpClient.post(HttpClient.java:95) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.DataResource.post(DataResource.java:37) ~[io.intercom.intercom-java-1.3.0.jar:na]
    at io.intercom.api.Job.update(Job.java:36) ~[io.intercom.intercom-java-1.3.0.jar:na]

Add Event.list()

My application uses intercom-java 2.1.0 to access Intercom API and fetch (list) objects like Users, User Events, etc. For fetching User objects, we could use and call User.list method. But I noticed that Event doesn't have such method like list().

If you could add such Event.list method to fetch Events, it would be great for me. Or do you have any reasons why you cannot add list method to Event class? Or please let me know if you have any good ideas workarounds to fetch Events.

Version info

  • intercom-java version: 2.1.0
  • Java version: 1.7

ClientException: 'page' not found on model

Version info

  • intercom-java version: 2.0.0
  • Java version: 1.7

Expected behavior

Receive users in segment.

Actual behavior

Fails with exception, possibly a marshalling problem.

Steps to reproduce

  1. Query for users in segment

Logs

io.intercom.api.ClientException: 'page' not found on model
at io.intercom.api.HttpClient.throwException(HttpClient.java:205)
at io.intercom.api.HttpClient.handleError(HttpClient.java:164)
at io.intercom.api.HttpClient.runRequest(HttpClient.java:150)
at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105)
at io.intercom.api.HttpClient.get(HttpClient.java:81)
at io.intercom.api.HttpClient.get(HttpClient.java:77)
at io.intercom.api.TypedDataCollection.fetchNextPage(TypedDataCollection.java:44)
at io.intercom.api.UserCollection.nextPage(UserCollection.java:33)
at io.intercom.api.UserCollection.nextPage(UserCollection.java:9)
at io.intercom.api.TypedDataCollectionIterator.hasNext(TypedDataCollectionIterator.java:19)
at io.intercom.api.UserCollection.hasNext(UserCollection.java:37)

Tag.tag doesn't work

Hi there,

Running (more ;)) code from the samples (with version 0.0.4):

    Tag tag = new Tag().setName("henriktest");
    tag = Tag.create(tag);

    final ArrayList<User> users = new ArrayList<User>();
    users.add(user);
    Tag.tag(tag, new UserCollection(users));

The exception thrown from the last line above is as follows:

Exception in thread "main" io.intercom.api.ClientException: found unpermitted parameters: name, avatar, created_at, updated_at, remote_created_at, session_count, last_request_at, custom_attributes, user_agent_data, location_data, companies, social_profiles, segments, tags
at io.intercom.api.HttpClient.throwException(HttpClient.java:198)
at io.intercom.api.HttpClient.handleError(HttpClient.java:154)
at io.intercom.api.HttpClient.runRequest(HttpClient.java:147)
at io.intercom.api.HttpClient.post(HttpClient.java:93)
at io.intercom.api.DataResource.create(DataResource.java:19)
at io.intercom.api.Tag.tag(Tag.java:23)

Create Company doesn't work

I call the API using these lines:
Company company = new Company();
company.setName("Blue Sun");
company.setCompanyID("1");
company.setPlan(new Company.Plan("premium"));
company.addCustomAttribute(CustomAttribute.newIntegerAttribute("foddstuff-items", 246));
company.addCustomAttribute(CustomAttribute.newStringAttribute("bestseller", "fruity oaty bar"));
Company.create(company);

I get the company back with this:
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", "Blue Sun");
Company company2 = Company.find(map);

And it seems fine. But no company is created in my intercom account.
And no exception is thrown.

Please advice?

IllegalArgumentException: Illegal character(s) in message header value

Getting error from HttpURLConnection.checkMessageHeader when trying to create user.
I'm using Play Framework (1.2.7).

Stack:

java.lang.IllegalArgumentException: Illegal character(s) in message header value: Basic

at sun.net.www.protocol.http.HttpURLConnection.checkMessageHeader(HttpURLConnection.java:482)
at sun.net.www.protocol.http.HttpURLConnection.isExternalMessageHeaderAllowed(HttpURLConnection.java:434)
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:2735)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:316)
at io.intercom.api.HttpClient.applyHeaders(HttpClient.java:211)
at io.intercom.api.HttpClient.initializeConnection(HttpClient.java:136)
at io.intercom.api.HttpClient.post(HttpClient.java:91)
at io.intercom.api.DataResource.create(DataResource.java:19)
at io.intercom.api.User.create(User.java:56)
at services.IntercomHelper.createUser(IntercomHelper.java:31)

....

getConversationPartCollection() creates recursion

Please use the following template to submit your issue. Following this template will allow us to quickly investigate and help you with your issue. Please be aware that issues which do not conform to this template may be closed.

For feature requests please contact us at [email protected]

Version info

  • intercom-java version: 2.2.3
  • Java version: 1.8.0_115

Expected behavior

Get conversation parts

Actual behavior

Endless loop polling intercom backend

Steps to reproduce

  1. Conversation.find(conversation.getId()).getConversationPartCollection();
  2. Conversation does not have any parts

Logs

Impossible to send a message from a user

Hi,

I'm trying to send a message from a user using the Conversation resource.
So what I do is basically:

// Fetch a user from Intercom
User intercomUser = User.find('USER_ID')

// Create a UserMessage and set the body and the user sending it
UserMessage userMessage = new UserMessage().setBody('This is a test!').setUser(intercomUser)

// Create the conversation
Conversation.create(userMessage)

This seems to be exactly what is described in the doc, but whatever I try, I keep getting this error

io.intercom.api.NotFoundException: Resource Not Found

The user is correctly returned, but the error is sent when trying the create the conversation at the last line.

Could you please try on your side and confirm that this code is working for you? I can't figure out the reason why this error is returned.

Thanks a lot.
Florian

Adding a note to a conversation

Hi,

I would like to be able to add a note to a given conversation. So it would mean, having a conversation, being able to manipulate the conversationPartCollection on it (to add notes in my case).
Is there any possibility to do this, or if not, any plan in the roadmap to add this feature?

Thanks a lot,
Florian

Bulk operations do not work

Hi!

I'm getting this error when try to use Users.submit:

{
    "errors": [
        {
            "code": "media_type_not_acceptable",
            "message": "The Accept header should send a media type of application/json"
        }
    ],
    "type": "error.list"
}

This is my request:

{  
   "items":[  
      {  
         "method":"post",
         "data":{  
            "user_id":"user_id",
            "email":"user@email",
            "remote_created_at":1447935969,
            "name":"User Name",
            "custom_attributes":{  
               "project_count":7,
               "is_staff":false,
               "subscription_state":null,
               "is_suspended":false,
               "referrer":null,
               "is_org_teacher":true,
               "is_org_creator":true,
               "has_user_subscription":false,
               "trial_ends_at":null,
               "has_org_subscription":true,
               "plan":null,
               "is_org_owner":true,
               "has_subscription":true,
               "username":"user_name",
               "is_org_student":false
            },
            "companies":[  
               {  
                  "name":"My Edu ORg",
                  "company_id":"My Company Id",
                  "remote_created_at":1448012028,
                  "plan":"eduTrial"
               }
            ]
         }
      }
   ]
}

What's wrong ?

Crashes when bulk fetching users on social media links

Another social media bug:

Thread exception in intercom cron: Local exception calling [https://api.intercom.io/users?per_page=50&page=414]. Check connectivity and
settings. [no protocol: dusting.tumblr.com (through reference chain: io.intercom.api.UserCollection["users"]->java.util.ArrayList[45]->io.intercom.api.User["social_profiles"]->io.intercom.api.SocialProf
ileCollection["social_profiles"]->java.util.ArrayList[4])]

This is the second bug on a short time I found, the other bug was also on parsing these URLs.

Could you please just parse the URL as a string, and then create something like a getURL or let the user of the API get it? Since I haven't added these links to my users, intercom has. Or just make it optional to fetch the social media profiles?

User.create doesn't work (0.0.4)

Hi there,

A simple User.create(user) doesn't work, code:

User user = new User();
user.setEmail("[email protected]");
User.create(user);

Throws exception:

Exception in thread "main" java.lang.NullPointerException
at io.intercom.api.User$UserUpdate.isUpdateLastRequestAt(User.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.fasterxml.jackson.databind.introspect.AnnotatedMethod.getValue(AnnotatedMethod.java:159)
at com.fasterxml.jackson.databind.ser.PropertyBuilder.getDefaultValue(PropertyBuilder.java:239)
at com.fasterxml.jackson.databind.ser.PropertyBuilder.buildWriter(PropertyBuilder.java:111)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._constructWriter(BeanSerializerFactory.java:726)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:557)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:344)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:263)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:222)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:152)
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1077)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1037)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:445)
at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:599)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:92)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2866)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2289)
at io.intercom.api.HttpClient.prepareRequestEntity(HttpClient.java:126)
at io.intercom.api.HttpClient.post(HttpClient.java:92)
at io.intercom.api.DataResource.create(DataResource.java:19)
at io.intercom.api.User.create(User.java:79)

Best regards,
Henrik

Exception in thread "main" io.intercom.api.ServerException: service error

Please use the following template to submit your issue. Following this template will allow us to quickly investigate and help you with your issue. Please be aware that issues which do not conform to this template may be closed.

For feature requests please contact us at [email protected]

Version info

  • intercom-java version: 2.1.0
  • Java version: 1.8.x

Expected behavior

API should work.

Actual behavior

From time to time, we get the exception:
Exception in thread "main" io.intercom.api.ServerException: service error

What are the reasons for such an error ? What do you advice to do in such a case ?

Steps to reproduce

Logs

Exception in thread "main" io.intercom.api.ServerException: service error
at io.intercom.api.HttpClient.throwException(HttpClient.java:207)
at io.intercom.api.HttpClient.handleError(HttpClient.java:164)
at io.intercom.api.HttpClient.runRequest(HttpClient.java:150)
at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105)
at io.intercom.api.HttpClient.post(HttpClient.java:95)
at io.intercom.api.DataResource.create(DataResource.java:27)
at io.intercom.api.Job.submit(Job.java:49)
at io.intercom.api.Event.submit(Event.java:45)
at io.intercom.api.Event.submit(Event.java:40)

Make Intercom Credentials configurable on a Per - Object Basis

Due to the fact that static methods are used in order to list, create, update etc... entities, we are forced to either talk to 1 Intercom app per Java application or use Java synchronization in order to switch credentials on a per-method call (which is awkward since remote method calls take time to finish).

In order to send events to multiple Intercom apps within a single Java application, it would be helpful to extend the API in order to take credentials on a per-operation level, e.g.

def app = new IntercomApp(apiKey: "...", appId: "...")
User.list(app)
User.create(app, user)

Events.create missing data parameter

Hey there!

Using the sample code, I'm trying to create an Event using the Java API wrapper. I use the following code (with intercom-java 0.0.4):

    Event event = new Event().setEventName("bought-hat")
            .setUserID(user.getUserId())
            .putMetadata("invitee_email", "[email protected]")
            .putMetadata("found_date", System.currentTimeMillis())
            .putMetadata("new_signup", true);
        Event.create(event);

The last line throws the following exception:

Exception in thread "main" io.intercom.api.ClientException: missing data parameter
at io.intercom.api.HttpClient.throwException(HttpClient.java:198)
at io.intercom.api.HttpClient.handleError(HttpClient.java:154)
at io.intercom.api.HttpClient.runRequest(HttpClient.java:147)
at io.intercom.api.HttpClient.post(HttpClient.java:93)
at io.intercom.api.DataResource.create(DataResource.java:19)
at io.intercom.api.Event.create(Event.java:20)

Looking forward for a bit more stable Java wrapper (perhaps via a small test suite?).

Best regards,
Henrik

Implement scroll API for users

Please use the following template to submit your issue. Following this template will allow us to quickly investigate and help you with your issue. Please be aware that issues which do not conform to this template may be closed.

For feature requests please contact us at [email protected]

Version info

  • intercom-java version: 2.1.0
  • Java version: 1.8.x

Expected behavior

The SDK should provide an implementation for the scroll API.

Actual behavior

The SDK does not provide any implementation for the scroll API.

Steps to reproduce

Logs

Can't set unsubscribed from emails to false

When I call setUnsubscribedFromEmails(false) on an Intercom User object, the change is reflected locally, but when I call User.update with the user, the change can't be seen on Intercom.io. I intercepted the JSON payload being sent, and the "unsubscribed_from_emails" field seems to be missing when set to false. Works as expected when set to true.

Conflicting getter definitions for property \"update_last_request_at\":

Worked locally after updating to 1.0.8, deployed to prod, breaks with:
{"error":"Local exception calling [https://api.intercom.io//users]. Check connectivity and settings. [Conflicting getter definitions for property "update_last_request_at": io.intercom.api.User$UserUpdate#getUpdateLastRequestAt(0 params) vs io.intercom.api.User$UserUpdate#isUpdateLastRequestAt(0 params)]"}

Feels to me like a dependency issue where it was satisfied locally but had to go get it in prod...

API deprecation

Version info

  • intercom-java version: 2.0.0
  • Java version: 1.8u102

Expected behavior

Currently there is no indication which versions of this plugin are still supported by the actual API. We were on 2.0.0, when we noticed that since a few days, the bulk updating of users started to fail. Upgrading to 2.2.2 fixed the issue.

In this case a call to User.submit return null instead of a Job object

Please publish a list of versions and dates until these are supported as part of the readme.

Actual behavior

No information about supported versions is available

Cannot remove users from Company

It's written in intercom doc:

To remove a company from a user add the field remove with a value of true
to the embedded company object and submit the user as a update request. 
You must also submit the id of the company.

Seems this operation is not possible with this library.

bulk update crashes on response from server

Currently the server responds to the bulk submit like

{
  "app_id": "app_id",
  "id": "job_1234b123_12e1_11e5_8e6a_5f97e1eb8ad9",
  "created_at": 1449054998,
  "completed_at": null,
  "closing_at": 1449055898,
  "updated_at": 1449054998,
  "name": "api_bulk_job",
  "state": "running",
  "links": {
    "error": "https://api.intercom.io/jobs/job_1234b123_12e1_11e5_8e6a_5f97e1eb8ad9/error",
    "self": "https://api.intercom.io/jobs/job_1234b123_12e1_11e5_8e6a_5f97e1eb8ad9",
    "note": "You must authenticate with a valid API key to view these links."
  }
} 

The additional "note" in "links" is crashing the whole User.submit() method (line 187 in io.intercom.api.HttpClient), probably because a URI is expected.

User.setLastRequestAt doesn't reflect in app

Hey!

We have created a bunch of users in intercom. We want to update the lastRequestAt attribute to be able to see when they've logged on last (using intercom-java 1.0.0).

According to the API doc we should do this by using the user.setLastRequestAt setter. Here is the doc:
http://doc.intercom.io/api/#updating-the-last-seen-time

1: we find the user
2: we call user.setLastRequestAt(long)
3: we set user.setUpdateLastRequestAt(true) ; we've tried without this as well
4: we call User.update(user)

But no matter what we do, the "Last Seen" attribute on the user in the intercom app always seem to be updated to "now", meaning the time of the update via API.

Please advice!

Thanks in advance.

Best,
Henrik

image

Can't set the LocationData of a User from Api

I'm looking for creating users from the api and set his location.

I've seen the location_data property in the User Object and a getter but i can't find a setter for this property.

Is there any restriction for this property or just a lost setter function?

Thanks in advance.

JsonMappingException on Subscription.list()

Version info

  • intercom-java version: 2.2.0
  • Java version: 1.8

Expected behavior

Subscription.list() should return the list of subscriptions.

Actual behavior

It throws com.fasterxml.jackson.databind.JsonMappingException, because there are two possible cases of Subscription.metadata values:
1.
"metadata": { "event_names": [ "nps-response" ] }
In this case, it works well, because can be deserialized in Map Map<String, ArrayList<String>>
2.
"metadata": { "channel": "all" }
In this case, it throws the JsonMappingException, because this cannot be deserialized in Map<String, ArrayList<String>>.

Steps to reproduce

  1. Call Subscription.list()
  2. Depending on the configured subscriptions, you will get this exception.

Logs

Caused by: io.intercom.api.IntercomException: Local exception calling [https://api.intercom.io//subscriptions]. Check connectivity and settings. [Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5340ca7c; line: 1, column: 2611] (through reference chain: io.intercom.api.SubscriptionCollection["items"]->java.util.ArrayList[4]->io.intercom.api.Subscription["metadata"]->java.util.LinkedHashMap["channel"])]
    at io.intercom.api.HttpClient.throwLocalException(HttpClient.java:117)
    at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105)
    at io.intercom.api.HttpClient.get(HttpClient.java:79)
    at io.intercom.api.HttpClient.get(HttpClient.java:75)
    at io.intercom.api.DataResource.list(DataResource.java:58)
    at io.intercom.api.Subscription.list(Subscription.java:42)
    at com.konsus.server.service.intercom.IntercomConfig.findSubscription(IntercomConfig.java:148)
    at com.konsus.server.service.intercom.IntercomConfig.requireSubscription(IntercomConfig.java:137)
    at com.konsus.server.service.intercom.IntercomConfig.subscribeWebHooks(IntercomConfig.java:120)
    at com.konsus.server.service.intercom.IntercomConfig.onApplicationEvent(IntercomConfig.java:103)
    at com.konsus.server.service.intercom.IntercomConfig.onApplicationEvent(IntercomConfig.java:26)
    at com.konsus.server.service.intercom.IntercomConfig$$EnhancerBySpringCGLIB$$dfe151b7.onApplicationEvent(<generated>)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:166)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:121)
    at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111)
    at org.springframework.boot.context.event.EventPublishingRunListener.finished(EventPublishingRunListener.java:98)
    at org.springframework.boot.SpringApplicationRunListeners.callFinishedListener(SpringApplicationRunListeners.java:79)
    at org.springframework.boot.SpringApplicationRunListeners.finished(SpringApplicationRunListeners.java:72)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:149)
    at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:129)
    at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:85)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5240)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
    ... 42 more
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5340ca7c; line: 1, column: 2611] (through reference chain: io.intercom.api.SubscriptionCollection["items"]->java.util.ArrayList[4]->io.intercom.api.Subscription["metadata"]->java.util.LinkedHashMap["channel"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:857)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:853)
    at com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer.handleNonArray(StringCollectionDeserializer.java:240)
    at com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer.deserialize(StringCollectionDeserializer.java:171)
    at com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer.deserialize(StringCollectionDeserializer.java:161)
    at com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer.deserialize(StringCollectionDeserializer.java:19)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:495)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:341)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:217)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2810)
    at io.intercom.api.HttpClient.readEntity(HttpClient.java:185)
    at io.intercom.api.HttpClient.handleSuccess(HttpClient.java:169)
    at io.intercom.api.HttpClient.runRequest(HttpClient.java:146)
    at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:103)
    ... 66 more

This is an example of JSON response retrieved from intercom API, which fails:

{
  "type": "notification_subscription.list",
  "items": [
    {
      "type": "notification_subscription",
      "id": "<private>",
      "created_at": 1455493097,
      "updated_at": 1455578439,
      "url": "<private>",
      "topics": [
        "conversation.admin.replied",
        "conversation.admin.opened",
        "conversation.admin.closed",
        "conversation.admin.assigned"
      ],
      "active": true,
      "metadata": {
        "event_names": [
          "invited-friend"
        ]
      },
      "hub_secret": "",
      "links": {},
      "notes": [],
      "service_type": "web",
      "app_id": "<private>",
      "mode": "point"
    },
    {
      "type": "notification_subscription",
      "id": "<private>",
      "created_at": 1453575037,
      "updated_at": 1468970641,
      "url": "<private>",
      "topics": [
        "conversation.user.created",
        "conversation.user.replied",
        "conversation.admin.replied",
        "conversation.admin.single.created",
        "conversation.admin.assigned",
        "conversation.admin.noted",
        "conversation.admin.closed",
        "conversation.admin.opened"
      ],
      "active": true,
      "metadata": {},
      "hub_secret": "<private>",
      "links": {},
      "notes": [],
      "service_type": "web",
      "app_id": "<private>",
      "mode": "point"
    },
    {
      "type": "notification_subscription",
      "id": "<private>",
      "created_at": 1467027770,
      "updated_at": 1467028195,
      "url": "<private>",
      "topics": [
        "conversation.admin.noted"
      ],
      "active": true,
      "metadata": {
        "event_names": [
          null
        ]
      },
      "hub_secret": null,
      "links": {},
      "notes": [],
      "service_type": "web",
      "app_id": "<private>",
      "mode": "point"
    },
    {
      "type": "notification_subscription",
      "id": "<private>",
      "created_at": 1455760391,
      "updated_at": 1458687700,
      "url": "<private>",
      "topics": [
        "conversation.user.created"
      ],
      "active": true,
      "metadata": {
        "channel": "all"
      },
      "hub_secret": null,
      "links": {},
      "notes": [],
      "service_type": "slack",
      "app_id": "<private>",
      "mode": "point"
    }
  ]
}

io.intercom.api.ClientException: bad 'type' parameter

Using 1.0.7

Intercom.setAppID(appId);
Intercom.setApiKey(apiKey);

User user = new User();
user.setEmail(email);  //where email is my email address.
User.create(user);

Gives me
io.intercom.api.ClientException: bad 'type' parameter

I stepped through the code, sure enough, the server is sending back a 400 with bad 'type' parameter as the message...

Usage of api client

How should I use the api client. For example if I want to find a user by id, I do this:
User.find(id);
But from what I can tell, this call configures and registers a new jackson ObjectMapper module instance that is always the same. Why do we do this? I'm asking because I have a problem that after I do many api calls those objects remain stored in memory and the program stops with out of memory exception.

support for language_override

Version info

  • intercom-java version: 2.0.0

Expected behavior

the Java SDK should support the user attribute 'language_override'

see also https://docs.intercom.io/configure-intercom-for-your-product-or-site/customize-the-intercom-messenger/localize-intercom-to-work-with-multiple-languages#can-i-localize-the-intercom-sdks

while setting the attribute like this does add a new field with the expected data - the official attribute stays untouched...
user.addCustomAttribute(CustomAttribute.newStringAttribute("language_override", "fr"));

HTTP Requests should retry on 503 (maybe 429)

We have a custom integration with Intercom that hits the /users/ API, and we have been getting some 503 errors recently, which the Intercom support team say are temporary global rate limits akin to Amazon S3's use of "503 slow down". We also get some (documented) 429s when we hit the API too frequently.

I want to replace our integration with your Java client, rather than having to deal with retrying myself, but I notice that the client will throw an exception when your API returns a 503, rather than retrying with exponential back-off.

Backing off when a 429 is received would be handy too (there should be enough information in the 429 response header to reschedule the API call).

No way to bulk create/update users

It would be great if it was possible to bulk create/update users. Currently the API docs say this is not exposed in the Java client. Is there a reason for this? If not, this would be a very helpful addition.

Delete user is calling wrong url

The delete user call is generating a

DELETE https://api.intercom.io/users/{id}

instead of

DELETE https://api.intercom.io/users?user_id={id}

Error when adding metadata to an Event.

If I create an event with metadata it fails when doing the Event.create(event) step.

The stacktrace of the exception is:

Caused by: java.lang.NoSuchFieldError: WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
at io.intercom.api.MapperSupport.configure(MapperSupport.java:20)
at io.intercom.api.MapperSupport.objectMapper(MapperSupport.java:13)
at io.intercom.api.HttpClient.clientAgentDetails(HttpClient.java:48)
at io.intercom.api.HttpClient.(HttpClient.java:28)
at io.intercom.api.DataResource.create(DataResource.java:19)
at io.intercom.api.Event.create(Event.java:25)

Note.create() complains of unpermitted parameters in the User object

Creating a Note linked to a User like this:

                intercomId = "someintercomidhere";
                body = "A SHORT TEST BODY";
                Note note = new Note()
                        //.setUser(User.find(intercomId))           // try sending a fully-persisted User
                        .setUser(new User().setId(intercomId))  // try sending a bare User with just the ID set
                        //.setUser(new User().setEmail(email))    // try sending a bare User with just the email set
                        .setBody(body);
                System.err.println("NEW NOTE: "+note);
                // TODO: THIS FAILS! SERVER JUST WANTS A BARE 'user':{'id':'foobar'} ENTRY IN REQUEST, APPARENTLY
                Note.create(note);

constructs a request with a "type" key in the User object, which triggers an error:

INFO - api server request --
{"type":"note","body":"A SHORT TEST BODY","user":{"type":"user","id":"someintercomidhere"}}
-- 
DEBUG - error json follows --
{"type":"error.list","errors":[{"type":"error","code":"parameter_invalid","message":"found unpermitted parameters: type"}]}
-- 
io.intercom.api.ClientException: found unpermitted parameters: type
    at io.intercom.api.HttpClient.throwException(HttpClient.java:205)
    at io.intercom.api.HttpClient.handleError(HttpClient.java:164)
    at io.intercom.api.HttpClient.runRequest(HttpClient.java:150)
    at io.intercom.api.HttpClient.executeHttpMethod(HttpClient.java:105)
    at io.intercom.api.HttpClient.post(HttpClient.java:95)
    at io.intercom.api.DataResource.create(DataResource.java:22)
    at io.intercom.api.Note.create(Note.java:23)
[...]

Submitting a Note with a full User object (result of User.find(id), for example) yields server complaints of many more "unpermitted parameters" in the User object.

Crashes when user has invalid social media url

This one hit me today in production:

at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@51c238c1; line: 1, column: 28384](through reference chain: io.intercom.api.UserCollection["users"]->java.util.ArrayList[23]->io.intercom.api.User["social_profiles"]->io.intercom.api.SocialProfileCollection["social_profiles"]->java.util.ArrayList[0]->io.intercom.api.SocialProfile["url"])]
13:47:57.453 [pool-8-thread-1] ERROR shortcut.customers.package$ - Thread exception in intercom cron: Local exception calling [https://api.intercom.io/users?per_page=50&page=468]. Check connectivity and settings. [Can not construct instance of java.net.URI from String value 'http://www.myspace.com/alexandra thorvall': not a valid textual representationproblem: Illegal character in path at index 32: http://www.myspace.com/alexandra thorvall

Apparently you don't url encode urls or something.

How do I fix this?

Intercom is showing an error: E/Intercom-Android: ERROR: Api call failed: Canceled

After making the following call using the Intercom-java framework:

Intercom.client().displayConversationsList();

A new activity opens up and shows an error message where normally a conversation list would be. "Unable to load conversations". Further, the logs show the following error: "E/Intercom-Android: ERROR: Api call failed: Canceled".

I'm unable to find any documentation to this specific error. Any help would be appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.