diff --git a/bun.lockb b/bun.lockb index 81df2bd..44b1963 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..bea1efe --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[install.scopes] +"@jsr" = "https://npm.jsr.io" diff --git a/src/module/KAS.ts b/src/module/KAS.ts index 0acc88d..b422e74 100644 --- a/src/module/KAS.ts +++ b/src/module/KAS.ts @@ -1,3 +1,6 @@ +//@ts-ignore +import { createTripByKey } from "./trip"; + function formatUnixTime(unixTime: number): string { // UNIXタイムをミリ秒に変換 const date = new Date(unixTime * 1000); @@ -71,8 +74,8 @@ async function NES(input: string, mail: string): Promise<{ name: string, mail: s const convertedInput = input.replace(/[◆★\n]/g, function (m) { return map[m]; }); let trip = ''; if (length > 0) { - // trip = `◆`+await convertTrip(match, length, true); - trip = `◆` + `現在一時的にトリップは使用できません` + trip = `◆`+await createTripByKey(match[1]); + // trip = `◆` + `現在一時的にトリップは使用できません` } return { "name": `${convertedInput.replace(/#.*/, '')}${trip}`, "mail": mail } } \ No newline at end of file diff --git a/src/module/trip.ts b/src/module/trip.ts new file mode 100644 index 0000000..b846b06 --- /dev/null +++ b/src/module/trip.ts @@ -0,0 +1,53 @@ +import * as IconvCP932 from "iconv-cp932"; + +import { create10DigitsTrip, create12DigitsTrip, createRawKeyTrip } from './trip/index' + +type Options = Partial<{ + hideWhitespace: boolean +}> + +const rawKeyPettern = /^#[0-9A-Fa-f]{16}[.\/0-9A-Za-z]{0,2}$/ + +const maskSpecialSymbols = (text: string) => text.replace(/★/g, '☆').replace(/◆/g, '◇') + +export const createTripByKey = (key: string) => { +// const encodedKeyString = convert(key, { from: 'UNICODE', to: 'SJIS', fallback: 'html-entity' }) + const encodedKeyString = IconvCP932.encode(key).toString() + + // 10 桁トリップ + if (encodedKeyString.length < 12) return create10DigitsTrip(key) + + // 生キートリップ + if (encodedKeyString.startsWith('#') || encodedKeyString.startsWith('$')) { + // 拡張用のため ??? を返す + if (!rawKeyPettern.test(encodedKeyString)) return '???' + + return createRawKeyTrip(key) + } + + // 12 桁トリップ + return create12DigitsTrip(key) +} + +export const createTripByText = (text: string, options?: Options) => { + const indexOfSharp = (() => { + const indexOfHalfWidthSharp = text.indexOf('#') + const indexOfFullWidthSharp = text.indexOf('#') + + if (indexOfHalfWidthSharp >= 0) return indexOfHalfWidthSharp + if (indexOfFullWidthSharp >= 0) return indexOfFullWidthSharp + + return -1 + })() + + if (indexOfSharp < 0) return maskSpecialSymbols(text) + + const name = text.substr(0, indexOfSharp) + const key = text.substr(indexOfSharp + 1) + + const whitespaceIfNeeded = options?.hideWhitespace ? '' : ' ' + + return `${maskSpecialSymbols(name)}${whitespaceIfNeeded}◆${createTripByKey(key)}` +} + +export const createTrip = (text: string, options?: Options) => createTripByText(text, options) \ No newline at end of file diff --git a/src/module/trip/10digits.ts b/src/module/trip/10digits.ts new file mode 100644 index 0000000..616b817 --- /dev/null +++ b/src/module/trip/10digits.ts @@ -0,0 +1,41 @@ +import { encode } from 'iconv-cp932' +import crypt from 'unix-crypt-td-js' + +/** + * 10 桁トリップを生成する + */ +export const create10DigitsTrip = (key: string) => { + const saltSuffixString = 'H.' +// const encodedKeyString = convert(key, { from: 'UNICODE', to: 'SJIS', fallback: 'html-entity' }) + const encodedKeyString = encode(key).toString() + + const salt = `${encodedKeyString}${saltSuffixString}` + // 1 文字目から 2 文字を取得する + .substr(1, 2) + // . から z までの文字以外を . に置換する + .replace(/[^\.-z]/g, '.') + // 配列にする + .split('') + // salt として使えない記号をアルファベットに置換する + .map((string) => { + if (string === ':') return 'A' + if (string === ';') return 'B' + if (string === '<') return 'C' + if (string === '=') return 'D' + if (string === '>') return 'E' + if (string === '?') return 'F' + if (string === '@') return 'G' + if (string === '[') return 'a' + if (string === '\\') return 'b' + if (string === ']') return 'c' + if (string === '^') return 'd' + if (string === '_') return 'e' + if (string === '`') return 'f' + + return string + }) + // 文字列にする + .join('') + + return (crypt(encodedKeyString, salt) as string).substr(-10, 10) +} \ No newline at end of file diff --git a/src/module/trip/12digits.ts b/src/module/trip/12digits.ts new file mode 100644 index 0000000..4d2bbac --- /dev/null +++ b/src/module/trip/12digits.ts @@ -0,0 +1,13 @@ +import { encode } from 'iconv-cp932' +import { createHash } from 'node:crypto' + +/** + * 12 桁トリップを生成する + */ +export const create12DigitsTrip = (key: string) => { +// const arrayBuffer = convert(key, { from: 'UNICODE', to: 'SJIS', type: 'arraybuffer', fallback: 'html-entity' }) + const arrayBuffer = encode(key) + const byteArray = new Uint8Array(arrayBuffer) + + return createHash('sha1').update(byteArray).digest().toString('base64').replace(/\+/g, '.').substr(0, 12) +} \ No newline at end of file diff --git a/src/module/trip/index.ts b/src/module/trip/index.ts new file mode 100644 index 0000000..11a3e5b --- /dev/null +++ b/src/module/trip/index.ts @@ -0,0 +1,3 @@ +export * from './10digits' +export * from './12digits' +export * from './raw' \ No newline at end of file diff --git a/src/module/trip/raw.ts b/src/module/trip/raw.ts new file mode 100644 index 0000000..b27496c --- /dev/null +++ b/src/module/trip/raw.ts @@ -0,0 +1,26 @@ +import crypt from 'unix-crypt-td-js' + +/** + * 生キートリップを生成する + */ +export const createRawKeyTrip = (key: string) => { + const saltSuffixString = '..' + + const rawKey = key + // 2 文字目以降の全ての文字列を取得 + .substr(1) + // 2 文字ごとに配列に分割する + .match(/.{2}/g)! + // ASCII コードを ASCII 文字に変換する + .map((hexadecimalASCIICode) => { + const demicalASCIICode = parseInt(hexadecimalASCIICode, 16) + + return String.fromCharCode(demicalASCIICode) + }) + // 文字列にする + .join('') + + const salt = `${key}${saltSuffixString}`.substr(17, 2) + + return (crypt(rawKey, salt) as string).substr(-10, 10) +} \ No newline at end of file