File size: 6,765 Bytes
af5a34b
 
 
 
 
 
481eba0
 
 
 
 
 
 
 
 
 
 
 
 
 
0800168
 
481eba0
0800168
af5a34b
 
 
 
 
 
481eba0
af5a34b
 
 
 
 
 
 
 
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
481eba0
af5a34b
 
 
 
 
02fc7f7
af5a34b
481eba0
 
 
 
af5a34b
 
 
 
481eba0
 
af5a34b
481eba0
af5a34b
 
 
 
481eba0
 
af5a34b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481eba0
af5a34b
481eba0
af5a34b
 
 
 
481eba0
af5a34b
 
 
 
 
 
 
 
0800168
af5a34b
 
0800168
af5a34b
 
0800168
af5a34b
 
 
 
 
 
 
 
 
0800168
af5a34b
 
0800168
 
af5a34b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481eba0
af5a34b
481eba0
 
 
af5a34b
481eba0
af5a34b
481eba0
 
 
af5a34b
 
 
 
 
 
0800168
af5a34b
 
481eba0
 
 
af5a34b
 
 
 
 
 
 
 
0800168
af5a34b
 
 
 
 
 
481eba0
af5a34b
 
481eba0
 
 
af5a34b
 
 
481eba0
af5a34b
 
 
 
02fc7f7
 
 
 
 
af5a34b
481eba0
af5a34b
0800168
 
 
 
 
 
 
af5a34b
0800168
 
 
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/**
 * plugin的runtime,可通过e.runtime访问
 *
 * 提供一些常用的运行时变量、方法及model获取
 * 降低对目录结构的依赖
 */
import lodash from "lodash"
import fs from "node:fs/promises"
import common from "../common/common.js"
import cfg from "../config/config.js"
import puppeteer from "../puppeteer/puppeteer.js"
import Handler from "./handler.js"

let gsCfg, MysApi, MysInfo, NoteUser, MysUser, Version
try {
  gsCfg = (await import("../../plugins/genshin/model/gsCfg.js")).default
  MysApi = (await import("../../plugins/genshin/model/mys/mysApi.js")).default
  MysInfo = (await import("../../plugins/genshin/model/mys/mysInfo.js")).default
  NoteUser = (await import("../../plugins/genshin/model/mys/NoteUser.js")).default
  MysUser = (await import("../../plugins/genshin/model/mys/MysUser.js")).default
} catch {}
try {
  Version = (await import("#miao")).Version
} catch {}

/**
 * 常用的处理方法
 */

export default class Runtime {
  constructor(e) {
    this.e = e
    this._mysInfo = {}

    this.handler = {
      has: Handler.has,
      call: Handler.call,
      callAll: Handler.callAll
    }
  }

  get uid() {
    return this.user?.uid
  }

  get hasCk() {
    return this.user?.hasCk
  }

  get user() {
    return this.e.user
  }

  get cfg() {
    return cfg
  }

  get gsCfg() {
    return gsCfg
  }

  get common() {
    return common
  }

  get puppeteer() {
    return puppeteer
  }

  get MysInfo() {
    return MysInfo
  }

  get NoteUser() {
    return NoteUser
  }

  get MysUser() {
    return MysUser
  }

  async initUser() {
    let e = this.e
    let user = await NoteUser.create(e)
    if (user) {
      e.user = new Proxy(user, {
        get (self, key, receiver) {
          let game = e.game
          let fnMap = {
            uid: "getUid",
            uidList: "getUidList",
            mysUser: "getMysUser",
            ckUidList: "getCkUidList"
          }
          if (fnMap[key]) {
            return self[fnMap[key]](game)
          }
          if (key === "uidData") {
            return self.getUidData("", game)
          }
          if (["getUid", "getUidList", "getMysUser", "getCkUidList", "getUidMapList", "getGameDs"].includes(key)) {
            return (_game, arg2) => {
              return self[key](_game || game, arg2)
            }
          }
          if (["getUidData", "hasUid", "addRegUid", "delRegUid", "setMainUid"].includes(key)) {
            return (uid, _game = "") => {
              return self[key](uid, _game || game)
            }
          }
          return self[key]
        }
      })
    }
  }

