class Ayadn::Workers

Public Class Methods

epoch_to_date(epoch) click to toggle source
# File lib/ayadn/workers.rb, line 579
def self.epoch_to_date(epoch)
  Time.at(epoch).to_time
end
new(status = Status.new) click to toggle source
# File lib/ayadn/workers.rb, line 5
def initialize status = Status.new
  @status = status
end

Public Instance Methods

add_arobase(username) click to toggle source
# File lib/ayadn/workers.rb, line 436
def add_arobase username
  add_arobase_if_missing(username)
end
add_arobase_if_missing(username) click to toggle source
# File lib/ayadn/workers.rb, line 440
def add_arobase_if_missing(username) # expects an array of username(s), works on the first one and outputs a string
  unless username.first == "me"
    username = username.first.chars
    username.unshift("@") unless username.first == "@"
  else
    username = "me".chars
  end
  username.join
end
add_arobases_to_usernames(args) click to toggle source
# File lib/ayadn/workers.rb, line 459
def add_arobases_to_usernames args
  args.map do |username|
    if username == 'me'
      who_am_i
    else
      temp = username.chars
      temp.unshift("@") unless temp.first == "@"
      temp.join
    end
  end
end
all_but_me(usernames) click to toggle source
# File lib/ayadn/workers.rb, line 574
def all_but_me usernames
  arr = usernames.select { |user| user != 'me' && user != Settings.config.identity.username }
  at(arr)
end
at(usernames) click to toggle source
# File lib/ayadn/workers.rb, line 471
def at usernames
  usernames.map do |user|
    if user == 'me'
      'me'
    elsif user[0] == '@'
      user
    else
      "@#{user}"
    end
  end
end
build_aliases_list(list) click to toggle source
# File lib/ayadn/workers.rb, line 17
def build_aliases_list(list)
  table = init_table
  table.title = "List of your channel aliases".color(:cyan) + "".color(:white)
  table.style = table_borders()
  table.headings = [ 'Channel', 'Alias' ]
  list.each_with_index do |obj, index|
    table << [obj[0].to_s.color(:green), obj[1].color(:red)]
    if index + 1 != list.length && !Settings.options.timeline.compact
      table << :separator
    end
  end
  table
end
build_blacklist_list(list) click to toggle source
# File lib/ayadn/workers.rb, line 31
def build_blacklist_list(list)
  table = init_table
  table.title = "Your blacklist".color(:cyan) + "".color(:white)
  table.style = table_borders()
  table.headings = [ 'Name', 'Type' ]
  list.sort!
  list.each_with_index do |obj, index|
    table << ["#{obj[1].capitalize}".to_s.force_encoding("UTF-8").color(:green), "#{obj[0]}".to_s.force_encoding("UTF-8").color(:red)]
    if index + 1 != list.length && !Settings.options.timeline.compact
      table << :separator
    end
  end
  table
