···11+import { type Config, loadConfig, updateConfig } from "~/lib/config.ts";
22+import { dim, log } from "~/cli/formatter.ts";
33+import { AppError, describe } from "~/lib/errors.ts";
44+import { Ok, Result } from "~/lib/result.ts";
55+import { ask } from "~/utils/prompt.ts";
66+import { italic } from "@std/fmt/colors";
77+88+type BootstrapConfig = Omit<Required<Config>, "password" | "username">;
99+1010+export const SECRET_WARNING = italic(dim(
1111+ "\n\nYour Last.fm credentials are used only to authenticate with Last.fm services. " +
1212+ "They are sent directly to Last.fm over a secure connection and are not stored locally after authentication.",
1313+));
1414+1515+export async function requireBaseConfig(): Promise<Result<BootstrapConfig, AppError>> {
1616+ const result = await loadConfig();
1717+1818+ if (result.ok && result.value.apiKey && result.value.secret) {
1919+ return Ok(result.value as BootstrapConfig);
2020+ }
2121+2222+ if (!result.ok && result.error.tag !== "not_found") {
2323+ return result;
2424+ }
2525+2626+ log.warn("No API credentials found. Let's set up scrobkit :3\n");
2727+2828+ const apiKey = ask(" What is your Last.fm API key?");
2929+ const sharedSecret = ask(SECRET_WARNING + "\n\n What about your key's shared secret, eh?", true);
3030+3131+ const saved = await updateConfig({ apiKey, secret: sharedSecret });
3232+ if (!saved.ok) {
3333+ return saved;
3434+ }
3535+3636+ return Ok(saved.value as BootstrapConfig);
3737+}