()
| 4 | |
| 5 | class ServiceQQ { |
| 6 | handle(): RouterMiddleware<'/qq/profile'> { |
| 7 | return async (ctx) => { |
| 8 | const qq = await Common.getParam('qq', ctx.request) |
| 9 | const size = +((await Common.getParam('size', ctx.request)) || 0) |
| 10 | |
| 11 | if (!qq) { |
| 12 | return Common.requireArguments('qq', ctx.response) |
| 13 | } |
| 14 | |
| 15 | if (!/^\d{5,11}$/.test(qq)) { |
| 16 | ctx.response.status = 400 |
| 17 | ctx.response.body = Common.buildJson(null, 400, '无效的 QQ 号码') |
| 18 | return |
| 19 | } |
| 20 | |
| 21 | const validSizes = [0, 40, 100, 160, 640] |
| 22 | |
| 23 | if (!validSizes.includes(size)) { |
| 24 | ctx.response.status = 400 |
| 25 | ctx.response.body = Common.buildJson(null, 400, `无效的 size 参数。必须是以下之一: ${validSizes.join(', ')}`) |
| 26 | return |
| 27 | } |
| 28 | |
| 29 | const data = await this.#fetch(qq, size) |
| 30 | |
| 31 | switch (ctx.state.encoding) { |
| 32 | case 'text': |
| 33 | ctx.response.body = data.nickname |
| 34 | break |
| 35 | |
| 36 | case 'markdown': |
| 37 | ctx.response.body = `# 👤 QQ 用户信息\n\n\n\n**昵称**: ${data.nickname}\n\n**QQ 号**: ${data.qq}\n\n**头像尺寸**: ${data.avatar_size}px` |
| 38 | break |
| 39 | |
| 40 | case 'image': |
| 41 | ctx.response.redirect(data.avatar_url) |
| 42 | break |
| 43 | |
| 44 | case 'json': |
| 45 | default: |
| 46 | ctx.response.body = Common.buildJson(data) |
| 47 | break |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | async #fetch(qq: string, size: number): Promise<QQUserInfo> { |
| 53 | const options = { headers: { 'User-Agent': Common.chromeUA } } |
no test coverage detected