Class: Mytotp::Commands::Generate

Inherits:
Dry::CLI::Command
  • Object
show all
Defined in:
lib/mytotp/commands/generate.rb

Overview

Class command for generate a totp token.

Instance Method Summary collapse

Instance Method Details

#call(service: nil, username: nil, **options) ⇒ Object

call the command function



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/mytotp/commands/generate.rb', line 16

def call(service: nil, username: nil, **options)
  # find services
  services = Mytotp::Models::Service.where(Sequel.ilike(:service, "%#{service}%"))
                                    .where(Sequel.ilike(:username, "%#{username}%"))
  # select one service
  service =
    if services.count == 1
      found_one_message(services)
      services.first
    elsif services.count > 1
      select_one(services)
    else
      select_one(Mytotp::Models::Service.all)
    end
  # generate the complete message with the code
  generate_code(service, options.fetch(:mode))
end

#clear_last_lineObject

clear last line in the console



82
83
84
85
86
87
# File 'lib/mytotp/commands/generate.rb', line 82

def clear_last_line
  # Clear the line
  print(CLI::UI::ANSI.previous_line + CLI::UI::ANSI.clear_to_end_of_line)
  # Force StdoutRouter to prefix
  print("#{CLI::UI::ANSI.previous_line} \n")
end

#copy_to_clipboard(code) ⇒ Boolean

Copy code to clipboar



121
122
123
124
# File 'lib/mytotp/commands/generate.rb', line 121

def copy_to_clipboard(code)
  Clipboard.copy(code)
  Clipboard.paste == code
end

#found_one_message(services) ⇒ Object

Print message when is found one



37
38
39
40
# File 'lib/mytotp/commands/generate.rb', line 37

def found_one_message(services)
  puts CLI::UI.fmt "{{green:Service:}} #{services.first.service.capitalize}"
  puts CLI::UI.fmt "{{green:Username:}} #{services.first.username.capitalize}"
end

#generate_code(service, mode) ⇒ Object

Generate the complete message with the code



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/mytotp/commands/generate.rb', line 58

def generate_code(service, mode)
  totp = ROTP::TOTP.new(service.key, interval: service.period, digits: service.digits)
  if mode == 'continuos'
    # infinit loop
    loop do
      actual_code = totp.now
      message_code(actual_code)
      loop do
        message_valid_for(service, totp)
        sleep 1
        clear_last_line
        break unless totp.verify(actual_code)
      end
      clear_last_line
    end
  else
    # print once
    message_code(totp.now)
    message_valid_for(service, totp)
  end
end

#message_code(totp) ⇒ Object

Print the code



109
110
111
112
113
114
115
# File 'lib/mytotp/commands/generate.rb', line 109

def message_code(totp)
  if copy_to_clipboard(totp)
    puts CLI::UI.fmt "{{green:Current TOTP:}} #{totp} - {{green:Copy!}}"
  else
    puts CLI::UI.fmt "{{green:Current TOTP:}} #{totp} - {{red:It can't be copy.Do it manually.}}"
  end
end

#message_valid_for(service, totp) ⇒ Object

Print valid for



102
103
104
# File 'lib/mytotp/commands/generate.rb', line 102

def message_valid_for(service, totp)
  puts CLI::UI.fmt "{{green:Valid for:}} #{valid_for(service, totp)} seconds"
end

#select_one(services) ⇒ Mytotp::Models::Service

Ask which service when we have more than one found.



46
47
48
49
50
51
52
# File 'lib/mytotp/commands/generate.rb', line 46

def select_one(services)
  CLI::UI::Prompt.ask('Which service?') do |handler|
    services.each do |s|
      handler.option("#{s.service} : #{s.username}") { |_selection| s }
    end
  end
end

#valid_for(service, totp) ⇒ Integer

Count seconds



94
95
96
# File 'lib/mytotp/commands/generate.rb', line 94

def valid_for(service, totp)
  (service.period - (Time.now - Time.at(totp.verify(totp.now)))).round
end