class Lyricsender::CLI::Commands::Send

Public Instance Methods

call(**options) click to toggle source
# File bin/lyricsender, line 91
def call(**options)

  ### warning - This part is duplicated and I cannot figure out how to fix it
  # Supports https://no-color.org
  env_no_color = false if ENV['NO_COLOR']

  pastel = Pastel.new(enabled: env_no_color)
  config = TTY::Config.new
  prompt = TTY::Prompt.new(enable_color: env_no_color)

  config.filename = "lyricsender"
  config.extname = ".toml"
  config_append_path = "#{Dir.home}/.config"
  config.append_path config_append_path

  unless OS.mac?
    puts
    print pastel.bold.red "(!) Note: only macOS is supported"
    puts pastel.red " (this uses iMessage and AppleScript)."
    if prompt.yes? "Continue anyway?"
      nil
    else
      exit 1
    end
  end
  ### end duplicated part

  unless config.exist?
    puts pastel.red "Oops, you need to run the setup command first"
    puts pastel.red "(this script requires an access key from Genius)"
    puts pastel.bold.red "Try running `lyricsender setup`. Thanks!"
    exit 1
  end

  Genius.access_token = config.read["token"]

  begin
    search = options.fetch(:search)
  rescue
    search = prompt.ask("#{pastel.bold "→ Search for a song…"}", convert: :str, required: true)
  end

  songs = Genius::Song.search search
  songs_list = Hash.new
  songs.each do |song|
    songs_list["#{song.title} - #{song.primary_artist.name}"] = song.url
  end

  begin
    song = options.fetch(:song)
  rescue
    nil
  end

  unless song
    song = prompt.select("#{pastel.bold "→ Please choose a song:"}", songs_list.keys)
  end
  song_url = songs_list[song]

  begin
    to = options.fetch(:to).split(" ")
  rescue
    to = prompt.ask("#{pastel.bold "→ Please enter one or more recipients"} (phone numbers or email addresses), separated by commas…", convert: :array, required: true)
  end

  begin
    delay = options.fetch(:delay)
  rescue
    choices = {"no delay between messages": false, "prompt between sending messages": true, "choose a time to delay": nil}
    delay = prompt.select("#{pastel.bold "→ Would you like to wait between sending messages?"}", choices)
    if delay.nil?
      delay = prompt.ask("#{pastel.bold "→ How many seconds would you like to wait between messages?"}", convert: :int, required: true)
    end
  end

  doc = Nokogiri::HTML(URI.open(song_url.to_s))
  lyrics = Array.new
  doc.css('div[class^="Lyrics__Container-"], div[class*=" Lyrics__Container-"]').each do |match|
    # The following line removes newlines and the lines that are like [Intro] and [Verse 1] etc
    lyric_block = Nokogiri::HTML(match.to_s.gsub("<br>", "\n").gsub(/\[.*\]$/i, "").gsub("[Intro]", "")).content.gsub(/\n+|\r+/, "\n").squeeze("\n").strip
    lyric_block.each_line do |line|
      lyrics << line
    end
  end

  if lyrics.length == 0
    puts pastel.red "The song you chose appears to be empty…"
    exit 1
  end

  begin
    yes = options.fetch(:yes)
  rescue
    yes = false
  end

  unless yes
    puts pastel.italic.dim "Here's what will be sent:"
    lyrics.each do |line|
      puts "  #{line}"
    end
    yes = prompt.yes? "#{pastel.bold "→ Send"} #{pastel.underline.bold song} #{pastel.bold "to"} #{pastel.underline.bold to.join(",")} (#{lyrics.length} messages)?"
  end

  if yes
    sender = Imessage::Sender.new
    counter = 0
    bar = TTY::ProgressBar.new("sending… [:bar] :current/:total • :eta", total: lyrics.length, bar_format: :box, clear: true) unless delay == true
    lyrics.each_with_index do |line, index|
      send_line = true
      if delay == true
        if prompt.yes? "(#{index + 1}/#{lyrics.length}) Send line #{pastel.italic line.strip}?"
          nil
        else
          send_line = false
          print pastel.bold.red "Line not sent"
          puts pastel.red " (continuing to next line)"
        end
      elsif delay.is_a? Integer
        sleep delay
      end
      if send_line
        sender.deliver({
          # The gsub below replaces single quotes like those in contractions with '"'"' because the iMessage gem shells out to `oascript` to send messages and the single quotes otherwise mess up that part ('"'"' is interpreted as just ')
          text: line.gsub('\'', '\'"\'"\'').strip,
          contacts: to
        })
        counter += 1
        bar.advance if bar
      end
    end
    print pastel.bold.green "Success"
    puts pastel.green " (probably)! #{counter} messages sent."
  else
    puts pastel.bold.italic.red "Messages not sent."
    exit 1
  end
end