require 'thor' require 'twitter' require 't/collectable' require 't/printable' require 't/rcfile' require 't/requestable' require 't/utils' module T class List < Thor include T::Collectable include T::Printable include T::Requestable include T::Utils DEFAULT_NUM_RESULTS = 20 MAX_USERS_PER_LIST = 500 MAX_USERS_PER_REQUEST = 100 check_unknown_options! def initialize(*) @rcfile = T::RCFile.instance super end desc 'add LIST USER [USER...]', 'Add members to a list.' method_option 'id', :aliases => '-i', :type => :boolean, :desc => 'Specify input as Twitter user IDs instead of screen names.' def add(list, user, *users) added_users, number = fetch_users(users.unshift(user), options) do |users_to_add| client.add_list_members(list, users_to_add) users_to_add end say "@#{@rcfile.active_profile[0]} added #{pluralize(number, 'member')} to the list \"#{list}\"." say if options['id'] say "Run `#{File.basename($PROGRAM_NAME)} list remove --id #{list} #{added_users.join(' ')}` to undo." else say "Run `#{File.basename($PROGRAM_NAME)} list remove #{list} #{added_users.collect { |added_user| "@#{added_user}" }.join(' ')}` to undo." end end desc 'create LIST [DESCRIPTION]', 'Create a new list.' method_option 'private', :aliases => '-p', :type => :boolean def create(list, description = nil) opts = description ? {:description => description} : {} opts.merge!(:mode => 'private') if options['private'] client.create_list(list, opts) say "@#{@rcfile.active_profile[0]} created the list \"#{list}\"." end desc 'information [USER/]LIST', 'Retrieves detailed information about a Twitter list.' method_option 'csv', :aliases => '-c', :type => :boolean, :desc => 'Output in CSV format.' def information(list) owner, list = extract_owner(list, options) list = client.list(owner, list) if options['csv'] require 'csv' say ['ID', 'Description', 'Slug', 'Screen name', 'Created at', 'Members', 'Subscribers', 'Following', 'Mode', 'URL'].to_csv say [list.id, list.description, list.slug, list.user.screen_name, csv_formatted_time(list), list.member_count, list.subscriber_count, list.following?, list.mode, list.uri].to_csv else array = [] array << ['ID', list.id.to_s] array << ['Description', list.description] unless list.description.nil? array << ['Slug', list.slug] array << ['Screen name', "@#{list.user.screen_name}"] array << ['Created at', "#{ls_formatted_time(list, :created_at, false)} (#{time_ago_in_words(list.created_at)} ago)"] array << ['Members', number_with_delimiter(list.member_count)] array << ['Subscribers', number_with_delimiter(list.subscriber_count)] array << ['Status', list.following ? 'Following' : 'Not following'] array << ['Mode', list.mode] array << ['URL', list.uri] print_table(array) end end map %w[details] => :information desc 'members [USER/]LIST', 'Returns the members of a Twitter list.' method_option 'csv', :aliases => '-c', :type => :boolean, :desc => 'Output in CSV format.' method_option 'id', :aliases => '-i', :type => :boolean, :desc => 'Specify user via ID instead of screen name.' method_option 'long', :aliases => '-l', :type => :boolean, :desc => 'Output in long format.' method_option 'reverse', :aliases => '-r', :type => :boolean, :desc => 'Reverse the order of the sort.' method_option 'sort', :aliases => '-s', :type => :string, :enum => %w[favorites followers friends listed screen_name since tweets tweeted], :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER' method_option 'unsorted', :aliases => '-u', :type => :boolean, :desc => 'Output is not sorted.' def members(list) owner, list = extract_owner(list, options) users = client.list_members(owner, list).to_a print_users(users) end desc 'remove LIST USER [USER...]', 'Remove members from a list.' method_option 'id', :aliases => '-i', :type => :boolean, :desc => 'Specify input as Twitter user IDs instead of screen names.' def remove(list, user, *users) removed_users, number = fetch_users(users.unshift(user), options) do |users_to_remove| client.remove_list_members(list, users_to_remove) users_to_remove end say "@#{@rcfile.active_profile[0]} removed #{pluralize(number, 'member')} from the list \"#{list}\"." say if options['id'] say "Run `#{File.basename($PROGRAM_NAME)} list add --id #{list} #{removed_users.join(' ')}` to undo." else say "Run `#{File.basename($PROGRAM_NAME)} list add #{list} #{removed_users.collect { |removed_user| "@#{removed_user}" }.join(' ')}` to undo." end end desc 'timeline [USER/]LIST', 'Show tweet timeline for members of the specified list.' method_option 'csv', :aliases => '-c', :type => :boolean, :desc => 'Output in CSV format.' method_option 'decode_uris', :aliases => '-d', :type => :boolean, :desc => 'Decodes t.co URLs into their original form.' method_option 'id', :aliases => '-i', :type => :boolean, :desc => 'Specify user via ID instead of screen name.' method_option 'long', :aliases => '-l', :type => :boolean, :desc => 'Output in long format.' method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.' method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.' method_option 'reverse', :aliases => '-r', :type => :boolean, :desc => 'Reverse the order of the sort.' def timeline(list) owner, list = extract_owner(list, options) count = options['number'] || DEFAULT_NUM_RESULTS opts = {} opts[:include_entities] = !!options['decode_uris'] tweets = collect_with_count(count) do |count_opts| client.list_timeline(owner, list, count_opts.merge(opts)) end print_tweets(tweets) end map %w[tl] => :timeline end end