mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-19 04:29:45 +08:00
♻️ 请求重构
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/index.ts
|
||||
* @description Mys plugin index
|
||||
* @since Beta v0.7.1
|
||||
*/
|
||||
|
||||
import { doCaptchaLogin, getCaptcha } from "./request/doCaptchaLogin.js";
|
||||
import { getGachaData, getPositionData } from "./request/obcReq.js";
|
||||
import { getGachaCard } from "./utils/getGachaCard.js";
|
||||
import getPositionCard from "./utils/getPositionCard.js";
|
||||
|
||||
const Mys = {
|
||||
Gacha: { get: getGachaData, card: getGachaCard },
|
||||
Position: { get: getPositionData, card: getPositionCard },
|
||||
User: { getCaptcha, login: doCaptchaLogin },
|
||||
};
|
||||
|
||||
export default Mys;
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/request/doCaptchaLogin.ts
|
||||
* @description 通过短信验证码登录账号获取 stoken
|
||||
* @since Beta v0.7.1
|
||||
*/
|
||||
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { JSEncrypt } from "jsencrypt";
|
||||
|
||||
import TGBbs from "@/utils/TGBbs.js";
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getDeviceInfo } from "@/utils/toolFunc.js";
|
||||
|
||||
const PUB_KEY_STR: Readonly<string> = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs
|
||||
9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q
|
||||
CgGs52bFoYMtyi+xEQIDAQAB
|
||||
-----END PUBLIC KEY-----`;
|
||||
const encrypt = new JSEncrypt();
|
||||
encrypt.setPublicKey(PUB_KEY_STR);
|
||||
|
||||
/**
|
||||
* @description rsa 加密
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} data - 待加密数据
|
||||
* @returns {string} 加密后数据
|
||||
*/
|
||||
function rsaEncrypt(data: string): string {
|
||||
const res = encrypt.encrypt(data.toString());
|
||||
if (res === false) {
|
||||
showSnackbar.error("RSA 加密失败");
|
||||
return "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取短信验证码
|
||||
* @since Beta v0.7.1
|
||||
* @param {string} phone - 手机号
|
||||
* @param {string} [aigis] - 验证数据
|
||||
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getCaptcha(
|
||||
phone: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.BaseWithData<string>> {
|
||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-verifier/verifier/createLoginCaptcha";
|
||||
const device_fp = getDeviceInfo("device_fp");
|
||||
const device_name = getDeviceInfo("device_name");
|
||||
const device_id = getDeviceInfo("device_id");
|
||||
const device_model = getDeviceInfo("product");
|
||||
const body = { area_code: rsaEncrypt("+86"), mobile: rsaEncrypt(phone) };
|
||||
const header: Record<string, string> = {
|
||||
"x-rpc-aigis": aigis || "",
|
||||
"x-rpc-app_version": TGBbs.version,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": "bll8iq97cem8",
|
||||
"x-rpc-device_fp": device_fp,
|
||||
"x-rpc-device_name": device_name,
|
||||
"x-rpc-device_id": device_id,
|
||||
"x-rpc-device_model": device_model,
|
||||
"user-agent": TGBbs.ua,
|
||||
"content-type": "application/json",
|
||||
referer: "https://user.miyoushe.com/",
|
||||
"x-rpc-game_biz": "hk4e_cn",
|
||||
};
|
||||
const resp = await TGHttp<
|
||||
TGApp.Plugins.Mys.CaptchaLogin.CaptchaResponse | TGApp.BBS.Response.Base
|
||||
>(
|
||||
url,
|
||||
{
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(body),
|
||||
},
|
||||
true,
|
||||
);
|
||||
const data = await resp.data;
|
||||
if (data.retcode !== 0) {
|
||||
return <TGApp.BBS.Response.BaseWithData<string>>{
|
||||
retcode: data.retcode,
|
||||
message: data.message,
|
||||
data: resp.resp.headers.get("x-rpc-aigis"),
|
||||
};
|
||||
}
|
||||
return <TGApp.Plugins.Mys.CaptchaLogin.CaptchaData>data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 通过短信验证码登录
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} phone - 手机号
|
||||
* @param {string} captcha - 验证码
|
||||
* @param {string} action_type - 操作类型
|
||||
* @param {string} [aigis] - 验证数据
|
||||
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function doCaptchaLogin(
|
||||
phone: string,
|
||||
captcha: string,
|
||||
action_type: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base> {
|
||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-passport/app/loginByMobileCaptcha";
|
||||
const device_fp = getDeviceInfo("device_fp");
|
||||
const device_name = getDeviceInfo("device_name");
|
||||
const device_id = getDeviceInfo("device_id");
|
||||
const device_model = getDeviceInfo("product");
|
||||
const body = {
|
||||
area_code: rsaEncrypt("+86"),
|
||||
mobile: rsaEncrypt(phone),
|
||||
action_type,
|
||||
captcha,
|
||||
};
|
||||
const header = {
|
||||
"x-rpc-aigis": aigis || "",
|
||||
"x-rpc-app_version": TGBbs.version,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": "bll8iq97cem8",
|
||||
"x-rpc-device_fp": device_fp,
|
||||
"x-rpc-device_name": device_name,
|
||||
"x-rpc-device_id": device_id,
|
||||
"x-rpc-device_model": device_model,
|
||||
"user-agent": TGBbs.ua,
|
||||
};
|
||||
const resp = await TGHttp<TGApp.Plugins.Mys.CaptchaLogin.LoginResponse | TGApp.BBS.Response.Base>(
|
||||
url,
|
||||
{
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(body),
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/request/getEmojis.ts
|
||||
* @description Mys 表情包请求函数集合
|
||||
* @since Beta v0.5.0
|
||||
*/
|
||||
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
|
||||
/**
|
||||
* @description 获取表情包列表
|
||||
* @since Beta v0.5.0
|
||||
* @return {Promise<Record<string,string>|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getEmojis(): Promise<Record<string, string> | TGApp.BBS.Response.Base> {
|
||||
const url = "https://bbs-api-static.miyoushe.com/misc/api/emoticon_set";
|
||||
const resp = await TGHttp<TGApp.Plugins.Mys.Emoji.Response | TGApp.BBS.Response.Base>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
const emojis: Record<string, string> = {};
|
||||
for (const series of resp.data.list) {
|
||||
for (const emoji of series.list) {
|
||||
emojis[emoji.name] = emoji.icon;
|
||||
}
|
||||
}
|
||||
return emojis;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/request/obcReq.ts
|
||||
* @description 观测枢相关请求
|
||||
* @since Beta v0.6.3
|
||||
*/
|
||||
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
|
||||
const obcApi: Readonly<string> = "https://api-takumi.mihoyo.com/common/blackboard/ys_obc/v1/";
|
||||
|
||||
/**
|
||||
* @description 获取卡池信息
|
||||
* @since Beta v0.6.3
|
||||
* @return {Promise<TGApp.Plugins.Mys.Gacha.Data[]>}
|
||||
*/
|
||||
export async function getGachaData(): Promise<TGApp.Plugins.Mys.Gacha.Data[]> {
|
||||
const resp = await TGHttp<TGApp.Plugins.Mys.Gacha.Response>(`${obcApi}gacha_pool`, {
|
||||
method: "GET",
|
||||
query: { app_sn: "ys_obc" },
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
return resp.data.list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取热点追踪信息
|
||||
* @since Beta v0.6.3
|
||||
* @return {Promise<TGApp.Plugins.Mys.Position.Data[]>}
|
||||
*/
|
||||
export async function getPositionData(): Promise<TGApp.Plugins.Mys.Position.Data[]> {
|
||||
const resp = await TGHttp<TGApp.Plugins.Mys.Position.Response>(`${obcApi}home/position`, {
|
||||
method: "GET",
|
||||
query: { app_sn: "ys_obc" },
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
const data = resp.data.list;
|
||||
return DfsObc(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 深度优先遍历
|
||||
* @since Alpha v0.2.1
|
||||
* @param {TGApp.Plugins.Mys.Position.ObcItem[]} list 列表
|
||||
* @returns {TGApp.Plugins.Mys.Position.Data[]} 返回列表
|
||||
*/
|
||||
function DfsObc(list: TGApp.Plugins.Mys.Position.ObcItem[]): TGApp.Plugins.Mys.Position.Data[] {
|
||||
const res: TGApp.Plugins.Mys.Position.Data[] = [];
|
||||
for (const item of list) {
|
||||
if (item.name === "近期活动") {
|
||||
res.push(...item.list);
|
||||
}
|
||||
if (item.children) {
|
||||
res.push(...DfsObc(<TGApp.Plugins.Mys.Position.ObcItem[]>item.children));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
179
src/plugins/Mys/types/CaptchaLogin.d.ts
vendored
179
src/plugins/Mys/types/CaptchaLogin.d.ts
vendored
@@ -1,179 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/CaptchaLogin.d.ts
|
||||
* @description Mys 插件 Captcha 登录类型定义文件
|
||||
* @since Beta v0.5.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description Mys 插件 Captcha 登录类型
|
||||
* @since Beta v0.5.1
|
||||
* @namespace TGApp.Plugins.Mys.CaptchaLogin
|
||||
* @memberof TGApp.Plugins.Mys
|
||||
*/
|
||||
declare namespace TGApp.Plugins.Mys.CaptchaLogin {
|
||||
/**
|
||||
* @description 获取短信验证码返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface CaptchaResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {CaptchaData} data 数据
|
||||
* @return GetCaptchaResponse
|
||||
*/
|
||||
interface CaptchaResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: CaptchaData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取短信验证码返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface CaptchaData
|
||||
* @property {string} sent_new 是否发送新验证码
|
||||
* @property {string} countdown 倒计时
|
||||
* @property {string} action_type 操作类型
|
||||
* @return CaptchaData
|
||||
*/
|
||||
interface CaptchaData {
|
||||
sent_new: string;
|
||||
countdown: string;
|
||||
action_type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 触发验证的序列化数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface CaptchaAigis
|
||||
* @property {string} session_id 会话 id
|
||||
* @property {number} mmt_type mmt 类型
|
||||
* @see TGApp.BBS.Geetest.GeetestVerifyRes
|
||||
* @property {string} data 数据,为上面的序列化数据
|
||||
* @return CaptchaBody
|
||||
*/
|
||||
interface CaptchaAigis {
|
||||
session_id: string;
|
||||
mmt_type: number;
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 短信验证码登录返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface LoginResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {LoginData} data 数据
|
||||
* @return LoginResponse
|
||||
*/
|
||||
interface LoginResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: LoginData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 短信验证码登录返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface LoginData
|
||||
* @property {Token} token token数据
|
||||
* @property {UserInfo} user_info 用户信息
|
||||
* @property {ReactivateInfo} reactivate_info 重新激活信息
|
||||
* @property {string} login_ticket 登录 ticket
|
||||
* @property {boolean} new_user 是否新用户
|
||||
* @property {RealnameInfo} realname_info 实名信息
|
||||
* @property {boolean} need_realperson 是否需要实名认证
|
||||
* @property {string} oauth_hw_open_id 华为 open id
|
||||
* @return LoginData
|
||||
*/
|
||||
interface LoginData {
|
||||
token: Token;
|
||||
user_info: UserInfo;
|
||||
reactivate_info: ReactivateInfo;
|
||||
login_ticket: string;
|
||||
new_user: boolean;
|
||||
realname_info: RealnameInfo;
|
||||
need_realperson: boolean;
|
||||
oauth_hw_open_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description token 数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface Token
|
||||
* @property {number} token_type token 类型
|
||||
* @property {string} token token
|
||||
* @return Token
|
||||
*/
|
||||
interface Token {
|
||||
token_type: number;
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用户信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface UserInfo
|
||||
* @property {string} aid 账号 id
|
||||
* @property {string} mid mid
|
||||
* @property {string} account_name 账号名称
|
||||
* @property {string} email 邮箱
|
||||
* @property {number} is_email_verify 是否验证邮箱
|
||||
* @property {string} area_code 手机区号
|
||||
* @property {string} mobile 手机号
|
||||
* @property {string} safe_area_code 安全手机区号
|
||||
* @property {string} safe_mobile 安全手机号
|
||||
* @property {string} realname 真实姓名
|
||||
* @property {string} identity_code 身份证号
|
||||
* @property {string} rebind_area_code 重新绑定手机区号
|
||||
* @property {string} rebind_mobile 重新绑定手机号
|
||||
* @property {string} rebind_mobile_time 重新绑定手机时间
|
||||
* @property {string[]} links 账号绑定信息
|
||||
* @property {string} country 国家
|
||||
* @property {string} unmasked_email 邮箱
|
||||
* @property {number} unmasked_email_type 邮箱类型
|
||||
* @return UserInfo
|
||||
*/
|
||||
interface UserInfo {
|
||||
aid: string;
|
||||
mid: string;
|
||||
account_name: string;
|
||||
email: string;
|
||||
is_email_verify: number;
|
||||
area_code: string;
|
||||
mobile: string;
|
||||
safe_area_code: string;
|
||||
safe_mobile: string;
|
||||
realname: string;
|
||||
identity_code: string;
|
||||
rebind_area_code: string;
|
||||
rebind_mobile: string;
|
||||
rebind_mobile_time: string;
|
||||
links: string[];
|
||||
country: string;
|
||||
unmasked_email: string;
|
||||
unmasked_email_type: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 重新激活信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface ReactivateInfo
|
||||
* @property {boolean} required 是否需要重新激活
|
||||
* @property {string} ticket 重新激活 ticket
|
||||
* @return ReactivateInfo
|
||||
*/
|
||||
interface ReactivateInfo {
|
||||
required: boolean;
|
||||
ticket: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 实名信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface RealnameInfo
|
||||
* @property {boolean} required 是否需要实名认证
|
||||
* @property {string} action_type 操作类型
|
||||
* @property {string} action_ticket 操作 ticket
|
||||
* @return RealnameInfo
|
||||
*/
|
||||
interface RealnameInfo {
|
||||
required: boolean;
|
||||
action_type: string;
|
||||
action_ticket: string;
|
||||
}
|
||||
}
|
||||
83
src/plugins/Mys/types/Emoji.d.ts
vendored
83
src/plugins/Mys/types/Emoji.d.ts
vendored
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/Emoji.d.ts
|
||||
* @description Mys 表情包类型声明文件
|
||||
* @since Beta v0.3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description Mys 表情包类型
|
||||
* @since Beta v0.3.0
|
||||
* @namespace TGApp.Plugins.Mys.Emoji
|
||||
* @memberof TGApp.Plugins.Mys
|
||||
*/
|
||||
declare namespace TGApp.Plugins.Mys.Emoji {
|
||||
/**
|
||||
* @description 获取表情包列表返回
|
||||
* @since Beta v0.3.0
|
||||
* @interface Response
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {Series[]} data.list 表情包列表
|
||||
* @property {unknown} data.recently_emoticon 最近使用的表情包
|
||||
* @return Response
|
||||
*/
|
||||
interface Response extends TGApp.BBS.Response.BaseWithData {
|
||||
data: {
|
||||
list: Series[];
|
||||
recently_emoticon: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 表情包系列
|
||||
* @since Beta v0.3.0
|
||||
* @interface Series
|
||||
* @property {number} id 表情包系列 ID
|
||||
* @property {string} name 表情包系列名称
|
||||
* @property {string} icon 表情包系列图标
|
||||
* @property {number} sort_order 表情包系列排序
|
||||
* @property {number} num 表情包系列数量
|
||||
* @property {string} status 表情包系列状态
|
||||
* @property {EmojiItem[]} list 表情包系列列表
|
||||
* @property {number} updated_at 表情包系列更新时间
|
||||
* @property {boolean} is_available 表情包系列是否可用
|
||||
* @return Series
|
||||
*/
|
||||
interface Series {
|
||||
id: number;
|
||||
name: string;
|
||||
icon: string;
|
||||
sort_order: number;
|
||||
num: number;
|
||||
status: string;
|
||||
list: EmojiItem[];
|
||||
updated_at: number;
|
||||
is_available: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 表情包
|
||||
* @since Beta v0.3.0
|
||||
* @interface EmojiItem
|
||||
* @property {number} id 表情包 ID
|
||||
* @property {string} name 表情包名称
|
||||
* @property {string} icon 表情包图标
|
||||
* @property {number} sort_order 表情包排序
|
||||
* @property {string} static_icon 表情包静态图标
|
||||
* @property {number} updated_at 表情包更新时间
|
||||
* @property {boolean} is_available 表情包是否可用
|
||||
* @property {string} status 表情包状态
|
||||
* @property {unknown[]} keywords 表情包关键词
|
||||
* @return EmojiItem
|
||||
*/
|
||||
interface EmojiItem {
|
||||
id: number;
|
||||
name: string;
|
||||
icon: string;
|
||||
sort_order: number;
|
||||
static_icon: string;
|
||||
updated_at: number;
|
||||
is_available: boolean;
|
||||
status: string;
|
||||
keywords: unknown[];
|
||||
}
|
||||
}
|
||||
100
src/plugins/Mys/types/Gacha.d.ts
vendored
100
src/plugins/Mys/types/Gacha.d.ts
vendored
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/Gacha.d.ts
|
||||
* @description Mys 插件卡池类型定义文件
|
||||
* @since Beta v0.6.6
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Plugins.Mys.Gacha {
|
||||
/**
|
||||
* @description 获取卡池信息返回
|
||||
* @since Alpha v0.2.1
|
||||
* @interface Response
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {Data[]} data.list 卡池数据
|
||||
* @return Response
|
||||
*/
|
||||
interface Response extends TGApp.BBS.Response.BaseWithData {
|
||||
data: {
|
||||
list: Data[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 卡池信息
|
||||
* @since Beta v0.4.4
|
||||
* @interface Data
|
||||
* @property {string} id 卡池ID
|
||||
* @property {string} title 卡池标题
|
||||
* @property {string} activity_url 卡池对应帖子
|
||||
* @property {string} content_before_act 卡池内容
|
||||
* @property {Array<{icon: string; url: string}>} pool 卡池角色头像
|
||||
* @property {string} voice_icon 卡池角色语音头像
|
||||
* @property {string} voice_url 卡池角色语音URL
|
||||
* @property {string} voice_status 卡池角色语音状态
|
||||
* @description 如下时间示例:2023-03-21 17:59:59
|
||||
* @property {string} start_time 卡池开始时间
|
||||
* @property {string} end_time 卡池结束时间
|
||||
* @return Data
|
||||
*/
|
||||
interface Data {
|
||||
id: number;
|
||||
title: string;
|
||||
activity_url: string;
|
||||
content_before_act: string;
|
||||
pool: Array<{
|
||||
icon: string;
|
||||
url: string;
|
||||
}>;
|
||||
voice_icon: string;
|
||||
voice_url: string;
|
||||
voice_status: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用于渲染的卡池数据
|
||||
* @since Beta v0.6.6
|
||||
* @interface RenderCard
|
||||
* @property {string} id 卡池ID
|
||||
* @property {string} title 卡池标题
|
||||
* @property {string} subtitle 卡池副标题
|
||||
* @property {string} cover 卡池封面
|
||||
* @property {number} postId 卡池对应帖子ID
|
||||
* @property {Array<RenderItem>} characters 卡池角色头像
|
||||
* @property {string} time.str 卡池时间字符串
|
||||
* @property {string} time.startStamp 卡池开始时间戳
|
||||
* @property {string} time.endStamp 卡池结束时间戳
|
||||
* @property {string} time.totalStamp 卡池持续时间戳
|
||||
* @return RenderCard
|
||||
*/
|
||||
interface RenderCard {
|
||||
id: number;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
cover: string;
|
||||
postId: number;
|
||||
characters: RenderItem[];
|
||||
time: {
|
||||
str: string;
|
||||
startStamp: number;
|
||||
endStamp: number;
|
||||
totalStamp: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用于渲染的卡池角色头像
|
||||
* @since Beta v0.4.4
|
||||
* @interface RenderItem
|
||||
* @property {string} icon 角色头像
|
||||
* @property {string} url 角色详情页URL
|
||||
* @property {TGApp.App.Character.WikiBriefInfo} info 角色简略信息
|
||||
* @return RenderItem
|
||||
*/
|
||||
interface RenderItem {
|
||||
icon: string;
|
||||
url: string;
|
||||
info?: TGApp.App.Character.WikiBriefInfo;
|
||||
}
|
||||
}
|
||||
50
src/plugins/Mys/types/Obc.d.ts
vendored
50
src/plugins/Mys/types/Obc.d.ts
vendored
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/Obc.d.ts
|
||||
* @description Mys obc 类型定义文件
|
||||
* @since Alpha v0.2.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description Mys obc 类型
|
||||
* @since Alpha v0.2.1
|
||||
* @namespace TGApp.Plugins.Mys.Obc
|
||||
* @memberof TGApp.Plugins.Mys
|
||||
*/
|
||||
declare namespace TGApp.Plugins.Mys.Obc {
|
||||
/**
|
||||
* @description Mys obc 返回数据
|
||||
* @since Beta v0.3.6
|
||||
* @interface Response
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {Data[]} data.list obc 列表
|
||||
* @return Response
|
||||
*/
|
||||
interface Response extends TGApp.BBS.Response.BaseWithData {
|
||||
data: {
|
||||
list: Data[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Mys obc 层级结构
|
||||
* @since Alpha v0.2.1
|
||||
* @interface Data
|
||||
* @property {number} id ID
|
||||
* @property {string} name 名称
|
||||
* @property {number} parent_id 父ID
|
||||
* @property {number} depth 深度
|
||||
* @property {string} ch_ext 结构化扩展信息
|
||||
* @property {Obc[]} children 子节点,可以递归
|
||||
* @property {unknown[]} list 列表
|
||||
* @return Data
|
||||
*/
|
||||
interface Data {
|
||||
id: number;
|
||||
name: string;
|
||||
parent_id: number;
|
||||
depth: number;
|
||||
ch_ext: string;
|
||||
children: Data[];
|
||||
list: unknown[];
|
||||
}
|
||||
}
|
||||
96
src/plugins/Mys/types/Position.d.ts
vendored
96
src/plugins/Mys/types/Position.d.ts
vendored
@@ -1,96 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/Position.d.ts
|
||||
* @description Mys 插件热点追踪接口
|
||||
* @since Beta v0.6.6
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Plugins.Mys.Position {
|
||||
/**
|
||||
* @description 热点追踪信息的返回类型
|
||||
* @since Alpha v0.2.1
|
||||
* @interface Response
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {ObcItem[]} data.list obc 列表
|
||||
* @return Response
|
||||
*/
|
||||
interface Response extends TGApp.BBS.Response.BaseWithData {
|
||||
data: {
|
||||
list: ObcItem[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 热点追踪层级结构
|
||||
* @since Alpha v0.2.1
|
||||
* @interface ObcItem
|
||||
* @extends TGApp.Plugins.Mys.Obc.Data
|
||||
* @property {Data[]} list 列表
|
||||
* @return ObcItem
|
||||
*/
|
||||
interface ObcItem extends TGApp.Plugins.Mys.Obc.Data {
|
||||
list: Data[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 热点追踪信息
|
||||
* @since Alpha v0.2.1
|
||||
* @interface Data
|
||||
* @property {number} recommend_id 推荐ID
|
||||
* @property {number} content_id 内容ID
|
||||
* @property {string} title 标题
|
||||
* @property {string} ext 扩展信息
|
||||
* @property {number} type 类型
|
||||
* @property {string} url 链接
|
||||
* @property {string} icon 图标
|
||||
* @property {string} abstract 摘要
|
||||
* @property {string} article_user_name 作者
|
||||
* @property {string} avatar_url 头像
|
||||
* @property {string} article_time 时间
|
||||
* @property {string} create_time 创建时间 // 2023-03-31 11:16:57
|
||||
* @property {string} end_time 结束时间 // 1680465599000
|
||||
* @return Data
|
||||
*/
|
||||
interface Data {
|
||||
recommend_id: number;
|
||||
content_id: number;
|
||||
title: string;
|
||||
ext: string;
|
||||
type: number;
|
||||
url: string;
|
||||
icon: string;
|
||||
abstract: string;
|
||||
article_user_name: string;
|
||||
avatar_url: string;
|
||||
article_time: string;
|
||||
create_time: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 渲染用的热点追踪信息
|
||||
* @since Beta v0.6.6
|
||||
* @interface RenderCard
|
||||
* @property {string} title 标题
|
||||
* @property {number} postId 帖子ID
|
||||
* @property {string} link 链接
|
||||
* @property {string} icon 图标
|
||||
* @property {string} abstract 摘要
|
||||
* @property time 时间
|
||||
* @property {number} time.startStamp 开始时间戳
|
||||
* @property {number} time.endStamp 结束时间戳
|
||||
* @property {number} time.totalStamp 总时间戳
|
||||
* @return RenderCard
|
||||
*/
|
||||
interface RenderCard {
|
||||
title: string;
|
||||
postId: number;
|
||||
link: string;
|
||||
icon: string;
|
||||
abstract: string;
|
||||
time: {
|
||||
startStamp: number;
|
||||
endStamp: number;
|
||||
totalStamp: number;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/utils/getGachaCard.ts
|
||||
* @description Mys 插件抽卡工具
|
||||
* @since Beta v0.6.3
|
||||
*/
|
||||
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
|
||||
import { AppCharacterData } from "@/data/index.js";
|
||||
import postReq from "@/web/request/postReq.js";
|
||||
|
||||
/**
|
||||
* @description 根据单个卡池信息转为渲染用的卡池信息
|
||||
* @since Beta v0.6.6
|
||||
* @param {TGApp.Plugins.Mys.Gacha.Data} data 卡池信息
|
||||
* @param {string} poolCover 卡池封面
|
||||
* @returns {Promise<TGApp.Plugins.Mys.Gacha.RenderCard>}
|
||||
*/
|
||||
async function getGachaItemCard(
|
||||
data: TGApp.Plugins.Mys.Gacha.Data,
|
||||
poolCover?: string,
|
||||
): Promise<TGApp.Plugins.Mys.Gacha.RenderCard | null> {
|
||||
let cover = "/source/UI/empty.webp";
|
||||
const postId: number | undefined = Number(data.activity_url.split("/").pop()) || undefined;
|
||||
if (postId === undefined || isNaN(postId)) return null;
|
||||
if (poolCover !== undefined) {
|
||||
cover = poolCover;
|
||||
} else {
|
||||
const postResp = await postReq.post(postId);
|
||||
if ("retcode" in postResp) {
|
||||
showSnackbar.error(`[${postResp.retcode}] ${postResp.message}`);
|
||||
return null;
|
||||
}
|
||||
cover = postResp.cover?.url ?? postResp.post.images[0];
|
||||
}
|
||||
const timeStr = `${data.start_time} ~ ${data.end_time}`;
|
||||
const characters: TGApp.Plugins.Mys.Gacha.RenderItem[] = [];
|
||||
for (const character of data.pool) {
|
||||
const item: TGApp.Plugins.Mys.Gacha.RenderItem = { icon: character.icon, url: character.url };
|
||||
const contentId = character.url.match(/(?<=content\/)\d+/)?.[0];
|
||||
if (contentId) {
|
||||
const itemF = AppCharacterData.find((item) => item.contentId.toString() === contentId);
|
||||
if (itemF) item.info = itemF;
|
||||
}
|
||||
characters.push(item);
|
||||
}
|
||||
return {
|
||||
id: data.id,
|
||||
title: data.title,
|
||||
subtitle: data.content_before_act,
|
||||
cover,
|
||||
postId,
|
||||
characters,
|
||||
time: {
|
||||
str: timeStr,
|
||||
startStamp: new Date(data.start_time).getTime(),
|
||||
endStamp: new Date(data.end_time).getTime(),
|
||||
totalStamp: new Date(data.end_time).getTime() - new Date(data.start_time).getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据卡池信息转为渲染用的卡池信息
|
||||
* @since Beta v0.6.3
|
||||
* @param {TGApp.Plugins.Mys.Gacha.Data[]} gachaData 卡池信息
|
||||
* @param {Record<number, string>} poolCover 卡池封面
|
||||
* @returns {Promise<TGApp.Plugins.Mys.Gacha.RenderCard[]>}
|
||||
*/
|
||||
export async function getGachaCard(
|
||||
gachaData: TGApp.Plugins.Mys.Gacha.Data[],
|
||||
poolCover?: Record<number, string>,
|
||||
): Promise<TGApp.Plugins.Mys.Gacha.RenderCard[]> {
|
||||
const gachaCard: TGApp.Plugins.Mys.Gacha.RenderCard[] = [];
|
||||
for (const data of gachaData) {
|
||||
const item = await getGachaItemCard(data, poolCover?.[Number(data.id)]);
|
||||
if (item !== null) gachaCard.push(item);
|
||||
}
|
||||
return gachaCard;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/utils/getPositionCard.ts
|
||||
* @description Mys 插件热点追踪工具
|
||||
* @since Beta v0.6.6
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description 根据热点追踪信息转为渲染用的数据
|
||||
* @since Beta v0.6.6
|
||||
* @param {TGApp.Plugins.Mys.Position.Data[]} positionData 列表
|
||||
* @returns {TGApp.Plugins.Mys.Position.RenderCard[]} 返回列表
|
||||
*/
|
||||
function getPositionCard(
|
||||
positionData: TGApp.Plugins.Mys.Position.Data[],
|
||||
): TGApp.Plugins.Mys.Position.RenderCard[] {
|
||||
const res: TGApp.Plugins.Mys.Position.RenderCard[] = [];
|
||||
for (const position of positionData) {
|
||||
let link = position.url;
|
||||
if (position.url === "" && position.content_id !== 0) {
|
||||
link = `https://bbs.mihoyo.com/ys/obc/content/${position.content_id}/detail?bbs_presentation_style=no_header`;
|
||||
}
|
||||
const startTs = new Date(position.create_time).getTime();
|
||||
const endTs = Number(position.end_time);
|
||||
const card: TGApp.Plugins.Mys.Position.RenderCard = {
|
||||
title: position.title,
|
||||
postId: position.url !== "" ? Number(position.url.split("/").pop()) : position.content_id,
|
||||
link: link,
|
||||
icon: position.icon,
|
||||
abstract: position.abstract,
|
||||
time: { startStamp: startTs, endStamp: endTs, totalStamp: endTs - startTs },
|
||||
};
|
||||
res.push(card);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export default getPositionCard;
|
||||
Reference in New Issue
Block a user