-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconvert-gemini.auth.ts
More file actions
92 lines (74 loc) · 2.19 KB
/
convert-gemini.auth.ts
File metadata and controls
92 lines (74 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
89
90
91
92
#!/usr/bin/env bun
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"
import os from "node:os"
import path from "node:path"
type Gemini = {
access_token?: string
refresh_token?: string
expiry_date?: number | string
}
type OAuth = {
type: "oauth"
refresh: string
access: string
expires: number
}
type Auth = Record<string, OAuth | Record<string, unknown>>
function fail(msg: string): never {
console.error(`[convert-gemini.auth] ${msg}`)
process.exit(1)
}
function home() {
return process.env.HOME || os.homedir()
}
function data() {
return process.env.XDG_DATA_HOME || path.join(home(), ".local", "share")
}
function src() {
return process.env.GEMINI_OAUTH_CREDS_PATH || path.join(home(), ".gemini", "oauth_creds.json")
}
function dst() {
return process.env.OPENCODE_AUTH_PATH || path.join(data(), "opencode", "auth.json")
}
function ms(value: unknown) {
if (typeof value === "number" && Number.isFinite(value)) {
return value < 1e12 ? value * 1000 : value
}
if (typeof value === "string" && value.trim()) {
const num = Number(value)
if (Number.isFinite(num)) return num < 1e12 ? num * 1000 : num
const date = Date.parse(value)
if (!Number.isNaN(date)) return date
}
return Date.now() + 55 * 60 * 1000
}
async function json(file: string) {
return JSON.parse(await readFile(file, "utf8")) as Record<string, unknown>
}
async function existing(file: string): Promise<Auth> {
try {
return (await json(file)) as Auth
} catch {
return {}
}
}
async function main() {
const source = src()
const target = dst()
const creds = (await json(source)) as Gemini
if (!creds.refresh_token) fail(`missing refresh_token in ${source}`)
if (!creds.access_token) fail(`missing access_token in ${source}`)
const auth = await existing(target)
auth.google = {
type: "oauth",
refresh: creds.refresh_token,
access: creds.access_token,
expires: ms(creds.expiry_date),
}
await mkdir(path.dirname(target), { recursive: true })
await writeFile(target, `${JSON.stringify(auth, null, 2)}\n`, { mode: 0o600 })
await chmod(target, 0o600)
}
await main().catch((err) => {
fail(err instanceof Error ? err.message : String(err))
})