  /**
   * 获取MysInfo实例
   *
   * @param targetType all: 所有用户均可, cookie:查询用户必须具备Cookie
   * @returns {Promise<boolean|MysInfo>}
   */
  async getMysInfo(targetType = "all") {
    if (!this._mysInfo[targetType]) {
      this._mysInfo[targetType] = await MysInfo.init(this.e, targetType === "cookie" ? "detail" : "roleIndex")
    }
    return this._mysInfo[targetType]
  }

  async getUid() {
    return await MysInfo.getUid(this.e)
  }

  /**
   * 获取MysApi实例
   *
   * @param targetType all: 所有用户均可, cookie:查询用户必须具备Cookie
   * @param option MysApi option
   * @param isSr 是否为星穹铁道
   * @returns {Promise<boolean|MysApi>}
   */
  async getMysApi(targetType = "all", option = {}, isSr = false) {
    let mys = await this.getMysInfo(targetType)
    if (mys.uid && mys?.ckInfo?.ck) {
      return new MysApi(mys.uid, mys.ckInfo.ck, option, isSr)
    }
    return false
  }

  /**
   * 生成MysApi实例
   * @param uid
   * @param ck
   * @param option
   * @param isSr 是否为星穹铁道
   * @returns {Promise<MysApi>}
   */
  async createMysApi(uid, ck, option, isSr = false) {
    return new MysApi(uid, ck, option, isSr)
  }

  /**
   *
   * @param plugin plugin key
   * @param path html文件路径,相对于plugin resources目录
   * @param data 渲染数据
   * @param cfg 渲染配置
   * @param cfg.retType 返回值类型
   * * default/空:自动发送图片,返回true
   * * msgId:自动发送图片,返回msg id
   * * base64: 不自动发送图像,返回图像base64数据
   * @param cfg.beforeRender({data}) 可改写渲染的data数据
   * @returns {Promise<boolean>}
   */
  async render(plugin, path, data = {}, cfg = {}) {
    // 处理传入的path
    path = path.replace(/.html$/, "")
    let paths = lodash.filter(path.split("/"), (p) => !!p)
    path = paths.join("/")
    // 创建目录
    await Bot.mkdir(`temp/html/${plugin}/${path}`)
    // 自动计算pluResPath
    let pluResPath = `../../../${lodash.repeat("../", paths.length)}plugins/${plugin}/resources/`
    let miaoResPath = `../../../${lodash.repeat("../", paths.length)}plugins/miao-plugin/resources/`
    const layoutPath = process.cwd() + "/plugins/miao-plugin/resources/common/layout/"
    // 渲染data
    data = {
      sys: {
        scale: 1
      },
      /** miao 相关参数 **/
      copyright: `Created By TRSS-Yunzai<span class="version">${Version?.yunzai}</span> `,
      _res_path: pluResPath,
      _miao_path: miaoResPath,
      _tpl_path: process.cwd() + "/plugins/miao-plugin/resources/common/tpl/",
      defaultLayout: layoutPath + "default.html",
      elemLayout: layoutPath + "elem.html",

      ...data,

      /** 默认参数 **/
      _plugin: plugin,
      _htmlPath: path,
      pluResPath,
      tplFile: `./plugins/${plugin}/resources/${path}.html`,
      saveId: data.saveId || data.save_id || paths[paths.length - 1]
    }
    // 处理beforeRender
    if (cfg.beforeRender) {
      data = cfg.beforeRender({ data }) || data
    }
    // 保存模板数据
    if (process.argv.includes("dev")) {
      // debug下保存当前页面的渲染数据,方便模板编写与调试
      // 由于只用于调试,开发者只关注自己当时开发的文件即可,暂不考虑app及plugin的命名冲突
      let saveDir = await Bot.mkdir(`temp/ViewData/${plugin}`)
      let file = `${saveDir}/${data._htmlPath.split("/").join("_")}.json`
      await fs.writeFile(file, JSON.stringify(data))
    }
    // 截图
    let base64 = await puppeteer.screenshot(`${plugin}/${path}`, data)
    if (cfg.retType === "base64") {
      return base64
    }
    let ret = true
    if (base64) {
      if (cfg.recallMsg) {
        ret = await this.e.reply(base64, false, {})
      } else {
        ret = await this.e.reply(base64)
      }
    }
    return cfg.retType === "msgId" ? ret : true
  }

  static async init(e) {
    await MysInfo.initCache()
    e.runtime = new Runtime(e)
    await e.runtime.initUser()
    return e.runtime
  }
}

if (!MysInfo || !NoteUser)
  Runtime.init = async e => e.runtime = new Runtime(e)