lib/t/list.rb in t-0.6.4 vs lib/t/list.rb in t-0.7.0

- old
+ new

@@ -1,7 +1,10 @@ require 'action_view' require 'active_support/core_ext/array/grouping' +require 'csv' +# 'fastercsv' required on Ruby versions < 1.9 +require 'fastercsv' unless Array.new.respond_to?(:to_csv) require 'retryable' require 't/collectable' require 't/core_ext/enumerable' require 't/core_ext/string' require 't/printable' @@ -26,86 +29,154 @@ def initialize(*) super @rcfile = RCFile.instance end - desc "add LIST_NAME SCREEN_NAME [SCREEN_NAME...]", "Add members to a list." - def add(list_name, screen_name, *screen_names) - screen_names.unshift(screen_name) - screen_names.map!(&:strip_ats) - screen_names.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_each do |user_id_group| + desc "add LIST USER [USER...]", "Add members to a list." + method_option :id, :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names." + def add(list, user, *users) + users.unshift(user) + if options['id'] + users.map!(&:to_i) + else + users.map!(&:strip_ats) + end + users.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_each do |user_id_group| retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do - client.list_add_members(list_name, user_id_group) + client.list_add_members(list, user_id_group) end end - number = screen_names.length - say "@#{@rcfile.default_profile[0]} added #{number} #{number == 1 ? 'member' : 'members'} to the list \"#{list_name}\"." + number = users.length + say "@#{@rcfile.default_profile[0]} added #{number} #{number == 1 ? 'member' : 'members'} to the list \"#{list}\"." say - say "Run `#{File.basename($0)} list remove #{list_name} #{screen_names.join(' ')}` to undo." + if options['id'] + say "Run `#{File.basename($0)} list remove --id #{list} #{users.join(' ')}` to undo." + else + say "Run `#{File.basename($0)} list remove #{list} #{users.map{|user| "@#{user}"}.join(' ')}` to undo." + end end - desc "create LIST_NAME [DESCRIPTION]", "Create a new list." + desc "create LIST [DESCRIPTION]", "Create a new list." method_option :private, :aliases => "-p", :type => :boolean - def create(list_name, description="") + def create(list, description="") opts = description.blank? ? {} : {:description => description} opts.merge!(:mode => 'private') if options['private'] - client.list_create(list_name, opts) - say "@#{@rcfile.default_profile[0]} created the list \"#{list_name}\"." + client.list_create(list, opts) + say "@#{@rcfile.default_profile[0]} created the list \"#{list}\"." end - desc "members [SCREEN_NAME] LIST_NAME", "Returns the members of a Twitter list." - method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created." + desc "information [USER/]LIST", "Retrieves detailed information about a Twitter list." + method_option :csv, :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format." + def information(list) + owner, list = list.split('/') + if list.nil? + list = owner + owner = @rcfile.default_profile[0] + else + owner = if options['id'] + owner.to_i + else + owner.strip_ats + end + end + list = client.list(owner, list) + if options['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, list.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), list.member_count, list.subscriber_count, list.following?, list.mode, "https://twitter.com#{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}"] + created_at = list.created_at > 6.months.ago ? list.created_at.strftime("%b %e %H:%M") : list.created_at.strftime("%b %e %Y") + array << ["Created at", created_at] + array << ["Members", number_with_delimiter(list.member_count)] + array << ["Subscribers", number_with_delimiter(list.subscriber_count)] + status = list.following ? "Following" : "Not following" + array << ["Status", status] + array << ["Mode", list.mode] + array << ["URL", "https://twitter.com#{list.uri}"] + print_table(array) + end + end + map %w(detail) => :information + + desc "members [USER/]LIST", "Returns the members of a Twitter list." + method_option :csv, :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format." method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites." method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers." - method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends." - method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships." - method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format." + method_option :friends, :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by total number of friends." + method_option :id, :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name." + method_option :listed, :aliases => "-s", :type => :boolean, :default => false, :desc => "Sort by number of list memberships." + method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format." + method_option :posted, :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted." method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort." method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets." method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted." - def members(*args) - list = args.pop - owner = args.pop || @rcfile.default_profile[0] - owner = owner.strip_ats + def members(list) + owner, list = list.split('/') + if list.nil? + list = owner + owner = @rcfile.default_profile[0] + else + owner = if options['id'] + owner.to_i + else + owner.strip_ats + end + end users = collect_with_cursor do |cursor| client.list_members(owner, list, :cursor => cursor, :include_entities => false, :skip_status => true) end - print_user_list(users) + print_users(users) end - desc "remove LIST_NAME SCREEN_NAME [SCREEN_NAME...]", "Remove members from a list." - def remove(list_name, screen_name, *screen_names) - screen_names.unshift(screen_name) - screen_names.map!(&:strip_ats) - screen_names.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_each do |user_id_group| + desc "remove LIST USER [USER...]", "Remove members from a list." + method_option :id, :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names." + def remove(list, user, *users) + users.unshift(user) + if options['id'] + users.map!(&:to_i) + else + users.map!(&:strip_ats) + end + users.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_each do |user_id_group| retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do - client.list_remove_members(list_name, user_id_group) + client.list_remove_members(list, user_id_group) end end - number = screen_names.length - say "@#{@rcfile.default_profile[0]} removed #{number} #{number == 1 ? 'member' : 'members'} from the list \"#{list_name}\"." + number = users.length + say "@#{@rcfile.default_profile[0]} removed #{number} #{number == 1 ? 'member' : 'members'} from the list \"#{list}\"." say - say "Run `#{File.basename($0)} list add #{list_name} #{screen_names.join(' ')}` to undo." + if options['id'] + say "Run `#{File.basename($0)} list add --id #{list} #{users.join(' ')}` to undo." + else + say "Run `#{File.basename($0)} list add #{list} #{users.map{|user| "@#{user}"}.join(' ')}` to undo." + end end - desc "timeline [SCREEN_NAME] LIST_NAME", "Show tweet timeline for members of the specified list." - method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created." - method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites." - method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers." - method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends." - method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships." - method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format." + desc "timeline [USER/]LIST", "Show tweet timeline for members of the specified list." + method_option :csv, :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format." + method_option :id, :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name." + method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format." method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results." method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort." - method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets." - method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted." - def timeline(*args) - list = args.pop - owner = args.pop || @rcfile.default_profile[0] - owner = owner.strip_ats + def timeline(list) + owner, list = list.split('/') + if list.nil? + list = owner + owner = @rcfile.default_profile[0] + else + owner = if options['id'] + owner.to_i + else + owner.strip_ats + end + end per_page = options['number'] || DEFAULT_NUM_RESULTS statuses = client.list_timeline(owner, list, :include_entities => false, :per_page => per_page) - print_status_list(statuses) + print_statuses(statuses) end map %w(tl) => :timeline end end