[add] 羽球配對功能

This commit is contained in:
建喵 2023-01-18 17:53:14 +08:00
parent ce93877e8d
commit 570c0443d4
13 changed files with 948 additions and 60 deletions

View File

@ -14,16 +14,19 @@
"devDependencies": {
"@types/dateformat": "^5.0.0",
"@types/express": "^4.17.15",
"@types/mysql": "^2.15.21",
"@types/node": "^18.11.18",
"typescript": "^4.9.4"
},
"dependencies": {
"@line/bot-sdk": "^7.5.2",
"dateformat": "^4.5.1",
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"fs": "^0.0.1-security",
"linebot": "^1.6.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.20",
"openai": "^3.1.0",
"ts-node": "^10.9.1",

319
src/Badminton.ts Normal file
View File

@ -0,0 +1,319 @@
import * as line from "@line/bot-sdk";
import dayjs from "dayjs";
import DBTools from "./DBTools";
import { NumberEx } from "./Engine/Number/NumberEx";
/**
* Badminton
*/
export default class Badminton {
//#region Custom
public static async Run(msg: string[]): Promise<line.Message | line.Message[]> {
let message: line.Message | line.Message[] = null;
const instruction: string = msg[1];
switch (instruction) {
case "查詢參加人員": {
const text: string = await this.searchPlay(+msg[2]);
message = {
type: "text",
text: text
};
break;
}
case "查詢對戰人員": {
message = await this.searchMatch(+msg[2]);
break;
}
// case "查詢戰績": {
// const queryresp: any = await this.searchPlay(value);
// message.text = "Success";
// break;
// }
case "輸入名單": {
message = await this.inputList(msg);
break;
}
default:
break;
}
return message;
}
private static async searchPlay(date: number): Promise<string> {
let resp: string = "";
const query: string = String.Format("SELECT * FROM `badminton` WHERE `time` = '{0}' LIMIT 1;", date);
const queryresp: any[] = await DBTools.Query(query);
if (queryresp.length > 0) {
resp = queryresp[0].personnel;
} else {
resp = "這天沒有對戰資料";
}
return resp;
}
private static async searchMatch(date: number): Promise<line.Message | line.Message[]> {
let resp: line.Message | line.Message[] = {
type: "text",
text: "這天沒有對戰資料"
};
const query: string = String.Format("SELECT * FROM `badminton` WHERE `time` = '{0}' LIMIT 1;", date);
const queryresp: any[] = await DBTools.Query(query);
if (queryresp.length > 0) {
const matchData_Str: string = queryresp[0].battlecombination;
if (matchData_Str) {
const matchData: any = JSON.parse(matchData_Str);
resp = this.getMatch_LineFlex(date.toString(), matchData);
}
}
return resp;
}
/**
*
* @param msg
*/
private static async inputList(msg: any[]): Promise<line.Message | line.Message[]> {
const date: number = +msg[2];
let personnelDatas: any[] = [];
for (let i: number = 3; i < msg.length; i++) {
const personnelData: any[] = JSON.parse(msg[i]);
personnelDatas.push(personnelData);
}
const personnel_str: string = JSON.stringify(personnelDatas);
const query: string = String.Format("INSERT INTO `badminton` (time,personnel) VALUES ({0},'{1}') ON DUPLICATE KEY UPDATE personnel='{2}';"
, date, personnel_str, personnel_str);
await DBTools.Query(query);
return await this.listMatch(date, personnelDatas, personnel_str);
}
private static async listMatch(date: number, personnelDatas: any[], personnel_str: string): Promise<line.Message | line.Message[]> {
let man: string[] = [];
let woman: string[] = [];
for (let i: number = 0; i < personnelDatas.length; i++) {
const personnelData: any[] = personnelDatas[i];
if (personnelData[0]) {
man.push(personnelData[1]);
} else {
woman.push(personnelData[1]);
}
}
// 打亂
man.sort(function (): number {
return (0.5 - Math.random());
});
woman.sort(function (): number {
return (0.5 - Math.random());
});
let diffCount: number = Math.abs(NumberEx.minus(man.length, woman.length));
if (man.length !== woman.length && diffCount >= 2) {
const needDiffCount: number = NumberEx.divide(diffCount, 2);
if (man.length > woman.length) {
for (let i: number = 0; i < needDiffCount; i++) {
woman.push(man.shift());
}
} else {
for (let i: number = 0; i < needDiffCount; i++) {
man.push(woman.shift());
}
}
}
const totalRound: number = 3;
const totalCount: number = man.length > woman.length ? man.length : woman.length;
let lastmatch: Object = {};
let check: string[] = [];
let m_temp: number[] = [];
let w_temp: number[] = [];
for (let i: number = 0; i < totalCount; i++) {
m_temp.push(i);
w_temp.push(i);
}
for (let i: number = 0; i < totalRound; i++) {
const [match_num, check_temp] = this.getMatch(totalCount, check, m_temp, w_temp);
let match: string[][] = [];
check = check_temp;
for (let j: number = 0; j < match_num.length; j++) {
const [m, w] = match_num[j];
const man_str: string = man[m] ?? "那個";
const woman_str: string = woman[w] ?? "那個";
match.push([man_str, woman_str]);
}
lastmatch[i] = match;
}
// console.log(`manCount: ${man.length}, womanCount: ${woman.length}`);
const result: string = JSON.stringify(lastmatch);
const query: string = String.Format("INSERT INTO `badminton` (time,personnel,battlecombination) VALUES ({0},'{1}','{3}') ON DUPLICATE KEY UPDATE battlecombination='{2}';"
, date, personnel_str, result, result);
// console.log(`query: ${query}`);
await DBTools.Query(query);
let message: line.Message | line.Message[] = this.getMatch_LineFlex(date.toString(), lastmatch);
return message;
}
/**
*
* @param totalCount
* @param check
* @param m_temp
* @param w_temp
* @param repeatCount
*/
private static getMatch(totalCount: number, check: string[], m_temp: number[], w_temp: number[]): [number[][], string[]] {
const repeatMaxCount: number = 10;
let check_temp: string[] = [].concat(check);
const match: number[][] = [];
let m: number[] = [].concat(m_temp);
let w: number[] = [].concat(w_temp);
// 打亂
m.sort(function (): number {
return (0.5 - Math.random());
});
w.sort(function (): number {
return (0.5 - Math.random());
});
for (let j: number = 0; j < totalCount; j++) {
for (let k: number = 0; k < repeatMaxCount; k++) {
const check_str: string = `m${m[0]}w${w[0]}`;
if (check.includes(check_str) && j !== totalCount - 1) {
w.sort(function (): number {
return (0.5 - Math.random());
});
continue;
}
check_temp.push(check_str);
match.push([m.shift(), w.shift()]);
break;
}
}
return [match, check_temp];
}
/**
* Line模板
* @param date
* @param matchs
*/
private static getMatch_LineFlex(date: string, matchs: Object): line.Message | line.Message[] {
const contents: any[] = [];
const dateTime_Str: string = `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
let dateTime: number = new Date(dateTime_Str).getTime();
let date_Str: string = dayjs(Math.floor(dateTime)).format("YYYY-MM-DD");
for (let i: number = 0, matchKey: string[] = Object.keys(matchs); i < matchKey.length; i++) {
const key: string = matchKey[i];
const match: string[] = matchs[key];
let boxs: any[] = [];
const bubble: any = {
"type": "bubble",
"size": "micro",
"body": {
"type": "box",
"layout": "vertical"
},
"styles": {
"footer": {
"separator": true
}
}
};
const bubble_contents: Object = [
{
"type": "text",
"text": "勝皇羽球團",
"weight": "bold",
"color": "#1DB446",
"size": "sm"
},
{
"type": "text",
"text": date_Str,
"weight": "bold",
"size": "xl",
"margin": "sm"
},
{
"type": "text",
"text": `${i + 1}`,
"weight": "bold",
"size": "xxl",
"margin": "sm"
},
{
"type": "separator",
"margin": "md"
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "一號隊友",
"size": "sm",
"flex": 0
},
{
"type": "text",
"text": "二號隊友",
"size": "sm",
"align": "center"
}
],
"margin": "md"
},
{
"type": "separator",
"margin": "sm"
},
{
"type": "box",
"layout": "vertical",
"contents": boxs,
"spacing": "sm",
"margin": "md"
}];
for (let j: number = 0; j < match.length; j++) {
const box: any = {
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": match[j][0],
"size": "sm",
"flex": 0
},
{
"type": "text",
"text": match[j][1],
"size": "sm",
"align": "center"
}
]
};
boxs.push(box);
}
bubble.body["contents"] = bubble_contents;
contents.push(bubble);
}
const messages: line.Message[] = [
{
"type": "flex",
"altText": "對戰組合名單",
"contents":
{
"type": "carousel",
"contents": contents
}
}
];
return messages;
}
//#endregion
}

44
src/DBTools.ts Normal file
View File

@ -0,0 +1,44 @@
import mysql from "mysql";
import Tools from "./Tools";
/**
* DBTools
*/
export default class DBTools {
//#region Custom
public static async Query(query: string): Promise<any> {
const conn: mysql.Connection = this.connect();
let resp: any = null;
let run: boolean = true;
conn.query(query, function (err: mysql.MysqlError, rows: any, fields: mysql.FieldInfo[]): void {
if (err) {
console.error(`${query} Error: \n${err.message}`);
run = false;
}
resp = rows;
run = false;
});
while (run) {
await Tools.Sleep(100);
}
conn.end();
return resp;
}
private static connect(): mysql.Connection {
const conn: mysql.Connection = mysql.createConnection({
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE
});
conn.connect();
return conn;
}
//#endregion
}

View File

@ -0,0 +1,116 @@
declare interface Array<T> {
/**
*
* @param index
*/
ExRemoveAt(index: number): T;
/**
* (. )
* @example
*
* let bar: number[] = [1, 2, 3];
* let bar2: number[] = bar;
* bar.Clear();
* console.log(bar, bar2);
*
* // {
* // "bar": [],
* // "bar2": []
* // }
*/
Clear(): void;
/**
* asc&key陣列長度請一樣
* PS. boolean false是先true在false
* @link JavaScript Object http://www.eion.com.tw/Blogger/?Pid=1170#:~:text=JavaScript%20Object%20排序
* @param asc ()
* @param key key()()
*/
ObjectSort(asc?: boolean[], key?: string[]): any[];
/**
* Array<cc.Component.EventHandler>forHoldButton使用
* Add a non persistent listener to the UnityEvent.
* @param call Callback function.
*/
AddListener(call: Function): void;
}
Array.prototype.ExRemoveAt || Object.defineProperty(Array.prototype, "ExRemoveAt", {
enumerable: false,
value: function (index: number): any {
let item: any = this.splice(index, 1);
return item[0];
}
});
Array.prototype.Clear || Object.defineProperty(Array.prototype, "Clear", {
enumerable: false,
value: function (): void {
this.length = 0;
// let foo: number[] = [1, 2, 3];
// let bar: number[] = [1, 2, 3];
// let foo2: number[] = foo;
// let bar2: number[] = bar;
// foo = [];
// bar.length = 0;
// console.log(foo, bar, foo2, bar2);
// {
// "foo": [],
// "bar": [],
// "foo2": [
// 1,
// 2,
// 3
// ],
// "bar2": []
// }
}
});
Array.prototype.ObjectSort || Object.defineProperty(Array.prototype, "ObjectSort", {
enumerable: false,
/**
* @param asc ()
* @param key key()()
*/
value: function (asc: boolean[] = [true], key?: string[]): any[] {
if (this.length === 0) {
return this;
} else if (!key || key.length === 0) {
console.error(`ObjectSort key error`);
return this;
} else if (asc.length !== key.length) {
console.error(`ObjectSort key asc error asc.length: ${asc.length}, key.length: ${key.length}`);
return this;
}
for (let i: number = 0; i < key.length; i++) {
const keyname: string = key[i];
if (this[0][keyname] === undefined) {
console.error(`ObjectSort has not key[${i}]: ${keyname}`);
return this;
}
}
let count: number = key ? key.length : 1;
let arr: any[];
for (let i: number = count - 1; i >= 0; i--) {
arr = this.sort(function (a: any, b: any): 1 | -1 {
let mya: any = a;
let myb: any = b;
if (key) {
mya = a[key[i]];
myb = b[key[i]];
}
// 加個等於數字相同不要再去排序到
if (asc[i]) {
return mya >= myb ? 1 : -1;
} else {
return mya <= myb ? 1 : -1;
}
});
}
return arr;
}
});

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "b373f805-9297-4af5-8ea6-0a250649b5b0",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,189 @@
declare interface Number {
/**
* (), 2
* 41,038,560.00
* @param precision
* @param isPadZero
* */
ExFormatNumberWithComma(precision?: number, isPadZero?: boolean): string;
/**
* 4(9,999-999B-T)
* */
ExTransferToBMK(precision?: number,offset?: number): string;
/**
* , 0
* @param size
*/
Pad(size: number): string;
/**
* X位 (server計算規則)
* @param precision
*/
ExToNumRoundDecimal(precision: number): number;
/**
* X位
* @param precision
*/
ExToNumFloorDecimal(precision: number): number;
/**
* X位小數2200.2.00
* @param precision
* @param isPadZero
*/
ExToStringFloorDecimal(precision: number, isPadZero?: boolean): string;
/**
* )
*/
ExToInt():number;
/**
* ()
*/
Float2Fixed():number;
/**
* ()
*/
DigitLength():number;
target: number;
}
Number.prototype.ExFormatNumberWithComma || Object.defineProperty(Number.prototype, 'ExFormatNumberWithComma', {
enumerable: false,
value: function (precision: number = 2, isPadZero: boolean = true) {
// let arr = String(this).split('.');
let arr = this.ExToStringFloorDecimal(precision, isPadZero).split('.');
let num = arr[0], result = '';
while (num.length > 3) {
result = ',' + num.slice(-3) + result;
num = num.slice(0, num.length - 3);
}
if (num.length > 0) result = num + result;
return arr[1] ? result + '.' + arr[1] : result;
}
})
Number.prototype.ExTransferToBMK || Object.defineProperty(Number.prototype, 'ExTransferToBMK', {
enumerable: false,
value: function (precision: number=2,offset: number = 0) {
/**千 */
let MONEY_1K: number = 1000;
/**萬 */
// let MONEY_10K: number = 10000;
/**十萬 */
// let MONEY_100K: number = 100000;
/**百萬 */
let MONEY_1M: number = 1000000;
/**千萬 */
// let MONEY_10M: number = 10000000;
/**億 */
// let MONEY_100M: number = 100000000;
/**十億 */
let MONEY_1B: number = 1000000000;
/**百億 */
// let MONEY_10B: number = 10000000000;
/**千億 */
// let MONEY_100B: number = 100000000000;
/**兆 */
// let MONEY_1T: number = 1000000000000;
offset = Math.pow(10, offset);
// if (this >= MONEY_1T * offset) {
// //(3)1,000T
// //1T~
// return (~~(this / MONEY_1T)).ExFormatNumberWithComma(0) + "T";
// }
if (this >= MONEY_1B * offset) {
//1,000B~900,000B
//1B~900B
return (this / MONEY_1B).ExFormatNumberWithComma(3, false) + "B";
}
else if (this >= MONEY_1M * offset) {
//1,000M~900,000M
//1M~900M
return (this / MONEY_1M).ExFormatNumberWithComma(3, false) + "M";
}
else if (this >= MONEY_1K * offset) {
//1,000K~900,000K
//1K~90K
return (this / MONEY_1K).ExFormatNumberWithComma(3, false) + "K";
}
else {
//0~9,000,000
//0~9,000
return this.ExFormatNumberWithComma(precision);
}
}
})
Number.prototype.Pad || Object.defineProperty(Number.prototype, 'Pad', {
enumerable: false,
value: function (size: number) {
let s = this + "";
while (s.length < size) s = "0" + s;
return s;
}
})
Number.prototype.ExToNumRoundDecimal || Object.defineProperty(Number.prototype, 'ExToNumRoundDecimal', {
enumerable: false,
value: function (precision: number) {
return Math.round(Math.round(this * Math.pow(10, (precision || 0) + 1)) / 10) / Math.pow(10, (precision || 0));
}
})
Number.prototype.ExToInt || Object.defineProperty(Number.prototype, 'ExToInt',{
enumerable: false,
value: function (){
return ~~this;
}
})
Number.prototype.ExToNumFloorDecimal || Object.defineProperty(Number.prototype, 'ExToNumFloorDecimal', {
enumerable: false,
value: function (precision: number) {
let str = this.toPrecision(12);
let dotPos = str.indexOf('.');
return dotPos == -1 ? this : +`${str.substr(0, dotPos + 1 + precision)}`;
}
})
Number.prototype.ExToStringFloorDecimal || Object.defineProperty(Number.prototype, 'ExToStringFloorDecimal', {
enumerable: false,
value: function (precision: number, isPadZero: boolean = true) {
// 取小數點第X位
let f = this.ExToNumFloorDecimal(precision);
let s = f.toString();
// 補0
if (isPadZero) {
let rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + precision) {
s += '0';
}
}
return s;
}
})
Number.prototype.Float2Fixed || Object.defineProperty(Number.prototype, 'Float2Fixed', {
enumerable: false,
value: function () {
if (this.toString().indexOf('e') === -1) {
return Number(this.toString().replace('.', ''));
}
const dLen = this.DigitLength();
return dLen > 0 ? +parseFloat((this * Math.pow(10, dLen)).toPrecision(12)) : this;
}
})
Number.prototype.DigitLength || Object.defineProperty(Number.prototype, 'DigitLength', {
enumerable: false,
value: function () {
const eSplit = this.toString().split(/[eE]/);
const len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
return len > 0 ? len : 0;
}
})

View File

@ -0,0 +1,84 @@
export module NumberEx {
/**
*
* @param {*number} num
*/
function checkBoundary(num: number) {
if (_boundaryCheckingState) {
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
}
}
}
/**
*
*/
export function times(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return times(times(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = num1.Float2Fixed();
const num2Changed = num2.Float2Fixed();
const baseNum = num1.DigitLength() + num2.DigitLength();
const leftValue = num1Changed * num2Changed;
checkBoundary(leftValue);
return leftValue / Math.pow(10, baseNum);
}
/**
*
*/
export function plus(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return plus(plus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
}
/**
*
*/
export function minus(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return minus(minus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
}
/**
*
*/
export function divide(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return divide(divide(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = num1.Float2Fixed();
const num2Changed = num2.Float2Fixed();
checkBoundary(num1Changed);
checkBoundary(num2Changed);
return times((num1Changed / num2Changed), Math.pow(10, num2.DigitLength() - num1.DigitLength()));
}
/**
*
*/
export function round(num: number, ratio: number): number {
const base = Math.pow(10, ratio);
return divide(Math.round(times(num, base)), base);
}
let _boundaryCheckingState = false;
/**
*
* @param flag true false
*/
function enableBoundaryChecking(flag = true) {
_boundaryCheckingState = flag;
}
}

View File

@ -0,0 +1,90 @@
export module RandomEx {
/**
*
*/
export function GetBool() {
return GetInt() >= 0;
}
/**
* (min ~ max - 1)
* @param min
* @param max
*/
export function GetInt(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
return Math.floor(Math.random() * (max - min)) + min;
}
/**
*
* @param min
* @param max
*/
export function GetFloat(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
return Math.random() * (max - min) + min;
}
/**
*
* @param num
* @param items
*/
export function GetMultiNoRepeat(num: number, items: any[]): any[] {
let result: any[] = [];
for (let i: number = 0; i < num; i++) {
let ran: number = Math.floor(Math.random() * items.length);
let item = items.splice(ran, 1)[0];
if (result.indexOf(item) == -1) {
result.push(item);
}
};
return result;
}
/**
*
* @param prize
* @param weights
* @param count
*/
export function GetMultiNoRepeatByWeight(prize: any[], weights: number[] = null, count: number = 1): any[] {
if (weights === null) {
weights = [];
for (let i: number = 0; i < prize.length; i++) {
weights.push(1);
}
}
let target: any[] = [];
for (let i: number = 0; i < count; i++) {
let results: number[] = RandomEx.GetPrizeByWeight(prize, weights);
prize.splice(results[0], 1);
weights.splice(results[0], 1);
target.push(results[1]);
}
return target;
}
/**
*
* @param prize
* @param weights
*/
export function GetPrizeByWeight(prize: any[], weights: number[]): any[] {
if (prize.length !== weights.length) {
console.error(`GetWeight error -> prize.length:${prize.length} !== weights.length:${weights.length}`);
return null;
}
let totalWeight: number = 0;
for (let i: number = 0; i < weights.length; i++) {
totalWeight += weights[i];
}
let random: number = RandomEx.GetInt(0, totalWeight) + 1;
let nowWeight: number = weights[0];
for (let i: number = 0; i < weights.length; i++) {
if (nowWeight >= random) {
return [i, prize[i]];
}
nowWeight += weights[i + 1];
}
}
}

16
src/Engine/String.ts Normal file
View File

@ -0,0 +1,16 @@
interface StringConstructor {
IsNullOrEmpty: (value: string) => boolean;
Format: (format: string, ...args: any[]) => string;
}
String.IsNullOrEmpty = function (value: string): boolean {
return value === undefined || value === null || value.trim() === "";
};
String.Format = function (format: string, ...args: any[]): string {
return format.replace(/{(\d+)}/g, (match, index) => {
let value: any = args[index];
if (value === null || value === undefined) { return ""; }
return "" + value;
});
};

View File

@ -1,4 +1,5 @@
import * as line from "@line/bot-sdk";
import Badminton from "./Badminton";
import OpenAI from "./OpenAI";
/**
@ -68,8 +69,8 @@ export default class MessageClass {
}
public async User(event: any): Promise<any> {
let userId = event.source.userId;
let replyMsg = event.message.text;
let userId: string = event.source.userId;
let replyMsg: string = event.message.text;
// let displayName = "";
// let profile = await this.bot.getProfile(userId);
// if (profile) {
@ -77,61 +78,34 @@ export default class MessageClass {
// }
// 豬喵 特別功能
if ([process.env.toJianMiau, process.env.toZhuHan].includes(userId)) {
/** 訊息 */
let msg: string[] = event.message.text.split(" ");
if (userId === process.env.toJianMiau) {
// 建喵 指令功能
/** 指令 */
let instruction: string = msg[0];
switch (instruction) {
case "羽球": {
const messages: line.Message | line.Message[] = await Badminton.Run(msg);
if (messages) {
return this.bot.replyMessage(event.replyToken, messages);
}
}
default: {
const response: string = await OpenAI.RunOpenAI(replyMsg);
replyMsg = response;
break;
}
}
} else {
// 豬涵 指令功能
const response: string = await OpenAI.RunOpenAI(replyMsg);
replyMsg = response;
}
// /** 訊息 */
// let Msg = event.message.text.split(" ");
}
// /** 指令 */
// let Instruction = Msg[0];
// switch (Instruction) {
// case "msg":
// case "Msg":
// case "MSG": {
// if (userId == process.env.toJianMiau) {
// replyMsg = "";
// if (Msg[1] === "豬涵") {
// if (Msg[2] === "豬涵") {
// Msg[2] = process.env.toZhuHantoZhuHan;
// } else if (Msg[2] === "建喵") {
// Msg[2] = process.env.toZhuHantoJianMiau;
// }
// for (let i = 3; i < Msg.length; i++) {
// replyMsg += Msg[i] + (i === Msg.length - 1 ? "" : " ");
// }
// let res_Msg = this.ZhuHanbot.push(Msg[2], replyMsg);
// } else {
// for (let i = 3; i < Msg.length; i++) {
// replyMsg += Msg[i] + (i === Msg.length - 1 ? "" : " ");
// }
// let res_Msg = this.bot.push(Msg[2], replyMsg);
// }
// let ToJM_message = "已發送訊息:";
// ToJM_message += `\nMyId: ${Msg[1]}`;
// ToJM_message += `\nuserId: ${Msg[2]}`;
// ToJM_message += `\nmessage: ${replyMsg}`;
// let res_reply = event.reply(ToJM_message).then(function (data) {
// // 當訊息成功回傳後的處理
// }).catch(function (error) {
// // 當訊息回傳失敗後的處理
// });
// }
// break;
// }
// default: {
// // 使用event.reply(要回傳的訊息)方法可將訊息回傳給使用者
// event.reply(replyMsg).then(function (data) {
// // 當訊息成功回傳後的處理
// }).catch(function (error) {
// // 當訊息回傳失敗後的處理
// });
// break;
// }
// }
// }
return this.bot.replyMessage(event.replyToken, {
type: "text",
text: replyMsg
@ -142,6 +116,29 @@ export default class MessageClass {
// });
}
public async Group(event: any): Promise<any> {
let groupId: string = event.source.groupId;
// 羽球 特別功能
if ([process.env.toBadminton].includes(groupId)) {
/** 訊息 */
let msg: string[] = event.message.text.split(" ");
/** 指令 */
let instruction: string = msg[0];
switch (instruction) {
case "羽球": {
const messages: line.Message | line.Message[] = await Badminton.Run(msg);
if (messages) {
return this.bot.replyMessage(event.replyToken, messages);
}
}
default: {
break;
}
}
}
}
// Group(event) {
// switch (event.source.groupId) {
// case process.env.toYoutube: {

View File

@ -8,13 +8,14 @@ export default class OpenAI {
//#region Custom
public static async RunOpenAI(msg: string): Promise<string> {
const configuration = new Configuration({
const configuration: Configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
const openai: OpenAIApi = new OpenAIApi(configuration);
// tslint:disable-next-line:typedef
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: msg,
prompt: "人類:" + msg,
temperature: 0.7,
max_tokens: 256,
top_p: 1,
@ -22,8 +23,8 @@ export default class OpenAI {
presence_penalty: 0,
});
let resptext: string = msg;
const choices = response.data.choices;
for (let i = 0; i < choices.length; i++) {
const choices: CreateCompletionResponseChoicesInner[] = response.data.choices;
for (let i: number = 0; i < choices.length; i++) {
const choice: CreateCompletionResponseChoicesInner = choices[i];
resptext += choice.text;
}

13
src/Tools.ts Normal file
View File

@ -0,0 +1,13 @@
/**
* Tools
*/
export default class Tools {
//#region Custom
public static Sleep(ms: number): Promise<any> {
return new Promise(resolve => setTimeout(resolve, ms));
}
//#endregion
}

View File

@ -3,8 +3,14 @@
// 監聽檔案變化 "npm start"
// 連線Debug "npm run dev"
import dayjs from "dayjs";
import "dayjs/locale/zh-tw";
import dotenv from "dotenv";
import "./Engine/CCExtensions/ArrayExtension";
import "./Engine/CCExtensions/NumberExtension";
import "./Engine/String";
import LineBotClass from "./LineBotClass";
dayjs.locale("zh-tw");
dotenv.config();
new LineBotClass();