| 110 | try { |
| 111 | const resp = await axios.get(url, { timeout: 8000 }); |
| 112 | const $ = cheerio.load(resp.data); |
| 113 | const og = $('meta[property="og:description"]').attr('content') || ""; |
| 114 | // e.g. "This number: 545807 is a valid BIN number MASTERCARD issued by GAZPROMBANK ... in RUSSIAN FEDERATION" |
| 115 | const m = og.match(/valid BIN number\s+([A-Z ]+)\s+issued by\s+(.+?)\s+in\s+(.+)/i); |
| 116 | if (m) { |
| 117 | const scheme = m[1]?.trim().toLowerCase().replace(/\s+/g, ""); |
| 118 | const bank = m[2]?.trim(); |
| 119 | const country = m[3]?.trim(); |
| 120 | return { scheme, bank, country }; |
| 121 | } |
| 122 | } catch (e) { |
| 123 | // ignore, fallback will be used |
| 124 | } |
| 125 | return {}; |
| 126 | } |
| 127 | |
| 128 | class BinPlugin extends Plugin { |
| 129 | |
| 130 | description: string = `BIN 查询插件\n\n${help_text}`; |
| 131 | cmdHandlers: Record<string, (msg: Api.Message) => Promise<void>> = { |
| 132 | bin: async (msg: Api.Message) => { |
| 133 | const line = msg.text?.trim()?.split(/\r?\n/g)?.[0] || ""; |
| 134 | const args = line.split(/\s+/) || []; |
| 135 | const [, ...rest] = args; |
| 136 | if (rest.length === 0 || /^h(elp)?$/i.test(rest[0])) { |