package com.google.cloud.pubsub.client.demos.cli; import com.google.api.services.pubsub.Pubsub; import com.google.api.services.pubsub.model.ListTopicsResponse; import com.google.api.services.pubsub.model.PublishRequest; import com.google.api.services.pubsub.model.PublishResponse; import com.google.api.services.pubsub.model.PubsubMessage; import com.google.api.services.pubsub.model.Topic; import com.google.common.collect.ImmutableList; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Class TopicMethods contains static methods for topics. */ public final class TopicMethods { /** * Prevents initialization. */ private TopicMethods() { } /** * IRC bot name. */ private static final String BOT_NAME = "pubsub-irc-bot/1.0"; /** * IRC port number. */ private static final int PORT = 6667; /** * Creates a new topic with a given name. * * @param client Cloud Pub/Sub client. * @param args Command line arguments. * @throws IOException when Cloud Pub/Sub API calls fail. */ public static void createTopic(final Pubsub client, final String[] args) throws IOException { Main.checkArgsLength(args, 3); String topicName = PubsubUtils.getFullyQualifiedResourceName( PubsubUtils.ResourceType.TOPIC, args[0], args[2]); Topic topic = client.projects().topics() .create(topicName, new Topic()) .execute(); System.out.printf("Topic %s was created.\n", topic.getName()); } /** * Connects an IRC channel and publish the chat messages to the given topic. * * @param client Cloud Pub/Sub client. * @param args Command line arguments. * @throws IOException when Cloud Pub/Sub API calls fail. */ public static void connectIrc(final Pubsub client, final String[] args) throws IOException { Main.checkArgsLength(args, 5); final String server = args[3]; final String channel = args[4]; final String topic = PubsubUtils.getFullyQualifiedResourceName( PubsubUtils.ResourceType.TOPIC, args[0], args[2]); final String nick = String.format("bot-%s", args[0]); final Socket socket = new Socket(server, PORT); final BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())); final BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); writer.write(String.format("NICK %s\r\n", nick)); writer.write(String.format("USER %s 8 * : %s\r\n", nick, BOT_NAME)); writer.flush(); String line; while ((line = reader.readLine()) != null) { if (line.contains("004")) { System.out.printf("Connected to %s.\n", server); break; } else if (line.contains("433")) { System.err.println("Nickname is already in use."); return; } } writer.write(String.format("JOIN %s\r\n", channel)); writer.flush(); // A regex pattern for Wikipedia change log as of June 4, 2014 Pattern pat = Pattern.compile( "\\u000314\\[\\[\\u000307(.*)\\u000314\\]\\]\\u0003.*" + "\\u000302(http://[^\\u0003]*)\\u0003"); while ((line = reader.readLine()) != null) { if (line.toLowerCase().startsWith("PING ")) { // We must respond to PINGs to avoid being disconnected. writer.write("PONG " + line.substring(5) + "\r\n"); writer.write("PRIVMSG " + channel + " :I got pinged!\r\n"); writer.flush(); } else { String privmsgMark = "PRIVMSG " + channel + " :"; int prividx = line.indexOf(privmsgMark); if (prividx == -1) { continue; } line = line.substring(prividx + privmsgMark.length(), line.length()); PubsubMessage pubsubMessage = new PubsubMessage(); Matcher matcher = pat.matcher(line); if (matcher.find()) { String message = String.format("Title: %s, Diff: %s", matcher.group(1), matcher.group(2)); pubsubMessage.encodeData(message.getBytes("UTF-8")); } else { pubsubMessage.encodeData(line.getBytes("UTF-8")); } List<PubsubMessage> messages = ImmutableList.of(pubsubMessage); PublishRequest publishRequest = new PublishRequest(); publishRequest.setMessages(messages); client.projects().topics() .publish(topic, publishRequest) .execute(); } } } /** * Publishes the given message to the given topic. * * @param client Cloud Pub/Sub client. * @param args Command line arguments. * @throws IOException when Cloud Pub/Sub API calls fail. */ public static void publishMessage(final Pubsub client, final String[] args) throws IOException { Main.checkArgsLength(args, 4); String topic = PubsubUtils.getFullyQualifiedResourceName( PubsubUtils.ResourceType.TOPIC, args[0], args[2]); String message = args[3]; PubsubMessage pubsubMessage = new PubsubMessage() .encodeData(message.getBytes("UTF-8")); List<PubsubMessage> messages = ImmutableList.of(pubsubMessage); PublishRequest publishRequest = new PublishRequest(); publishRequest.setMessages(messages); PublishResponse publishResponse = client.projects().topics() .publish(topic, publishRequest) .execute(); List<String> messageIds = publishResponse.getMessageIds(); if (messageIds != null) { for (String messageId : messageIds) { System.out.println("Published with a message id: " + messageId); } } } /** * Deletes a topic with the given name. * * @param client Cloud Pub/Sub client. * @param args Command line arguments. * @throws IOException when Cloud Pub/Sub API calls fail. */ public static void deleteTopic(final Pubsub client, final String[] args) throws IOException { Main.checkArgsLength(args, 3); String topicName = PubsubUtils.getFullyQualifiedResourceName( PubsubUtils.ResourceType.TOPIC, args[0], args[2]); client.projects().topics().delete(topicName).execute(); System.out.printf("Topic %s was deleted.\n", topicName); } /** * Lists existing topics in the project. * * @param client Cloud Pub/Sub client. * @param args Command line arguments. * @throws IOException when Cloud Pub/Sub API calls fail. */ public static void listTopics(final Pubsub client, final String[] args) throws IOException { String nextPageToken = null; boolean hasTopics = false; Pubsub.Projects.Topics.List listMethod = client.projects().topics().list("projects/" + args[0]); do { if (nextPageToken != null) { listMethod.setPageToken(nextPageToken); } ListTopicsResponse response = listMethod.execute(); if (!response.isEmpty()) { for (Topic topic : response.getTopics()) { hasTopics = true; System.out.println(topic.getName()); } } nextPageToken = response.getNextPageToken(); } while (nextPageToken != null); if (!hasTopics) { System.out.println(String.format( "There are no topics in the project '%s'.", args[0])); } } }