end
build_blocked_list(list, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 86
def build_blocked_list(list, options = {})
  table = init_table
  table.title = "List of users you blocked".color(:cyan) + "".color(:white)
  table.style = table_borders()
  build_users_list(build_users_array(list), table, options)
end
build_channels(stream, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 321
def build_channels(stream, options = {})
  bucket = []
  stream = [stream] unless stream.is_a?(Array)
  if options[:channels]
    @status.say_yellow :downloading, "list of channels and their users credentials"
    @status.say_info "it could take a while if there are many results and users"
  else
    @status.say_yellow :downloading, "the channels and their users attributes (owners, writers, editors and readers)"
    @status.say_info "users are recorded in a database for later filtering and analyzing"
    @status.say_info "it could take a while if there are many results"
  end

  chan = Struct.new(:id, :num_messages, :subscribers, :type, :owner, :annotations, :readers, :editors, :writers, :you_subscribed, :unread, :recent_message_id, :recent_message)

  no_user = {}
  api = API.new
  stream.each do |ch|
    next if ch.id.nil?
    unless ch.writers.user_ids.empty?
      @status.say_cyan :parsing, "channel #{ch.id}"
      usernames = []
      ch.writers.user_ids.each do |id|
        next if no_user[id]
        db = Databases.find_user_by_id(id)
        if db.nil?
          @status.say_yellow :downloading, "user #{id}"
          resp = api.get_user(id)

          if resp['meta']['code'] != 200
            @status.say_error "can't get user #{id}'s data, skipping"
            no_user[id] = true
            next
          end

          the_username = resp['data']['username']
          @status.say_yellow :recording, "@#{the_username}"

          usernames << "@" + the_username
          Databases.add_to_users_db(id, the_username, resp['data']['name'])
        else
          the_username = "@#{db}"
          @status.say_blue :match, "#{the_username} is already in the database"

          usernames << the_username
        end
      end
      usernames << Settings.config.identity.handle unless usernames.length == 1 && usernames.first == Settings.config[:identity][:handle]
      writers = usernames.join(", ")
    else
      writers = Settings.config.identity.handle
    end
    if ch.has_unread
      unread = "This channel has unread message(s)"
    else
      unread = "No unread messages"
    end
    bucket << chan.new(ch.id, ch.counts.messages, ch.counts.subscribers, ch.type, ch.owner, ch.annotations, ch.readers, ch.editors, writers, ch.you_subscribed, unread, ch.recent_message_id, ch.recent_message)
  end
  clear_screen
  bucket
end
build_followers_list(list, target, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 68
def build_followers_list(list, target, options = {})
  table = init_table
  table.title = if target == "me"
    "List of your followers".color(:cyan) + "".color(:white)
  else
    "List of users following ".color(:cyan) + "#{target}".color(:red) + "".color(:white)
  end
  table.style = table_borders()
  build_users_list(build_users_array(list), table, options)
end
build_followings_list(list, target, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 56
def build_followings_list(list, target, options = {}) #takes a hash of users with ayadn format
  table = init_table
  table.title = if target == "me"
    "List of users you're following".color(:cyan) + "".color(:white)
  else
    "List of users ".color(:cyan) + "#{target}".color(:red) + " is following ".color(:cyan) + "".color(:white)
  end
  table.style = table_borders()
  users_list = build_users_array(list)
  build_users_list(users_list, table, options)
end
build_muted_list(list, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 79
def build_muted_list(list, options = {})
  table = init_table
  table.title = "List of users you muted".color(:cyan) + "".color(:white)
  table.style = table_borders()
  build_users_list(build_users_array(list), table, options)
end
build_posts(posts, niceranks = {}) click to toggle source
# File lib/ayadn/workers.rb, line 128
def build_posts(posts, niceranks = {})
  # skip objects in blacklist unless force
  results = []
  posts.each.with_index(1) do |post, index|
    unless Settings.global.force
      if Settings.options.blacklist.active
        if Databases.is_in_blacklist?('client', post.source.name.downcase)
            Debug.skipped({source: post.source.name})
            next
        end
      end
    end
    unless Settings.global.force
      if Settings.options.blacklist.active
        if Databases.is_in_blacklist?('user', post.user.username.downcase)
          Debug.skipped({user: post.user.username})
          next
        end
      end
    end
    hashtags = extract_hashtags(post)
    @skip = false
    unless Settings.global.force
      if Settings.options.blacklist.active
        hashtags.each do |tag|
          if Databases.is_in_blacklist?('hashtag', tag.downcase)
            @skip = true
            Debug.skipped({hashtag: tag})
            break
          end
        end
      end
    end
    next if @skip
    mentions = extract_mentions(post)
    unless Settings.global.force
      if Settings.options.blacklist.active
        mentions.each do |m|
          if Databases.is_in_blacklist?('mention', m.downcase)
            @skip = true
            Debug.skipped({mention: m})
            break
          end
        end
      end
    end
    next if @skip
    unless Settings.global.force
      if Settings.options.blacklist.active
        post.text.split(" ").each do |word|
          target_word = word.gsub(/[~:-;,?!\'&`^=+<>*%()\/"“”’°£$€.…]/, "")
          if Databases.is_in_blacklist?('word', target_word.downcase)
            Debug.skipped({word: target_word})
            @skip = true
            break
          end
        end
      end
    end
    next if @skip
    
    # create custom objects from ADN response
    filtered = FilteredPost.new(post) 
    
    user_id_int = post.user.id.to_i
    if niceranks[user_id_int]
      filtered.nicerank = niceranks[user_id_int][:rank]
      filtered.is_human = niceranks[user_id_int][:is_human]
    else
      filtered.nicerank = false
      filtered.is_human = 'unknown'
    end

    if !post.user.name.blank?
      filtered.name = post.user.name.force_encoding("UTF-8")
    else
      filtered.name = "(no name)"
    end

    source = post.source.name.force_encoding("UTF-8")

    filtered.count = index
    filtered.id = post.id.to_i
    filtered.thread_id = post.thread_id
    filtered.username = post.user.username
    filtered.user_id = post.user.id.to_i
    filtered.handle = "@#{post.user.username}"
    filtered.type = post.user.type
    filtered.date = parsed_time(post.created_at)
    filtered.date_short = parsed_time_short(post.created_at)
    filtered.you_starred = post.you_starred
    filtered.source_name = source
    filtered.source_link = post.source.link
    filtered.canonical_url = post.canonical_url
    filtered.tags = hashtags
    filtered.links = extract_links(post)
    filtered.mentions = mentions
    filtered.directed_to = mentions.first || false
    filtered.checkins, filtered.has_checkins = extract_checkins(post)

    if !post.repost_of.nil?
      filtered.is_repost = true
      filtered.repost_of = post.repost_of.id
      filtered.original_poster = post.repost_of.user.username
    else
      filtered.is_repost = false
      filtered.repost_of = nil
      filtered.original_poster = post.user.username
    end

    unless post.text.blank?
      filtered.raw_text = post.text
      filtered.text = colorize_text(post.text, mentions, hashtags)
    else
      filtered.raw_text = ""
      filtered.text = "(no text)"
    end

    unless post.num_stars.nil? || post.num_stars == 0
      filtered.is_starred = true
      filtered.num_stars = post.num_stars
    else
      filtered.is_starred = false
      filtered.num_stars = 0
    end

    if !post.num_replies.nil?
      filtered.num_replies = post.num_replies
    else
      filtered.num_replies = 0
    end

    if !post.reply_to.nil?
      filtered.is_reply = true
      filtered.reply_to = post.reply_to
    else
      filtered.is_reply = false
      filtered.reply_to = nil
    end
    if !post.num_reposts.nil?
      filtered.num_reposts = post.num_reposts
    else
      filtered.num_reposts = 0
    end

    results << filtered

  end

  results
end
build_reposted_list(list, target) click to toggle source
# File lib/ayadn/workers.rb, line 46
def build_reposted_list(list, target)
  title = "List of users who reposted post ".color(:cyan) + "#{target}".color(:red) + "".color(:white)
  build_reposted_or_starred_list(list, title)
end
build_starred_list(list, target) click to toggle source
# File lib/ayadn/workers.rb, line 51
def build_starred_list(list, target)
  title = "List of users who starred post ".color(:cyan) + "#{target}".color(:red) + "".color(:white)
  build_reposted_or_starred_list(list, title)
end
build_users_list(list, table, options = {}) click to toggle source
# File lib/ayadn/workers.rb, line 93
def build_users_list(list, table, options = {})
  users = at(list.map {|obj| obj[:username]})
  ids = list.map {|obj| obj[:id].to_i}
  ranks = NiceRank.new.from_ids(ids)
  table << ['USERNAME'.color(:red), 'NAME'.color(:red), 'POSTS'.color(:red)]
  table << :separator
  arr = []
  if options[:username]
    list.sort_by! { |obj| obj[:username] }
  elsif options[:name]
    list.sort_by! { |obj| obj[:name].nil? ? "(no name)" : obj[:name].downcase }
  elsif options[:posts]
    list.sort_by! { |obj| [obj[:posts], obj[:username]] }
  end
  list.each do |obj|
    obj[:name] = "" if obj[:name].nil?
    obj[:username].length > 23 ? username = "#{obj[:username][0..20]}..." : username = obj[:username]
    obj[:name].length > 23 ? name = "#{obj[:name][0..20]}..." : name = obj[:name]
    arr << [ "@#{username} ".color(Settings.options.colors.username), "#{name.to_s.force_encoding('UTF-8')}", obj[:posts] ]
  end
  if options[:reverse]
    arr.reverse!
  end
  if Settings.options.formats.list.reverse
    arr.reverse!
  end
  arr.each_with_index do |obj, index|
    table << arr[index]
    if index + 1 != arr.length && !Settings.options.timeline.compact
      table << :separator
    end
  end
  table
end
clear_screen() click to toggle source
# File lib/ayadn/workers.rb, line 383
def clear_screen
  puts "\e[H\e[2J"
end
colorize_text(text, mentions, hashtags) click to toggle source
# File lib/ayadn/workers.rb, line 495
def colorize_text(text, mentions, hashtags)
  reg_split = '[~:-;,?!\'&`^=+<>*%()\/"“”’°£$€.…]'
  reg_tag = '#([[:alpha:]0-9_]{1,255})(?![\w+])'
  reg_mention = '@([A-Za-z0-9_]{1,20})(?![\w+])'
  reg_sentence = '^.+[\r\n]*'
  handles, words, sentences = [], [], []
  mentions.each {|username| handles << "@#{username}"}
  hashtag_color = Settings.options.colors.hashtags
  mention_color = Settings.options.colors.mentions
  text.scan(/#{reg_sentence}/) do |sentence|
    sentence.split(' ').each do |word|

      word_chars = word.chars
      sanitized, word = [], []
      word_chars.each do |ch|
        if UnicodeUtils.general_category(ch) == :Other_Symbol
          sanitized << "#{ch} "
        elsif UnicodeUtils.char_name(ch).nil?
          next
        else
          sanitized << ch
        end
      end
      word = sanitized.join

      if word =~ /#\w+/
        slices = word.split('#')
        has_h = false
        slices.each do |tag|
          has_h = true if hashtags.include?(tag.downcase.scan(/[[:alpha:]0-9_]/).join(''))
        end
        if has_h
          if slices.length > 1
            words << slices.join('#').gsub(/#{reg_tag}/, '#\1'.color(hashtag_color))
          else
            words << word.gsub(/#{reg_tag}/, '#\1'.color(hashtag_color))
          end
        else
          words << word
        end
      elsif word =~ /@\w+/
        enc = []
        warr = word.split(' ')
        warr.each do |w|
          @str = def_str(w, reg_split)
          if handles.include?(@str.downcase)
            if warr.length == 1
              enc << w.gsub(/#{reg_mention}/, '@\1'.color(mention_color))
            else
              enc << " #{w.gsub(/#{reg_mention}/, '@\1'.color(mention_color))}"
            end
          else
            enc << w
          end
        end
        words << enc.join
      else
        words << word
      end
    end
    sentences << words.join(' ')
    words = Array.new
  end
  if Settings.options.timeline.compact
    without_linebreaks = sentences.keep_if { |s| s != "" }
    without_linebreaks.join("\n")
  else
    sentences.join("\n")
  end
end
extract_hashtags(post) click to toggle source
# File lib/ayadn/workers.rb, line 313
def extract_hashtags(post)
  post.entities.hashtags.map { |h| h.name }
end
extract_mentions(post) click to toggle source
# File lib/ayadn/workers.rb, line 317
def extract_mentions(post)
  post.entities.mentions.map { |m| m.name }
end
extract_users(resp) click to toggle source
# File lib/ayadn/workers.rb, line 487
def extract_users(resp)
  users_hash = {}
  resp['data'].each do |item|
    users_hash[item['id']] = [item['username'], item['name'], item['you_follow'], item['follows_you'], item['counts']['posts']]
  end
  users_hash
end
get_channel_id_from_alias(channel_id) click to toggle source
# File lib/ayadn/workers.rb, line 406
def get_channel_id_from_alias(channel_id)
  unless channel_id.is_integer?
    orig = channel_id
    channel_id = Databases.get_channel_id(orig)
    if channel_id.nil?
      Errors.warn("Alias '#{orig}' doesn't exist.")
      @status.no_alias
      exit
    end
  end
  channel_id
end
get_original_id(post_id, resp) click to toggle source
# File lib/ayadn/workers.rb, line 395
def get_original_id(post_id, resp)
  if resp['data']['repost_of']
    @status.redirecting
    id = resp['data']['repost_of']['id']
    Errors.repost(post_id, id)
    return id
  else
    return post_id
  end
end
get_post_from_index(id) click to toggle source
# File lib/ayadn/workers.rb, line 423
def get_post_from_index id
  Databases.get_post_from_index id
end
get_real_post_id(post_id) click to toggle source
# File lib/ayadn/workers.rb, line 427
def get_real_post_id post_id
  id = post_id.to_i
  if id <= 200
    resp = get_post_from_index(id)
    post_id = resp['id']
  end
  post_id
end
length_of_index() click to toggle source
# File lib/ayadn/workers.rb, line 419
def length_of_index
  Databases.get_index_length
end
parsed_time(string) click to toggle source
# File lib/ayadn/workers.rb, line 387
def parsed_time(string)
  "#{string[0...10]} #{string[11...19]}"
end
parsed_time_short(string) click to toggle source
# File lib/ayadn/workers.rb, line 391
def parsed_time_short(string)
  "#{string[11...19]}"
end
remove_arobase_if_present(args) click to toggle source
# File lib/ayadn/workers.rb, line 450
def remove_arobase_if_present args
  args.map! do |username|
    temp = username.chars
    temp.shift if temp.first == "@"
    temp.join
  end
  args
end
table_borders() click to toggle source
# File lib/ayadn/workers.rb, line 9
def table_borders
  if Settings.options.formats.table.borders
    { :width => Settings.options.formats.table.width, border_x: '—', border_i: '+', border_y: '|' }
  else
    { :width => Settings.options.formats.table.width, border_x: ' ', border_i: ' ', border_y: ' ' }
  end
end
who_am_i() click to toggle source
# File lib/ayadn/workers.rb, line 483
def who_am_i
  Databases.active_account(Amalgalite::Database.new(Dir.home + "/ayadn/accounts.sqlite"))[2]
end

Private Instance Methods

build_reposted_or_starred_list(list, title) click to toggle source
# File lib/ayadn/workers.rb, line 585
def build_reposted_or_starred_list list, title
  table = init_table
  table.title = title
  users_list = []
  list.each do |obj|
    obj['name'].nil? ? name = "" : name = obj['name'].to_s.force_encoding("UTF-8")
    users_list << {:username => obj['username'], :name => name, :you_follow => obj['you_follow'], :follows_you => obj['follows_you'], :id => obj['id'], :posts => obj['counts']['posts']}
  end
  table.style = table_borders()
  return users_list, table
end
build_users_array(list) click to toggle source
# File lib/ayadn/workers.rb, line 614
def build_users_array(list)
  users = list.map do |key, value|
    {:username => value[0], :name => value[1], :you_follow => value[2], :follows_you => value[3], :id => key, :posts => value[4]}
  end
  return users
end
def_str(word, reg_split) click to toggle source
# File lib/ayadn/workers.rb, line 597
def def_str(word, reg_split)
  splitted = word.split(/#{reg_split}/) if word =~ /#{reg_split}/
  if splitted
    splitted.each {|d| @str = d if d =~ /@\w+/}
    return word if @str.nil?
    @str
  else
    word
  end
end
extract_checkins(post) click to toggle source
# File lib/ayadn/workers.rb, line 621
def extract_checkins(post)
  has_checkins = false
  checkins = {}
  unless post.annotations.blank?
    post.annotations.each do |anno|
      anno_value = anno.value
      case anno.type
      when "net.app.core.checkin", "net.app.ohai.location"
        has_checkins = true
        checkins = {
          name: anno_value['name'],
          address: anno_value['address'],
          address_extended: anno_value['address_extended'],
          locality: anno_value['locality'],
          postcode: anno_value['postcode'],
          country_code: anno_value['country_code'],
          website: anno_value['website'],
          telephone: anno_value['telephone']
        }
        unless anno_value['categories'].nil?
          unless anno_value['categories'][0].nil?
            checkins[:categories] = anno_value['categories'][0]['labels'].join(", ")
          end
        end
        unless anno_value['factual_id'].nil?
          checkins[:factual_id] = anno_value['factual_id']
        end
        unless anno_value['longitude'].nil?
          checkins[:longitude] = anno_value['longitude']
          checkins[:latitude] = anno_value['latitude']
        end
        unless anno_value['title'].nil?
          checkins[:title] = anno_value['title']
        end
        unless anno_value['region'].nil?
          checkins[:region] = anno_value['region']
        end
      end
    end
  end
  return checkins, has_checkins
end
init_table() click to toggle source
# File lib/ayadn/workers.rb, line 608
def init_table
  Terminal::Table.new do |t|
    t.style = { :width => Settings.options.formats.table.width }
  end
end