diff --git a/src/components/userScripts/tus-sign.vue b/src/components/userScripts/tus-sign.vue new file mode 100644 index 00000000..8157440d --- /dev/null +++ b/src/components/userScripts/tus-sign.vue @@ -0,0 +1,404 @@ + + + diff --git a/src/pages/User/Scripts.vue b/src/pages/User/Scripts.vue index 853a2600..8d25717a 100644 --- a/src/pages/User/Scripts.vue +++ b/src/pages/User/Scripts.vue @@ -56,8 +56,8 @@
脚本列表
- - + +
@@ -69,6 +69,7 @@ import showLoading from "@comp/func/loading.js"; import showSnackbar from "@comp/func/snackbar.js"; import TusMission from "@comp/userScripts/tus-mission.vue"; import TusOutput from "@comp/userScripts/tus-output.vue"; +import TusSign from "@comp/userScripts/tus-sign.vue"; import TSUserAccount from "@Sqlite/modules/userAccount.js"; import { storeToRefs } from "pinia"; import { onMounted, ref, shallowRef } from "vue"; diff --git a/src/types/BBS/Sign.d.ts b/src/types/BBS/Sign.d.ts new file mode 100644 index 00000000..a6457666 --- /dev/null +++ b/src/types/BBS/Sign.d.ts @@ -0,0 +1,131 @@ +/** + * @file types/BBS/Sign.d.ts + * @description 米游社游戏签到模块相关类型声明 + * @since Beta v0.7.2 + */ + +declare namespace TGApp.BBS.Sign { + /** + * @description 获取签到奖励信息返回 + * @interface HomeResp + * @since Beta v0.7.2 + * @extends TGApp.BBS.Response.BaseWithData + * @property {HomeRes} data - 返回数据 + * @returns HomeResp + */ + type HomeResp = TGApp.BBS.Response.BaseWithData; + + /** + * @description 获取签到奖励信返回数据 + * @interface HomeRes + * @property {number} month - 月份 + * @property {Array} awards - 签到奖励列表 + * @property {string} biz - 业务标识 + * @property {boolean} resign - 是否补签 + * @property {HomeAwardExtra} short_extra_award - 签到额外奖励 + * @returns HomeRes + */ + type HomeRes = { + month: number; + awards: Array; + biz: string; + resign: boolean; + short_extra_award: HomeAwardExtra; + }; + + /** + * @description 签到奖励 + * @interface HomeAward + * @property {string} icon - 奖励图标 + * @property {string} name - 奖励名称 + * @property {number} cnt - 奖励数量 + * @returns HomeAward + */ + type HomeAward = { icon: string; name: string; cnt: number }; + + /** + * @description 签到额外奖励 + * @interface HomeAwardExtra + * @property {boolean} has_extra_award - 是否有额外奖励 + * @property {string} start_time - 额外奖励开始时间 + * @property {string} end_time - 额外奖励结束时间 + * @property {Array} list - 额外奖励列表 + * @property {string} start_timestamp - 额外奖励开始时间戳 + * @property {string} end_timestamp - 额外奖励结束时间戳 + * @returns HomeAwardExtra + */ + type HomeAwardExtra = { + has_extra_award: boolean; + start_time: string; + end_time: string; + list: Array; + start_timestamp: string; + end_timestamp: string; + }; + + /** + * @description 获取签到信息返回 + * @interface InfoResp + * @since Beta v0.7.2 + * @extends TGApp.BBS.Response.BaseWithData + * @property {InfoRes} data - 返回数据 + * @returns InfoResp + */ + type InfoResp = TGApp.BBS.Response.BaseWithData; + + /** + * @description 获取签到信息返回数据 + * @interface InfoRes + * @since Beta v0.7.2 + * @property {number} total_sign_day - 总签到天数 + * @property {string} today - 今日日期 + * @property {boolean} is_sign - 是否已签到 + * @property {boolean} is_sub - 是否已补签 + * @property {string} region - 服务器 + * @property {number} sign_cnt_missed - 未签到天数 + * @property {number} short_sign_day - 未知属性 + * @property {boolean} send_first - 是否首签 + * @return InfoRes + */ + type InfoRes = { + total_sign_day: number; + today: string; + is_sign: boolean; + is_sub: boolean; + region: string; + sign_cnt_missed: number; + short_sign_day: number; + send_first: boolean; + }; + + /** + * @description 签到返回 + * @interface SignResp + * @since Beta v0.7.2 + * @extends TGApp.BBS.Response.BaseWithData + * @property {SignRes} data - 返回数据 + * @returns SignResp + */ + type SignResp = TGApp.BBS.Response.BaseWithData; + + /** + * @description 签到返回数据 + * @interface SignRes + * @since Beta v0.7.2 + * @property {string} challenge - gt-challenge + * @property {string} code - 签到状态码 + * @property {string} gt - gt + * @property {boolean} is_risk - 是否有风险 + * @property {number} risk_code - 风险码 + * @property {number} success - 是否成功 + * @return SignRes + */ + type SignRes = { + challenge: string; + code: string; + gt: string; + is_risk: boolean; + risk_code: number; + success: number; + }; +} diff --git a/src/web/request/lunaReq.ts b/src/web/request/lunaReq.ts new file mode 100644 index 00000000..7e88ed4d --- /dev/null +++ b/src/web/request/lunaReq.ts @@ -0,0 +1,152 @@ +/** + * @file web/request/lunaReq.ts + * @description 签到模块请求 + * @since Beta v0.7.2 + */ +import TGBbs from "@/utils/TGBbs.js"; +import TGHttp from "@/utils/TGHttp.js"; +import { getRequestHeader } from "@/web/utils/getRequestHeader.js"; + +// takumiEventLunaApiBaseUrl => telaBu +const telaBu: Readonly = "https://api-takumi.mihoyo.com/event/luna/"; + +type ReqParam = { host?: string; actId: string }; + +/** + * @description 根据服务器获取actId跟host + * @since Beta v0.7.2 + * @param {string} region - 服务器 + * @returns {string} actId + */ +function getActConf(region: string): ReqParam | false { + switch (region) { + // 崩坏2 + case "bh2_cn": + return { actId: "e202203291431091" }; + // 崩坏3 + case "bh3_cn": + return { actId: "e202306201626331" }; + // 原神 + case "hk4e_cn": + return { actId: "e202311201442471", host: "hk4e" }; + // 崩坏:星穹铁道 + case "hkrpg_cn": + return { actId: "e202304121516551", host: "hkrpg" }; + // 未定事件簿 + case "nxx_cn": + return { actId: "e202202251749321" }; + // 绝区零 + case "nap_cn": + return { actId: "e202406242138391", host: "zzz" }; + default: + return false; + } +} + +/** + * @description 获取签到奖励列表 + * @since Beta v0.7.2 + * @property {TGApp.Sqlite.Account.Game} account - 账号信息 + * @property {Record} cookie - cookies + * @returns {Promise} + */ +async function getLunaHome( + account: TGApp.Sqlite.Account.Game, + cookie: Record, +): Promise { + const conf = getActConf(account.gameBiz); + if (conf === false) { + return { retcode: 1, message: "未知服务器" }; + } + const url = conf.host ? `${telaBu}${conf.host}/home` : `${telaBu}home`; + const params = { lang: "zh-cn", act_id: conf.actId }; + const header: Record = { + "user-agent": TGBbs.ua, + referer: "https://act.mihoyo.com", + cookie: Object.keys(cookie) + .map((key) => `${key}=${cookie[key]}`) + .join("; "), + }; + if (conf.host) if (conf.host) header["x-rpc-signgame"] = conf.host; + const resp = await TGHttp(url, { + method: "GET", + query: params, + headers: header, + }); + if (resp.retcode !== 0) return resp; + return resp.data; +} + +/** + * @description 获取签到信息 + * @since Beta v0.7.2 + * @property {TGApp.Sqlite.Account.Game} account - 账号信息 + * @property {Record} cookie - cookies + * @returns {Promise} + */ +async function getLunaInfo( + account: TGApp.Sqlite.Account.Game, + cookie: Record, +): Promise { + const conf = getActConf(account.gameBiz); + if (conf === false) { + return { retcode: 1, message: "未知服务器" }; + } + const url = conf.host ? `${telaBu}${conf.host}/info` : `${telaBu}info`; + const params = { + lang: "zh-cn", + act_id: conf.actId, + region: account.region, + uid: account.gameUid, + }; + const header: Record = { + "user-agent": TGBbs.ua, + referer: "https://act.mihoyo.com", + cookie: Object.keys(cookie) + .map((key) => `${key}=${cookie[key]}`) + .join("; "), + }; + if (conf.host) header["x-rpc-signgame"] = conf.host; + const resp = await TGHttp(url, { + method: "GET", + query: params, + headers: header, + }); + if (resp.retcode !== 0) return resp; + return resp.data; +} + +async function lunaSign( + account: TGApp.Sqlite.Account.Game, + cookie: Record, + challenge?: string, +): Promise { + const conf = getActConf(account.gameBiz); + if (conf === false) { + return { retcode: 1, message: "未知服务器" }; + } + const url = conf.host ? `${telaBu}${conf.host}/sign` : `${telaBu}sign`; + const data = { + lang: "zh-cn", + act_id: conf.actId, + region: account.region, + uid: account.gameUid, + }; + const header: Record = { + ...getRequestHeader(cookie, "POST", JSON.stringify(data), "X6"), + "x-rpc-client_type": "2", + }; + if (conf.host) header["x-rpc-signgame"] = conf.host; + if (challenge) header["x-rpc-challenge"] = challenge; + const resp = await TGHttp(url, { + method: "POST", + headers: header, + body: JSON.stringify(data), + }); + if (resp.retcode !== 0) return resp; + return resp.data; +} + +const lunaReq = { home: getLunaHome, info: getLunaInfo, sign: lunaSign }; + +export default lunaReq;