Module: Lich::Common::Authentication::CLI

Defined in:
documented/common/authentication/cli.rb

Class Method Summary collapse

Class Method Details

.decrypt_and_authenticate(char_entry, entry_data) ⇒ LaunchData?

Decrypts the character's password and authenticates with the game server.

Examples:

Authenticate a character

Lich::Common::Authentication::CLI.decrypt_and_authenticate(char_entry, entry_data)

Parameters:

  • char_entry (Hash)

    the character entry containing authentication details.

  • entry_data (Hash)

    the entry data containing additional information.

Returns:

  • (LaunchData, nil)

    returns launch data on successful authentication, or nil on failure.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'documented/common/authentication/cli.rb', line 97

def self.decrypt_and_authenticate(char_entry, entry_data)
  # Get encryption mode from YAML
  encryption_mode = (entry_data[:encryption_mode] || 'plaintext').to_sym

  # Decrypt the password
  begin
    plaintext_password = EntryStore.decrypt_password(
      char_entry[:password],
      mode: encryption_mode,
      account_name: char_entry[:username]
    )
  rescue StandardError => e
    Lich.log "error: Failed to decrypt password: #{e.message}"
    return nil
  end

  unless plaintext_password
    Lich.log "error: No password available for character"
    return nil
  end

  # Authenticate with game server
  begin
    auth_data = Authentication.authenticate(
      account: char_entry[:username],
      password: plaintext_password,
      character: char_entry[:char_name],
      game_code: char_entry[:game_code]
    )

    # Format and return launch data
    LaunchData.prepare(
      auth_data,
      char_entry[:frontend],
      char_entry[:custom_launch],
      char_entry[:custom_launch_dir]
    )
  rescue StandardError => e
    Lich.log "error: Authentication failed: #{e.message}"
    return nil
  end
end

.execute(character_name, game_code: nil, frontend: nil, custom_launch: nil, data_dir: nil) ⇒ LaunchData?

Executes the CLI login process for a character.

Examples:

Successful login

Lich::Common::Authentication::CLI.execute("Hero", game_code: "game123")

Parameters:

  • character_name (String)

    the name of the character to log in.

  • game_code (String, nil) (defaults to: nil)

    optional game code for the character.

  • frontend (String, nil) (defaults to: nil)

    optional frontend identifier.

  • custom_launch (String, nil) (defaults to: nil)

    optional custom launch parameters.

  • data_dir (String, nil) (defaults to: nil)

    optional directory for data files.

Returns:

  • (LaunchData, nil)

    returns launch data on success, or nil on failure.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'documented/common/authentication/cli.rb', line 29

def self.execute(character_name, game_code: nil, frontend: nil, custom_launch: nil, data_dir: nil)
  data_dir ||= DATA_DIR

  # Validate inputs
  unless character_name && !character_name.empty?
    Lich.log "error: Character name is required"
    return nil
  end

  # Validate master password availability before attempting login (required for Enhanced encryption mode)
  unless CLIPassword.validate_master_password_available
    Lich.log "error: Master password validation failed during CLI login"
    return nil
  end

  # Load raw YAML data (not decrypted yet)
  yaml_file = EntryStore.yaml_file_path(data_dir)
  unless File.exist?(yaml_file)
    Lich.log "error: No saved entries YAML file found"
    return nil
  end

  begin
    yaml_data = YAML.safe_load_file(yaml_file, permitted_classes: [Symbol])
    entry_data = LoginHelpers.symbolize_keys(yaml_data)
  rescue StandardError => e
    Lich.log "error: Failed to load YAML data: #{e.message}"
    return nil
  end

  # Find matching character(s) using login_helpers
  matching_entries = LoginHelpers.find_character_by_name_game_and_frontend(
    entry_data,
    character_name,
    game_code,
    frontend,
    custom_launch
  )

  if matching_entries.nil? || matching_entries.empty?
    Lich.log "error: No matching character found for: #{character_name}"
    return nil
  end

  # Select best match from candidates
  char_entry = LoginHelpers.select_best_fit(
    char_data_sets: matching_entries,
    requested_character: character_name,
    requested_instance: game_code,
    requested_fe: frontend
  )

  unless char_entry
    Lich.log "error: Could not select character entry from matches"
    return nil
  end

  # Decrypt password and authenticate
  decrypt_and_authenticate(char_entry, entry_data)
end