/* * The MIT License (MIT) * * Copyright (c) 2013-2017 Jeff Nelson, Cinchapi Software Collective * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.cinchapi.concourse.example.mocktwitter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import com.cinchapi.concourse.time.Time; /** * The TwitterCLI is a command line application that mimics some of the * functionality of Twitter. This application is designed to run with a * {@link Twitter} back end that uses Concourse or some other database for data * storage. * * @author Jeff Nelson */ public class TwitterCLI { /** * The {@link Twitter} back end that is used to manage the application logic * and data storage. */ public static final Twitter twitter = new ConcourseTwitter(); /** * Run the program... * * @param args */ public static void main(String... args) { String linebreak = System.getProperty("line.separator"); boolean loggedIn = false; boolean running = true; String loggedOutInstructions = new StringBuilder() .append("Type 'login <username>' to login").append(linebreak) .append("Type 'register <username>' to create user") .append(linebreak).append("Type 'exit' to quit").toString(); String loggedInInstructions = new StringBuilder() .append("Type 'tweet <message>' to tweet").append(linebreak) .append("Type 'follow <username>' to follow user") .append(linebreak) .append("Type 'unfollow <username>' to unfollow user") .append(linebreak) .append("Type 'timeline' to view your timeline") .append(linebreak) .append("Type 'mentions' to view your mentions") .append(linebreak).append("Type 'exit' to quit").toString(); System.out.println("Welcome to the Twitter Demo application!"); System.out.println("THIS APPLICATION READS PASSWORDS IN PLAIN TEXT SO " + "PLEASE DON'T USE SENSITIVE INFORMATION DURING TESTING"); while (running) { try { if(!loggedIn) { System.out.println(""); System.out.println(loggedOutInstructions); } else { System.out.println(""); System.out.println(loggedInInstructions); } String input = getInput("twitter>"); String[] toks = input.split(" "); if(toks.length < 1) { System.err.println("Please specify an action"); } else { String action = toks[0]; if(action.equalsIgnoreCase("login") && !loggedIn) { if(toks.length < 2) { System.err.println("Please specify a username"); } else { String username = toks[1]; String password = getInput("password>"); if(twitter.login(username, password)) { loggedIn = true; System.out.println("Successfully logged in as " + username); } else { System.err.println("Invalid username/password " + "combination"); } } } else if(action.equalsIgnoreCase("register") && !loggedIn) { if(toks.length < 2) { System.err.println("Please specify a username"); } else { String username = toks[1]; String password = getInput("password>"); if(twitter.register(username, password)) { System.out.println("Successfully registered " + username); } else { System.err .println("Could not register user with the " + "specified username/password combination"); } } } else if(action.equalsIgnoreCase("tweet") && loggedIn) { if(toks.length < 2) { System.err .println("Please specify a message for the tweet"); } else { StringBuilder message = new StringBuilder(); for (int i = 1; i < toks.length; i++) { if(i != 1) { message.append(" "); } message.append(toks[i]); } twitter.tweet(message.toString()); } } else if(action.equalsIgnoreCase("follow") && loggedIn) { if(toks.length < 2) { System.err.println("Please specify a username"); } else if(twitter.follow(toks[1])) { System.out.println("You are now following " + toks[1]); } else { System.err.println("Error trying to follow " + toks[1]); } } else if(action.equalsIgnoreCase("unfollow") && loggedIn) { if(toks.length < 2) { System.err.println("Please specify a username"); } else if(twitter.follow(toks[1])) { System.out.println("You are no longer following " + toks[1]); } else { System.err.println("Error trying to unfollow " + toks[1]); } } else if(action.equalsIgnoreCase("timeline") && loggedIn) { displayTweets(twitter.timeline()); } else if(action.equalsIgnoreCase("mentions") && loggedIn) { displayTweets(twitter.mentions()); } else if(action.equalsIgnoreCase("exit")) { running = false; } else { System.err.println("Please specify a valid action"); } } } catch (Exception e) { System.err.println(e.getMessage()); } } System.exit(0); } /** * Format and print {@code tweets} to the console. * * @param tweets */ private static void displayTweets(Map<Long, String> tweets) { for (Entry<Long, String> tweet : tweets.entrySet()) { String elapsed = getElapsedTimeString(tweet.getKey()); String message = tweet.getValue(); System.out.println(message + " (" + elapsed + " ago)"); } } /** * Return a string that describes the time that has elapsed since the * timestamp specified in {@code microseconds}. * * @param microseconds * @return the elapsed time string */ private static String getElapsedTimeString(long microseconds) { long elapsed = TimeUnit.SECONDS.convert(Time.now() - microseconds, TimeUnit.MICROSECONDS); String unit = ""; if(elapsed < 60) { unit = "seconds"; } else if(elapsed >= 60 && elapsed < 3600) { elapsed = TimeUnit.MINUTES.convert(elapsed, TimeUnit.SECONDS); unit = elapsed > 1 ? "minutes" : "minute"; } else if(elapsed >= 3600 && elapsed < 86400) { elapsed = TimeUnit.HOURS.convert(elapsed, TimeUnit.SECONDS); unit = elapsed > 1 ? "hours" : "hour"; } else { elapsed = TimeUnit.DAYS.convert(elapsed, TimeUnit.SECONDS); unit = elapsed > 1 ? "days" : "day"; } return elapsed + " " + unit; } /** * Get user input from the command line. * * @param prompt * @return the input */ private static String getInput(String prompt) { try { System.out.print(prompt + " "); return input.readLine(); } catch (IOException e) { throw new RuntimeException(e); } } // Handler to read System.in private static final BufferedReader input = new BufferedReader( new InputStreamReader(System.in)); }