org.tomitribe.chatterbox.slack.adapter.SlackResourceAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.tomitribe.chatterbox.slack.adapter.SlackResourceAdapter.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tomitribe.chatterbox.slack.adapter;

import com.fasterxml.jackson.databind.JsonNode;
import flowctrl.integration.slack.SlackClientFactory;
import flowctrl.integration.slack.rtm.Event;
import flowctrl.integration.slack.rtm.EventListener;
import flowctrl.integration.slack.rtm.SlackRealTimeMessagingClient;
import flowctrl.integration.slack.type.Authentication;
import flowctrl.integration.slack.type.Presence;
import flowctrl.integration.slack.webapi.SlackWebApiClient;
import flowctrl.integration.slack.webapi.method.chats.ChatPostMessageMethod;
import org.tomitribe.crest.Main;
import org.tomitribe.crest.cmds.Cmd;
import org.tomitribe.crest.cmds.processors.Commands;
import org.tomitribe.crest.cmds.targets.Target;
import org.tomitribe.crest.environments.Environment;

import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ConfigProperty;
import javax.resource.spi.Connector;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkManager;
import javax.transaction.xa.XAResource;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

@Connector(description = "Sample Resource Adapter", displayName = "Sample Resource Adapter", eisType = "Sample Resource Adapter", version = "1.0")
public class SlackResourceAdapter implements ResourceAdapter, EventListener {
    final Map<SlackActivationSpec, EndpointTarget> targets = new ConcurrentHashMap<SlackActivationSpec, EndpointTarget>();

    @ConfigProperty
    private String token;

    private SlackRealTimeMessagingClient slackRealTimeMessagingClient;
    private SlackWebApiClient webApiClient;
    private Main main;
    private WorkManager workManager;
    private String user;
    private String userId;

    public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
        workManager = bootstrapContext.getWorkManager();
        webApiClient = SlackClientFactory.createWebApiClient(token);
        slackRealTimeMessagingClient = SlackClientFactory.createSlackRealTimeMessagingClient(token);

        final Authentication authentication = webApiClient.auth();
        user = authentication.getUser();
        userId = authentication.getUser_id();

        webApiClient.setPresenceUser(Presence.AUTO);

        slackRealTimeMessagingClient.addListener(Event.MESSAGE, this);
        slackRealTimeMessagingClient.connect();
        main = new Main();
    }

    public void stop() {
        webApiClient.setPresenceUser(Presence.AWAY);
    }

    public void endpointActivation(final MessageEndpointFactory messageEndpointFactory,
            final ActivationSpec activationSpec) throws ResourceException {
        final SlackActivationSpec slackActivationSpec = (SlackActivationSpec) activationSpec;

        workManager.scheduleWork(new Work() {

            @Override
            public void run() {
                try {
                    final MessageEndpoint messageEndpoint = messageEndpointFactory.createEndpoint(null);

                    final EndpointTarget target = new EndpointTarget(messageEndpoint);
                    final Class<?> endpointClass = slackActivationSpec.getBeanClass() != null
                            ? slackActivationSpec.getBeanClass()
                            : messageEndpointFactory.getEndpointClass();

                    target.commands.addAll(Commands.get(endpointClass, target, null).values());

                    for (Cmd cmd : target.commands) {
                        main.add(cmd);
                    }

                    targets.put(slackActivationSpec, target);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void release() {
            }

        });

    }

    public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) {
        final SlackActivationSpec telnetActivationSpec = (SlackActivationSpec) activationSpec;

        final EndpointTarget endpointTarget = targets.get(telnetActivationSpec);
        if (endpointTarget == null) {
            throw new IllegalStateException("No EndpointTarget to undeploy for ActivationSpec " + activationSpec);
        }

        final List<Cmd> commands = telnetActivationSpec.getCommands();
        for (Cmd command : commands) {
            main.remove(command);
        }

        endpointTarget.messageEndpoint.release();
    }

    public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
        return new XAResource[0];
    }

    public void sendMessage(final String channel, final String message) {
        ChatPostMessageMethod postMessage = new ChatPostMessageMethod(channel, message);
        postMessage.setUsername(user);
        webApiClient.postMessage(postMessage);
    }

    @Override
    public void handleMessage(final JsonNode jsonNode) {

        String commandLine = jsonNode.get("text").textValue();
        final String userPrefix = "<@" + userId + ">";
        if (!commandLine.startsWith(userPrefix)) {
            return;
        }

        // chop off the user: prefix
        commandLine = commandLine.replaceAll("^" + userPrefix + ":?\\s*", "");

        final String channel = jsonNode.get("channel").textValue();

        String[] args;
        final Arguments[] arguments = ArgumentsParser.parse(commandLine);
        if (arguments == null || arguments.length == 0) {
            args = new String[] { "help" };
        } else {
            args = arguments[0].get();
        }

        final ByteArrayOutputStream os = new ByteArrayOutputStream();
        final PrintStream ps = new PrintStream(os);
        final Environment environment = new Environment() {
            @Override
            public PrintStream getOutput() {
                return ps;
            }

            @Override
            public PrintStream getError() {
                return ps;
            }

            @Override
            public InputStream getInput() {
                return null;
            }

            @Override
            public Properties getProperties() {
                return System.getProperties();
            }
        };

        try {
            main.main(environment, args);
        } catch (Exception e) {
            e.printStackTrace(ps);
        }

        ChatPostMessageMethod postMessage = new ChatPostMessageMethod(channel, new String(os.toByteArray()));
        postMessage.setUsername(user);
        webApiClient.postMessage(postMessage);
    }

    private static class EndpointTarget implements Target {
        private final MessageEndpoint messageEndpoint;
        private final List<Cmd> commands = new ArrayList<Cmd>();

        public EndpointTarget(MessageEndpoint messageEndpoint) {
            this.messageEndpoint = messageEndpoint;
        }

        @Override
        public Object invoke(Method method, Object... objects)
                throws InvocationTargetException, IllegalAccessException {

            try {
                try {
                    messageEndpoint.beforeDelivery(method);

                    return method.invoke(messageEndpoint, objects);
                } finally {
                    messageEndpoint.afterDelivery();
                }
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (ResourceException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public String getToken() {
        return token;
    }

    public void setToken(final String token) {
        this.token = token;
    }
}