Skip to content

Commit

Permalink
feat: show faction reachability at during register
Browse files Browse the repository at this point in the history
  • Loading branch information
eseidel committed Oct 7, 2023
1 parent b605905 commit 84a22a5
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 103 deletions.
1 change: 1 addition & 0 deletions packages/cli/bin/cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:cli/logger.dart';
import 'package:cli/logic.dart';
import 'package:cli/net/auth.dart';
import 'package:cli/net/counts.dart';
import 'package:cli/net/register.dart';
import 'package:cli/printing.dart';
import 'package:db/db.dart';
import 'package:file/local.dart';
Expand Down
103 changes: 0 additions & 103 deletions packages/cli/lib/net/auth.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import 'package:cli/api.dart';
import 'package:cli/logger.dart';
import 'package:cli/net/counts.dart';
import 'package:cli/net/exceptions.dart';
import 'package:cli/net/queries.dart';
import 'package:cli/net/queue.dart';
import 'package:db/db.dart';
import 'package:file/file.dart';
Expand Down Expand Up @@ -66,103 +63,3 @@ Api defaultApi(
required int Function() getPriority,
}) =>
apiFromAuthToken(loadAuthToken(fs), db, getPriority: getPriority);

/// loadAuthTokenOrRegister loads the auth token from the given file system
/// or registers a new user and returns the auth token.
Future<String> loadAuthTokenOrRegister(
FileSystem fs,
Database db, {
String? callsign,
String? email,
String path = defaultAuthTokenPath,
}) async {
try {
return loadAuthToken(fs);
} catch (e) {
logger.info('No auth token found.');
// Otherwise, register a new user.
final handle = callsign ?? logger.prompt('What is your call sign?');
final token = await register(db, callsign: handle, email: email);
final file = fs.file(path);
await file.create(recursive: true);
await file.writeAsString(token);
return token;
}
}

Future<String> _tryRegister(
DefaultApi api, {
required String symbol,
required FactionSymbols faction,
String? email,
}) async {
final registerRequest = RegisterRequest(
symbol: symbol,
faction: faction,
email: email,
);
final registerResponse = await api.register(registerRequest: registerRequest);
return registerResponse!.data.token;
}

/// register registers a new user with the space traders api and
/// returns the auth token which should be saved and used for future requests.
/// If the call sign is already taken, it will prompt for the email address
/// associated with the call sign.
Future<String> register(
Database db, {
required String callsign,
String? email,
}) async {
final client = getApiClient(db, getPriority: () => 0);
final defaultApi = DefaultApi(client);

final factions = await fetchAllPages(FactionsApi(client), (api, page) async {
final response = await api.getFactions(page: page);
return (response!.data, response.meta);
}).toList();

final recruitingFactions = factions.where((f) => f.isRecruiting).toList();

// There are more factions in the game than players are allowed to join
// at the start, so we use RegisterRequestFactionEnum.
final faction = logger.chooseOne(
'Choose a faction:',
choices: recruitingFactions,
display: (faction) {
final f = factions.firstWhere((f) => f.symbol == faction.symbol);
return '${f.symbol} - ${f.description}';
},
);

try {
return await _tryRegister(
defaultApi,
symbol: callsign,
faction: faction.symbol,
email: email,
);
} on ApiException catch (e) {
if (!isReservedHandleException(e)) {
logger.err('Exception registering: $e\n');
rethrow;
}
}

// This was a reserved handle. Ask for the email associated with it.
try {
final email = logger.prompt(
'Call sign has been reserved between resets. Please enter the email '
'associated with this call sign to proceed:',
);
return await _tryRegister(
defaultApi,
symbol: callsign,
faction: faction.symbol,
email: email,
);
} on ApiException catch (e) {
logger.err('Exception registering: $e\n');
rethrow;
}
}
110 changes: 110 additions & 0 deletions packages/cli/lib/net/register.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import 'package:cli/cache/caches.dart';
import 'package:cli/logger.dart';
import 'package:cli/net/auth.dart';
import 'package:cli/net/exceptions.dart';
import 'package:db/db.dart';
import 'package:types/api.dart';

/// loadAuthTokenOrRegister loads the auth token from the given file system
/// or registers a new user and returns the auth token.
Future<String> loadAuthTokenOrRegister(
FileSystem fs,
Database db, {
String? callsign,
String? email,
String path = defaultAuthTokenPath,
}) async {
try {
return loadAuthToken(fs);
} catch (e) {
logger.info('No auth token found.');
// Otherwise, register a new user.
final handle = callsign ?? logger.prompt('What is your call sign?');
final token = await register(fs, db, callsign: handle, email: email);
final file = fs.file(path);
await file.create(recursive: true);
await file.writeAsString(token);
return token;
}
}

Future<String> _tryRegister(
DefaultApi api, {
required String symbol,
required FactionSymbols faction,
String? email,
}) async {
final registerRequest = RegisterRequest(
symbol: symbol,
faction: faction,
email: email,
);
final registerResponse = await api.register(registerRequest: registerRequest);
return registerResponse!.data.token;
}

/// register registers a new user with the space traders api and
/// returns the auth token which should be saved and used for future requests.
/// If the call sign is already taken, it will prompt for the email address
/// associated with the call sign.
Future<String> register(
FileSystem fs,
Database db, {
required String callsign,
String? email,
}) async {
final systemsCache = await SystemsCache.load(fs);
final clusterCache = SystemConnectivity.fromSystemsCache(systemsCache);

final client = getApiClient(db, getPriority: () => 0);
final defaultApi = DefaultApi(client);

final factionsApi = FactionsApi(client);
final factions = await loadFactions(db, factionsApi);

final recruitingFactions = factions.where((f) => f.isRecruiting).toList();

// There are more factions in the game than players are allowed to join
// at the start, so we use RegisterRequestFactionEnum.
final faction = logger.chooseOne(
'Choose a faction:',
choices: recruitingFactions,
display: (faction) {
final f = factions.firstWhere((f) => f.symbol == faction.symbol);
final reachable =
clusterCache.connectedSystemCount(f.headquartersSymbol.systemSymbol);
return '${f.symbol} - connected to $reachable systems';
},
);

try {
return await _tryRegister(
defaultApi,
symbol: callsign,
faction: faction.symbol,
email: email,
);
} on ApiException catch (e) {
if (!isReservedHandleException(e)) {
logger.err('Exception registering: $e\n');
rethrow;
}
}

// This was a reserved handle. Ask for the email associated with it.
try {
final email = logger.prompt(
'Call sign has been reserved between resets. Please enter the email '
'associated with this call sign to proceed:',
);
return await _tryRegister(
defaultApi,
symbol: callsign,
faction: faction.symbol,
email: email,
);
} on ApiException catch (e) {
logger.err('Exception registering: $e\n');
rethrow;
}
}

0 comments on commit 84a22a5

Please sign in to comment.