Files
MusicServer/sdk/lr/auth.ts
T

52 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 懒人听书登录(web 通道 m.lrts.me/ajax/logon)
// 参考社区下载器(yoval/lrts 等):POST form {account, pwd: base64(password)},
// 成功响应 json.phone 非空,Set-Cookie 种下会话;取流接口必须携带该会话
// (免费章节匿名也返回"收费章节未购买",2026-10-02 实测)。
import { httpFetch } from '../request.ts'
import { getCredentials, setCredentials } from '../auth/store.ts'
const UA_MI = 'Mozilla/5.0 (Linux; U; Android 4.1.1; zh-cn; MI2 Build/JRO03L) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 XiaoMi/MiuiBrowser/1.0'
const LOGON_URL = 'https://m.lrts.me/ajax/logon'
/** 账号密码登录(成功保存会话 Cookie) */
export const login = async({ account, password }: { account: string, password: string }) => {
const form = `account=${encodeURIComponent(account)}&pwd=${Buffer.from(String(password), 'utf8').toString('base64')}`
const { statusCode, body, headers } = await httpFetch(LOGON_URL, {
method: 'post',
headers: {
'User-Agent': UA_MI,
Referer: 'https://m.lrts.me/',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: form,
timeout: 15000,
}).promise as any
const b = body ?? {}
if (statusCode != 200 || !b.phone) {
const err = new Error(b.msg || '登录失败(账号或密码错误)')
;(err as any).status = 401
throw err
}
const setCookies = (headers as any)?.['set-cookie'] ?? []
const cookie = (Array.isArray(setCookies) ? setCookies : [setCookies])
.map((c: string) => String(c).split(';')[0].trim())
.filter(Boolean)
.join('; ')
if (!cookie) throw new Error('登录成功但未返回会话 Cookie')
setCredentials('lr', { cookie, phone: String(b.phone) })
return { logged: true, phone: String(b.phone) }
}
/** 登录会话 Cookie(未登录返回空串) */
export const getLrCookie = (): string => (getCredentials('lr') as any)?.cookie || ''
/** 登录状态 */
export const status = () => {
const cred = getCredentials('lr') as { cookie?: string, phone?: string, updatedAt?: string } | null
return cred?.cookie
? { logged: true, phone: cred.phone, updatedAt: cred.updatedAt }
: { logged: false }
}
export default { login, getLrCookie, status }