| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /*
- Copyright (C) 2025 QuantumNous
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
- For commercial licensing, please contact support@quantumnous.com
- */
- import { API } from './api';
- /**
- * 按需获取单个令牌的真实 key
- * @param {number|string} tokenId
- * @returns {Promise<string>} 返回不带 sk- 前缀的真实 token key
- */
- export async function fetchTokenKey(tokenId) {
- const response = await API.post(`/api/token/${tokenId}/key`);
- const { success, data, message } = response.data || {};
- if (!success || !data?.key) {
- throw new Error(message || 'Failed to fetch token key');
- }
- return data.key;
- }
- /**
- * 获取可用的 token keys
- * @returns {Promise<string[]>} 返回 active 状态的不带 sk- 前缀的真实 token key 数组
- */
- export async function fetchTokenKeys() {
- try {
- const response = await API.get('/api/token/?p=1&size=10');
- const { success, data } = response.data;
- if (!success) throw new Error('Failed to fetch token keys');
- const tokenItems = Array.isArray(data) ? data : data.items || [];
- const activeTokens = tokenItems.filter((token) => token.status === 1);
- const keyResults = await Promise.allSettled(
- activeTokens.map((token) => fetchTokenKey(token.id)),
- );
- return keyResults
- .filter((result) => result.status === 'fulfilled' && result.value)
- .map((result) => result.value);
- } catch (error) {
- console.error('Error fetching token keys:', error);
- return [];
- }
- }
- /**
- * 获取服务器地址
- * @returns {string} 服务器地址
- */
- export function getServerAddress() {
- let status = localStorage.getItem('status');
- let serverAddress = '';
- if (status) {
- try {
- status = JSON.parse(status);
- serverAddress = status.server_address || '';
- } catch (error) {
- console.error('Failed to parse status from localStorage:', error);
- }
- }
- if (!serverAddress) {
- serverAddress = window.location.origin;
- }
- return serverAddress;
- }
- export const CHANNEL_CONN_CLIPBOARD_TYPE = 'newapi_channel_conn';
- /**
- * @param {string} key - 完整的 API key(含 sk- 前缀)
- * @param {string} url - 服务器地址
- * @returns {string} JSON 格式的连接字符串
- */
- export function encodeChannelConnectionString(key, url) {
- return JSON.stringify({
- _type: CHANNEL_CONN_CLIPBOARD_TYPE,
- key,
- url,
- });
- }
- /**
- * @param {string} text - 剪贴板文本
- * @returns {{ key: string, url: string } | null}
- */
- export function parseChannelConnectionString(text) {
- if (!text || typeof text !== 'string') return null;
- try {
- const parsed = JSON.parse(text.trim());
- if (
- parsed &&
- typeof parsed === 'object' &&
- parsed._type === CHANNEL_CONN_CLIPBOARD_TYPE &&
- typeof parsed.key === 'string' &&
- typeof parsed.url === 'string'
- ) {
- return { key: parsed.key, url: parsed.url };
- }
- } catch {
- // not valid JSON
- }
- return null;
- }
|