Commit 1e0613cb authored by nanahira's avatar nanahira

Merge branch 'master' into enter-room-log

parents 78da1f9d 103429ba
Pipeline #10117 passed with stages
in 40 minutes and 22 seconds
......@@ -8,7 +8,7 @@ RUN apt update && \
rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*
# windbot
RUN git clone --depth=1 https://github.com/nanahira/windbot /tmp/windbot && \
RUN git clone --depth=1 https://code.mycard.moe/nanahira/windbot /tmp/windbot && \
cd /tmp/windbot && \
xbuild /property:Configuration=Release /property:TargetFrameworkVersion="v4.5" && \
mv /tmp/windbot/bin/Release /ygopro-server/windbot && \
......
......@@ -11,6 +11,8 @@ const typedefs_json_1 = __importDefault(require("./data/typedefs.json"));
const proto_structs_json_1 = __importDefault(require("./data/proto_structs.json"));
const constants_json_1 = __importDefault(require("./data/constants.json"));
class Handler {
handler;
synchronous;
constructor(handler, synchronous) {
this.handler = handler;
this.synchronous = synchronous || false;
......@@ -28,6 +30,13 @@ class Handler {
}
}
class YGOProMessagesHelper {
handlers;
structs;
structs_declaration;
typedefs;
proto_structs;
constants;
singleHandleLimit;
constructor(singleHandleLimit) {
this.handlers = {
STOC: [new Map(),
......@@ -62,7 +71,7 @@ class YGOProMessagesHelper {
this.structs = new Map();
for (let name in this.structs_declaration) {
const declaration = this.structs_declaration[name];
let result = struct_1.Struct();
let result = (0, struct_1.Struct)();
for (let field of declaration) {
if (field.encoding) {
switch (field.encoding) {
......@@ -171,12 +180,13 @@ class YGOProMessagesHelper {
}
handlerCollection.get(translatedProto).push(handlerObj);
}
async handleBuffer(messageBuffer, direction, protoFilter, params) {
async handleBuffer(messageBuffer, direction, protoFilter, params, preconnect = false) {
let feedback = null;
let messageLength = 0;
let bufferProto = 0;
let datas = [];
for (let l = 0; l < this.singleHandleLimit; ++l) {
const limit = preconnect ? 2 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) {
if (messageLength === 0) {
if (messageBuffer.length >= 2) {
messageLength = messageBuffer.readUInt16LE(0);
......@@ -206,7 +216,14 @@ class YGOProMessagesHelper {
else {
if (messageBuffer.length >= 2 + messageLength) {
const proto = this.constants[direction][bufferProto];
let cancel = proto && protoFilter && underscore_1.default.indexOf(protoFilter, proto) === -1;
let cancel = proto && protoFilter && !protoFilter.includes(proto);
if (cancel && preconnect) {
feedback = {
type: "INVALID_PACKET",
message: `${direction} proto not allowed`
};
break;
}
let buffer = messageBuffer.slice(3, 2 + messageLength);
//console.log(l, direction, proto, cancel);
for (let priority = 0; priority < 4; ++priority) {
......@@ -224,6 +241,12 @@ class YGOProMessagesHelper {
for (let handler of handlerCollection.get(bufferProto)) {
cancel = await handler.handle(buffer, info, datas, params);
if (cancel) {
if (cancel === '_cancel') {
return {
datas: [],
feedback
};
}
break;
}
}
......@@ -246,10 +269,10 @@ class YGOProMessagesHelper {
break;
}
}
if (l === this.singleHandleLimit - 1) {
if (l === limit - 1) {
feedback = {
type: "OVERSIZE",
message: `Oversized ${direction}`
message: `Oversized ${direction} ${limit}`
};
}
}
......
......@@ -8,13 +8,13 @@ import net from "net";
class Handler {
private handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean>;
private handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>;
synchronous: boolean;
constructor(handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean>, synchronous: boolean) {
constructor(handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>, synchronous: boolean) {
this.handler = handler;
this.synchronous = synchronous || false;
}
async handle(buffer: Buffer, info: any, datas: Buffer[], params: any) {
async handle(buffer: Buffer, info: any, datas: Buffer[], params: any): Promise<boolean | string> {
if (this.synchronous) {
return !!(await this.handler(buffer, info, datas, params));
} else {
......@@ -208,7 +208,7 @@ export class YGOProMessagesHelper {
});
}
addHandler(protostr: string, handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean>, synchronous: boolean, priority: number) {
addHandler(protostr: string, handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>, synchronous: boolean, priority: number) {
if (priority < 0 || priority > 4) {
throw "Invalid priority: " + priority;
}
......@@ -226,12 +226,13 @@ export class YGOProMessagesHelper {
handlerCollection.get(translatedProto).push(handlerObj);
}
async handleBuffer(messageBuffer: Buffer, direction: string, protoFilter?: string[], params?: any): Promise<HandleResult> {
async handleBuffer(messageBuffer: Buffer, direction: string, protoFilter?: string[], params?: any, preconnect = false): Promise<HandleResult> {
let feedback: Feedback = null;
let messageLength = 0;
let bufferProto = 0;
let datas: Buffer[] = [];
for (let l = 0; l < this.singleHandleLimit; ++l) {
const limit = preconnect ? 2 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) {
if (messageLength === 0) {
if (messageBuffer.length >= 2) {
messageLength = messageBuffer.readUInt16LE(0);
......@@ -257,7 +258,14 @@ export class YGOProMessagesHelper {
} else {
if (messageBuffer.length >= 2 + messageLength) {
const proto = this.constants[direction][bufferProto];
let cancel = proto && protoFilter && _.indexOf(protoFilter, proto) === -1;
let cancel: string | boolean = proto && protoFilter && !protoFilter.includes(proto);
if (cancel && preconnect) {
feedback = {
type: "INVALID_PACKET",
message: `${direction} proto not allowed`
};
break;
}
let buffer = messageBuffer.slice(3, 2 + messageLength);
//console.log(l, direction, proto, cancel);
for (let priority = 0; priority < 4; ++priority) {
......@@ -275,6 +283,12 @@ export class YGOProMessagesHelper {
for (let handler of handlerCollection.get(bufferProto)) {
cancel = await handler.handle(buffer, info, datas, params);
if (cancel) {
if (cancel === '_cancel') {
return {
datas: [],
feedback
}
}
break;
}
}
......@@ -296,10 +310,10 @@ export class YGOProMessagesHelper {
break;
}
}
if (l === this.singleHandleLimit - 1) {
if (l === limit - 1) {
feedback = {
type: "OVERSIZE",
message: `Oversized ${direction}`
message: `Oversized ${direction} ${limit}`
};
}
}
......
......@@ -8,6 +8,9 @@ const axios_1 = __importDefault(require("axios"));
const querystring_1 = __importDefault(require("querystring"));
const moment_1 = __importDefault(require("moment"));
class AthleticChecker {
config;
athleticDeckCache;
lastAthleticDeckFetchTime;
constructor(config) {
this.config = config;
}
......@@ -16,7 +19,7 @@ class AthleticChecker {
return deckText;
}
async getAthleticDecks() {
if (this.athleticDeckCache && moment_1.default().diff(this.lastAthleticDeckFetchTime, "seconds") < this.config.ttl) {
if (this.athleticDeckCache && (0, moment_1.default)().diff(this.lastAthleticDeckFetchTime, "seconds") < this.config.ttl) {
return this.athleticDeckCache;
}
const { data } = await axios_1.default.get(this.config.rankURL, {
......@@ -27,7 +30,7 @@ class AthleticChecker {
});
const athleticDecks = data.slice(0, this.config.rankCount).map(m => m.name);
this.athleticDeckCache = athleticDecks;
this.lastAthleticDeckFetchTime = moment_1.default();
this.lastAthleticDeckFetchTime = (0, moment_1.default)();
return athleticDecks;
}
async getDeckType(deck) {
......@@ -42,7 +45,7 @@ class AthleticChecker {
try {
const athleticDecks = await this.getAthleticDecks();
const deckType = await this.getDeckType(deck);
const athletic = athleticDecks.includes(deckType);
const athletic = athleticDecks.findIndex(d => d === deckType) + 1;
return { success: true, athletic, message: null };
}
catch (e) {
......
......@@ -21,7 +21,7 @@ interface AthleticDecksReturnData {
interface ReturnMessage {
success: boolean;
athletic?: boolean;
athletic?: number;
message: string;
}
......@@ -63,8 +63,8 @@ export class AthleticChecker {
try {
const athleticDecks = await this.getAthleticDecks();
const deckType = await this.getDeckType(deck);
const athletic = athleticDecks.includes(deckType);
return { success: true, athletic, message: null }
const athletic = athleticDecks.findIndex(d => d === deckType) + 1;
return { success: true, athletic, message: null };
} catch (e) {
return { success: false, message: e.toString() };
}
......
......@@ -40,35 +40,40 @@ const jszip_1 = __importDefault(require("jszip"));
const fs = __importStar(require("fs"));
require("reflect-metadata");
class DataManager {
config;
log;
ready;
db;
constructor(config, log) {
this.config = config;
this.ready = false;
this.log = log;
this.ready = false;
}
async transaction(fun) {
const runner = this.db.createQueryRunner();
await runner.connect();
await runner.startTransaction();
let result = false;
try {
result = await fun(runner.manager);
// @ts-ignore
if (this.config.type !== 'sqlite') {
this.db.transaction(async (mdb) => {
const result = await fun(mdb);
if (!result) {
throw new Error('Rollback requested.');
}
});
}
else {
await fun(this.db.manager);
}
}
catch (e) {
result = false;
this.log.warn(`Failed running transaction: ${e.toString()}`);
}
if (result) {
await runner.commitTransaction();
this.log.warn(`Transaction failed: ${e.toString()}`);
}
else {
await runner.rollbackTransaction();
}
await runner.release();
}
async init() {
this.db = await typeorm_1.createConnection({
this.db = await (0, typeorm_1.createConnection)({
type: "mysql",
synchronize: true,
supportBigNumbers: true,
bigNumberStrings: false,
entities: ["./data-manager/entities/*.js"],
...this.config
});
......@@ -76,8 +81,13 @@ class DataManager {
}
async getCloudReplaysFromKey(key) {
try {
const replays = await this.db.createQueryBuilder(CloudReplay_1.CloudReplay, "replay")
.where("exists (select id from cloud_replay_player where cloud_replay_player.cloudReplayId = replay.id and cloud_replay_player.key = :key)", { key })
const replaysQuery = this.db.createQueryBuilder(CloudReplay_1.CloudReplay, "replay");
const sqb = replaysQuery.subQuery()
.select('splayer.id')
.from(CloudReplayPlayer_1.CloudReplayPlayer, 'splayer')
.where('splayer.cloudReplayId = replay.id')
.andWhere('splayer.key = :key');
const replays = await replaysQuery.where(`exists ${sqb.getQuery()}`, { key })
.orderBy("replay.date", "DESC")
.limit(10)
.leftJoinAndSelect("replay.players", "player")
......@@ -125,7 +135,7 @@ class DataManager {
const replay = new CloudReplay_1.CloudReplay();
replay.id = id;
replay.fromBuffer(buffer);
replay.date = moment_1.default().toDate();
replay.date = (0, moment_1.default)().toDate();
const players = playerInfos.map(p => {
const player = CloudReplayPlayer_1.CloudReplayPlayer.fromPlayerInfo(p);
return player;
......@@ -216,12 +226,12 @@ class DataManager {
if (ban) {
ban.count += count;
const banTime = ban.count > 3 ? Math.pow(2, ban.count - 3) * 2 : 0;
const banDate = moment_1.default(ban.time);
if (moment_1.default().isAfter(banDate)) {
ban.time = moment_1.default().add(banTime, 'm').toDate();
const banDate = (0, moment_1.default)(ban.time);
if ((0, moment_1.default)().isAfter(banDate)) {
ban.time = (0, moment_1.default)().add(banTime, 'm').toDate();
}
else {
ban.time = moment_1.default(banDate).add(banTime, 'm').toDate();
ban.time = (0, moment_1.default)(banDate).add(banTime, 'm').toDate();
}
if (!underscore_1.default.contains(ban.reasons, reason)) {
ban.reasons.push(reason);
......@@ -231,7 +241,7 @@ class DataManager {
else {
ban = new RandomDuelBan_1.RandomDuelBan();
ban.ip = ip;
ban.time = moment_1.default().toDate();
ban.time = (0, moment_1.default)().toDate();
ban.count = count;
ban.reasons = [reason];
ban.needTip = 1;
......@@ -275,18 +285,24 @@ class DataManager {
queryBuilder.andWhere("duelLog.duelCount = :duelCount", { duelCount });
}
if (playerName != null && playerName.length || playerScore != null && !isNaN(playerScore)) {
let innerQuery = "select id from duel_log_player where duel_log_player.duelLogId = duelLog.id";
const sqb = queryBuilder.subQuery()
.select('splayer.id')
.from(DuelLogPlayer_1.DuelLogPlayer, 'splayer')
.where('splayer.duelLogId = duelLog.id');
//let innerQuery = "select id from duel_log_player where duel_log_player.duelLogId = duelLog.id";
const innerQueryParams = {};
if (playerName != null && playerName.length) {
//const escapedPlayerName = this.getEscapedString(playerName);
innerQuery += " and duel_log_player.realName = :playerName";
sqb.andWhere('splayer.realName = :playerName');
//innerQuery += " and duel_log_player.realName = :playerName";
innerQueryParams.playerName = playerName;
}
if (playerScore != null && !isNaN(playerScore)) {
innerQuery += " and duel_log_player.score = :playerScore";
//innerQuery += " and duel_log_player.score = :playerScore";
sqb.andWhere('splayer.score = :playerScore');
innerQueryParams.playerScore = playerScore;
}
queryBuilder.andWhere(`exists (${innerQuery})`, innerQueryParams);
queryBuilder.andWhere(`exists ${sqb.getQuery()}`, innerQueryParams);
}
queryBuilder.orderBy("duelLog.id", "DESC")
.leftJoinAndSelect("duelLog.players", "player");
......@@ -313,8 +329,16 @@ class DataManager {
async getDuelLogFromRecoverSearch(realName) {
const repo = this.db.getRepository(DuelLog_1.DuelLog);
try {
const duelLogs = await repo.createQueryBuilder("duelLog")
.where("startDeckBuffer is not null and currentDeckBuffer is not null and roomMode != 2 and exists (select id from duel_log_player where duel_log_player.duelLogId = duelLog.id and duel_log_player.realName = :realName)", { realName })
const duelLogsQuery = repo.createQueryBuilder("duelLog")
.where('startDeckBuffer is not null')
.andWhere('currentDeckBuffer is not null')
.andWhere('roomMode != 2');
const sqb = duelLogsQuery.subQuery()
.select('splayer.id')
.from(DuelLogPlayer_1.DuelLogPlayer, 'splayer')
.andWhere('splayer.duelLogId = duelLog.id')
.andWhere('splayer.realName = :realName');
const duelLogs = await duelLogsQuery.andWhere(`exists ${sqb.getQuery()}`, { realName })
.orderBy("duelLog.id", "DESC")
.limit(10)
.leftJoinAndSelect("duelLog.players", "player")
......@@ -392,7 +416,7 @@ class DataManager {
async saveDuelLog(name, roomId, cloudReplayId, replayFilename, roomMode, duelCount, playerInfos) {
const duelLog = new DuelLog_1.DuelLog();
duelLog.name = name;
duelLog.time = moment_1.default().toDate();
duelLog.time = (0, moment_1.default)().toDate();
duelLog.roomId = roomId;
duelLog.cloudReplayId = cloudReplayId;
duelLog.replayFileName = replayFilename;
......@@ -599,11 +623,11 @@ class DataManager {
}
const keyType = vipKey.type;
const previousDate = user.vipExpireDate;
if (previousDate && moment_1.default().isBefore(previousDate)) {
user.vipExpireDate = moment_1.default(previousDate).add(keyType, "d").toDate();
if (previousDate && (0, moment_1.default)().isBefore(previousDate)) {
user.vipExpireDate = (0, moment_1.default)(previousDate).add(keyType, "d").toDate();
}
else {
user.vipExpireDate = moment_1.default().add(keyType, "d").toDate();
user.vipExpireDate = (0, moment_1.default)().add(keyType, "d").toDate();
}
user = await mdb.save(user);
vipKey.isUsed = 1;
......@@ -647,7 +671,7 @@ class DataManager {
user = new User_1.User();
user.key = userKey;
}
user.vipExpireDate = moment_1.default(oldVipUserInfo.expire_date).toDate();
user.vipExpireDate = (0, moment_1.default)(oldVipUserInfo.expire_date).toDate();
user.victory = oldVipUserInfo.victory || null;
user.words = oldVipUserInfo.words || null;
user = await mdb.save(user);
......
import moment from "moment";
import bunyan from "bunyan";
import {Connection, ConnectionOptions, createConnection, EntityManager} from "typeorm";
import {Connection, createConnection, EntityManager} from "typeorm";
import {CloudReplay} from "./entities/CloudReplay";
import {CloudReplayPlayer} from "./entities/CloudReplayPlayer";
import {Ban} from "./entities/Ban";
......@@ -16,6 +16,7 @@ import {RandomDuelScore} from "./entities/RandomDuelScore";
import JSZip from "jszip";
import * as fs from "fs";
import "reflect-metadata";
import { MysqlConnectionOptions } from "typeorm/driver/mysql/MysqlConnectionOptions";
interface BasePlayerInfo {
name: string;
......@@ -42,37 +43,34 @@ export interface DuelLogQuery {roomName: string, duelCount: number, playerName:
export class DataManager {
config: ConnectionOptions;
ready: boolean;
db: Connection;
log: bunyan;
constructor(config: ConnectionOptions, log: bunyan) {
this.config = config;
private db: Connection;
constructor(private config: MysqlConnectionOptions, private log: bunyan) {
this.ready = false;
this.log = log;
}
private async transaction(fun: (mdb: EntityManager) => Promise<boolean>) {
const runner = this.db.createQueryRunner();
await runner.connect();
await runner.startTransaction();
let result = false;
try {
result = await fun(runner.manager);
} catch(e) {
result = false;
this.log.warn(`Failed running transaction: ${e.toString()}`)
}
if(result) {
await runner.commitTransaction();
} else {
await runner.rollbackTransaction();
// @ts-ignore
if (this.config.type !== 'sqlite') {
this.db.transaction(async (mdb) => {
const result = await fun(mdb);
if (!result) {
throw new Error('Rollback requested.');
}
});
} else {
await fun(this.db.manager);
}
} catch (e) {
this.log.warn(`Transaction failed: ${e.toString()}`);
}
await runner.release();
}
async init() {
this.db = await createConnection({
type: "mysql",
synchronize: true,
supportBigNumbers: true,
bigNumberStrings: false,
entities: ["./data-manager/entities/*.js"],
...this.config
});
......@@ -80,8 +78,13 @@ export class DataManager {
}
async getCloudReplaysFromKey(key: string) {
try {
const replays = await this.db.createQueryBuilder(CloudReplay, "replay")
.where("exists (select id from cloud_replay_player where cloud_replay_player.cloudReplayId = replay.id and cloud_replay_player.key = :key)", { key })
const replaysQuery = this.db.createQueryBuilder(CloudReplay, "replay");
const sqb = replaysQuery.subQuery()
.select('splayer.id')
.from(CloudReplayPlayer, 'splayer')
.where('splayer.cloudReplayId = replay.id')
.andWhere('splayer.key = :key');
const replays = await replaysQuery.where(`exists ${sqb.getQuery()}`, { key })
.orderBy("replay.date", "DESC")
.limit(10)
.leftJoinAndSelect("replay.players", "player")
......@@ -282,19 +285,25 @@ export class DataManager {
if(duelCount != null && !isNaN(duelCount)) {
queryBuilder.andWhere("duelLog.duelCount = :duelCount", { duelCount });
}
if(playerName != null && playerName.length || playerScore != null && !isNaN(playerScore)) {
let innerQuery = "select id from duel_log_player where duel_log_player.duelLogId = duelLog.id";
if (playerName != null && playerName.length || playerScore != null && !isNaN(playerScore)) {
const sqb = queryBuilder.subQuery()
.select('splayer.id')
.from(DuelLogPlayer, 'splayer')
.where('splayer.duelLogId = duelLog.id');
//let innerQuery = "select id from duel_log_player where duel_log_player.duelLogId = duelLog.id";
const innerQueryParams: any = {};
if(playerName != null && playerName.length) {
//const escapedPlayerName = this.getEscapedString(playerName);
innerQuery += " and duel_log_player.realName = :playerName";
sqb.andWhere('splayer.realName = :playerName');
//innerQuery += " and duel_log_player.realName = :playerName";
innerQueryParams.playerName = playerName;
}
if(playerScore != null && !isNaN(playerScore)) {
innerQuery += " and duel_log_player.score = :playerScore";
//innerQuery += " and duel_log_player.score = :playerScore";
sqb.andWhere('splayer.score = :playerScore');
innerQueryParams.playerScore = playerScore;
}
queryBuilder.andWhere(`exists (${innerQuery})`, innerQueryParams);
queryBuilder.andWhere(`exists ${sqb.getQuery()}`, innerQueryParams);
}
queryBuilder.orderBy("duelLog.id", "DESC")
.leftJoinAndSelect("duelLog.players", "player");
......@@ -322,8 +331,16 @@ export class DataManager {
async getDuelLogFromRecoverSearch(realName: string) {
const repo = this.db.getRepository(DuelLog);
try {
const duelLogs = await repo.createQueryBuilder("duelLog")
.where("startDeckBuffer is not null and currentDeckBuffer is not null and roomMode != 2 and exists (select id from duel_log_player where duel_log_player.duelLogId = duelLog.id and duel_log_player.realName = :realName)", { realName })
const duelLogsQuery = repo.createQueryBuilder("duelLog")
.where('startDeckBuffer is not null')
.andWhere('currentDeckBuffer is not null')
.andWhere('roomMode != 2');
const sqb = duelLogsQuery.subQuery()
.select('splayer.id')
.from(DuelLogPlayer, 'splayer')
.andWhere('splayer.duelLogId = duelLog.id')
.andWhere('splayer.realName = :realName');
const duelLogs = await duelLogsQuery.andWhere(`exists ${sqb.getQuery()}`, { realName })
.orderBy("duelLog.id", "DESC")
.limit(10)
.leftJoinAndSelect("duelLog.players", "player")
......
......@@ -17,7 +17,7 @@ function encodeDeck(deck) {
buffer.writeInt32LE(cardCode, pointer);
pointer += 4;
}
assert_1.default(pointer === bufferSize, `Invalid buffer size. Expected: ${bufferSize}. Got: ${pointer}`);
(0, assert_1.default)(pointer === bufferSize, `Invalid buffer size. Expected: ${bufferSize}. Got: ${pointer}`);
return buffer;
}
exports.encodeDeck = encodeDeck;
......@@ -28,7 +28,7 @@ function decodeDeck(buffer) {
const sideLength = buffer.readInt32LE(pointer);
pointer += 4;
const correctBufferLength = (2 + mainLength + sideLength) * 4;
assert_1.default(buffer.length >= (2 + mainLength + sideLength) * 4, `Invalid buffer size. Expected: ${correctBufferLength}. Got: ${buffer.length}`);
(0, assert_1.default)(buffer.length >= (2 + mainLength + sideLength) * 4, `Invalid buffer size. Expected: ${correctBufferLength}. Got: ${buffer.length}`);
const main = [];
const side = [];
for (let i = 0; i < mainLength; ++i) {
......
......@@ -13,24 +13,27 @@ exports.Ban = void 0;
const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let Ban = class Ban extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
ip;
name;
};
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number)
], Ban.prototype, "id", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 64, nullable: true }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 64, nullable: true }),
__metadata("design:type", String)
], Ban.prototype, "ip", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 20, nullable: true }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 20, nullable: true }),
__metadata("design:type", String)
], Ban.prototype, "name", void 0);
Ban = __decorate([
typeorm_1.Entity(),
typeorm_1.Unique(["ip", "name"])
(0, typeorm_1.Entity)(),
(0, typeorm_1.Unique)(["ip", "name"])
], Ban);
exports.Ban = Ban;
//# sourceMappingURL=Ban.js.map
\ No newline at end of file
......@@ -4,7 +4,7 @@ import {CreateAndUpdateTimeBase} from "./CreateAndUpdateTimeBase";
@Entity()
@Unique(["ip", "name"])
export class Ban extends CreateAndUpdateTimeBase {
@PrimaryGeneratedColumn({ unsigned: true, type: "bigint" })
@PrimaryGeneratedColumn({ unsigned: true, type: (global as any).PrimaryKeyType as ('bigint' | 'integer') || 'bigint' })
id: number;
@Index()
......
......@@ -13,17 +13,20 @@ exports.BasePlayer = void 0;
const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
class BasePlayer extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
name;
pos;
}
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number)
], BasePlayer.prototype, "id", void 0);
__decorate([
typeorm_1.Column({ type: "varchar", length: 20 }),
(0, typeorm_1.Column)({ type: "varchar", length: 20 }),
__metadata("design:type", String)
], BasePlayer.prototype, "name", void 0);
__decorate([
typeorm_1.Column({ type: "tinyint" }),
(0, typeorm_1.Column)({ type: "tinyint" }),
__metadata("design:type", Number)
], BasePlayer.prototype, "pos", void 0);
exports.BasePlayer = BasePlayer;
......
import {Column, PrimaryGeneratedColumn} from "typeorm";
import {CreateAndUpdateTimeBase} from "./CreateAndUpdateTimeBase";
export abstract class BasePlayer extends CreateAndUpdateTimeBase {
@PrimaryGeneratedColumn({unsigned: true, type: "bigint"})
@PrimaryGeneratedColumn({unsigned: true, type: (global as any).PrimaryKeyType as ('bigint' | 'integer') || 'bigint'})
id: number;
@Column({ type: "varchar", length: 20 })
......@@ -10,4 +9,4 @@ export abstract class BasePlayer extends CreateAndUpdateTimeBase {
@Column({ type: "tinyint" })
pos: number;
}
\ No newline at end of file
}
......@@ -19,15 +19,19 @@ const underscore_1 = __importDefault(require("underscore"));
const moment_1 = __importDefault(require("moment"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
data;
fromBuffer(buffer) {
this.data = buffer.toString("base64");
}
toBuffer() {
return Buffer.from(this.data, "base64");
}
date;
getDateString() {
return moment_1.default(this.date).format('YYYY-MM-DD HH:mm:ss');
return (0, moment_1.default)(this.date).format('YYYY-MM-DD HH:mm:ss');
}
players;
getPlayerNamesString() {
const playerInfos = underscore_1.default.clone(this.players);
playerInfos.sort((p1, p2) => p1.pos - p2.pos);
......@@ -38,24 +42,24 @@ let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndU
}
};
__decorate([
typeorm_1.PrimaryColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number)
], CloudReplay.prototype, "id", void 0);
__decorate([
typeorm_1.Column({ type: "text" }),
(0, typeorm_1.Column)({ type: "text" }),
__metadata("design:type", String)
], CloudReplay.prototype, "data", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "datetime" }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "datetime" }),
__metadata("design:type", Date)
], CloudReplay.prototype, "date", void 0);
__decorate([
typeorm_1.OneToMany(() => CloudReplayPlayer_1.CloudReplayPlayer, player => player.cloudReplay),
(0, typeorm_1.OneToMany)(() => CloudReplayPlayer_1.CloudReplayPlayer, player => player.cloudReplay),
__metadata("design:type", Array)
], CloudReplay.prototype, "players", void 0);
CloudReplay = __decorate([
typeorm_1.Entity({
(0, typeorm_1.Entity)({
orderBy: {
date: "DESC"
}
......
......@@ -10,7 +10,7 @@ import {CreateAndUpdateTimeBase} from "./CreateAndUpdateTimeBase";
}
})
export class CloudReplay extends CreateAndUpdateTimeBase {
@PrimaryColumn({ unsigned: true, type: "bigint" })
@PrimaryColumn({ unsigned: true, type: (global as any).PrimaryKeyType as ('bigint' | 'integer') || 'bigint' })
id: number;
@Column({ type: "text" })
......
......@@ -15,6 +15,8 @@ const typeorm_1 = require("typeorm");
const CloudReplay_1 = require("./CloudReplay");
const BasePlayer_1 = require("./BasePlayer");
let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends BasePlayer_1.BasePlayer {
key;
cloudReplay;
static fromPlayerInfo(info) {
const p = new CloudReplayPlayer_1();
p.key = info.key;
......@@ -24,16 +26,16 @@ let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends Ba
}
};
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 128 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 128 }),
__metadata("design:type", String)
], CloudReplayPlayer.prototype, "key", void 0);
__decorate([
typeorm_1.ManyToOne(() => CloudReplay_1.CloudReplay, replay => replay.players),
(0, typeorm_1.ManyToOne)(() => CloudReplay_1.CloudReplay, replay => replay.players),
__metadata("design:type", CloudReplay_1.CloudReplay)
], CloudReplayPlayer.prototype, "cloudReplay", void 0);
CloudReplayPlayer = CloudReplayPlayer_1 = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], CloudReplayPlayer);
exports.CloudReplayPlayer = CloudReplayPlayer;
//# sourceMappingURL=CloudReplayPlayer.js.map
\ No newline at end of file
......@@ -12,13 +12,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateAndUpdateTimeBase = void 0;
const typeorm_1 = require("typeorm");
class CreateAndUpdateTimeBase {
createTime;
updateTime;
}
__decorate([
typeorm_1.CreateDateColumn(),
(0, typeorm_1.CreateDateColumn)(),
__metadata("design:type", Date)
], CreateAndUpdateTimeBase.prototype, "createTime", void 0);
__decorate([
typeorm_1.UpdateDateColumn(),
(0, typeorm_1.UpdateDateColumn)(),
__metadata("design:type", Date)
], CreateAndUpdateTimeBase.prototype, "updateTime", void 0);
exports.CreateAndUpdateTimeBase = CreateAndUpdateTimeBase;
......
......@@ -19,16 +19,25 @@ const moment_1 = __importDefault(require("moment"));
const underscore_1 = __importDefault(require("underscore"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
time;
name;
roomId;
cloudReplayId; // not very needed to become a relation
replayFileName;
roomMode;
duelCount;
players;
getViewString() {
const viewPlayers = underscore_1.default.clone(this.players);
viewPlayers.sort((p1, p2) => p1.pos - p2.pos);
const playerString = viewPlayers[0].realName.split("$")[0] + (viewPlayers[2] ? "+" + viewPlayers[2].realName.split("$")[0] : "") + " VS " + (viewPlayers[1] ? viewPlayers[1].realName.split("$")[0] : "AI") + (viewPlayers[3] ? "+" + viewPlayers[3].realName.split("$")[0] : "");
return `<${this.id}> ${playerString} ${moment_1.default(this.time).format("YYYY-MM-DD HH-mm-ss")}`;
return `<${this.id}> ${playerString} ${(0, moment_1.default)(this.time).format("YYYY-MM-DD HH-mm-ss")}`;
}
getViewJSON(tournamentModeSettings) {
const data = {
id: this.id,
time: moment_1.default(this.time).format("YYYY-MM-DD HH:mm:ss"),
time: (0, moment_1.default)(this.time).format("YYYY-MM-DD HH:mm:ss"),
name: this.name + (tournamentModeSettings.show_info ? " (Duel:" + this.duelCount + ")" : ""),
roomid: this.roomId,
cloud_replay_id: "R#" + this.cloudReplayId,
......@@ -47,46 +56,46 @@ let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTim
}
};
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number)
], DuelLog.prototype, "id", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("datetime"),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("datetime"),
__metadata("design:type", Date)
], DuelLog.prototype, "time", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 20 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 20 }),
__metadata("design:type", String)
], DuelLog.prototype, "name", void 0);
__decorate([
typeorm_1.Column("int"),
(0, typeorm_1.Column)("int"),
__metadata("design:type", Number)
], DuelLog.prototype, "roomId", void 0);
__decorate([
typeorm_1.Column("bigint"),
(0, typeorm_1.Column)(global.PrimaryKeyType || 'bigint'),
__metadata("design:type", Number)
], DuelLog.prototype, "cloudReplayId", void 0);
__decorate([
typeorm_1.Column({ type: "varchar", length: 256 }),
(0, typeorm_1.Column)({ type: "varchar", length: 256 }),
__metadata("design:type", String)
], DuelLog.prototype, "replayFileName", void 0);
__decorate([
typeorm_1.Column("tinyint", { unsigned: true }),
(0, typeorm_1.Column)("tinyint", { unsigned: true }),
__metadata("design:type", Number)
], DuelLog.prototype, "roomMode", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("tinyint", { unsigned: true }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("tinyint", { unsigned: true }),
__metadata("design:type", Number)
], DuelLog.prototype, "duelCount", void 0);
__decorate([
typeorm_1.OneToMany(() => DuelLogPlayer_1.DuelLogPlayer, player => player.duelLog),
(0, typeorm_1.OneToMany)(() => DuelLogPlayer_1.DuelLogPlayer, player => player.duelLog),
__metadata("design:type", Array)
], DuelLog.prototype, "players", void 0);
DuelLog = __decorate([
typeorm_1.Entity({
(0, typeorm_1.Entity)({
orderBy: {
id: "DESC"
}
......
......@@ -10,7 +10,7 @@ import {CreateAndUpdateTimeBase} from "./CreateAndUpdateTimeBase";
}
})
export class DuelLog extends CreateAndUpdateTimeBase {
@PrimaryGeneratedColumn({unsigned: true, type: "bigint"})
@PrimaryGeneratedColumn({unsigned: true, type: (global as any).PrimaryKeyType as ('bigint' | 'integer') || 'bigint'})
id: number;
@Index()
......@@ -24,7 +24,7 @@ export class DuelLog extends CreateAndUpdateTimeBase {
@Column("int")
roomId: number;
@Column("bigint")
@Column((global as any).PrimaryKeyType as ('bigint' | 'integer') || 'bigint')
cloudReplayId: number; // not very needed to become a relation
@Column({type: "varchar", length: 256})
......@@ -67,4 +67,4 @@ export class DuelLog extends CreateAndUpdateTimeBase {
}
return data;
}
}
\ No newline at end of file
}
......@@ -16,26 +16,36 @@ const BasePlayer_1 = require("./BasePlayer");
const DuelLog_1 = require("./DuelLog");
const DeckEncoder_1 = require("../DeckEncoder");
let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.BasePlayer {
realName;
ip;
isFirst;
score;
lp;
cardCount;
startDeckBuffer;
currentDeckBuffer;
winner;
setStartDeck(deck) {
if (deck === null) {
this.startDeckBuffer = null;
return;
}
this.startDeckBuffer = DeckEncoder_1.encodeDeck(deck).toString("base64");
this.startDeckBuffer = (0, DeckEncoder_1.encodeDeck)(deck).toString("base64");
}
getStartDeck() {
return DeckEncoder_1.decodeDeck(Buffer.from(this.startDeckBuffer, "base64"));
return (0, DeckEncoder_1.decodeDeck)(Buffer.from(this.startDeckBuffer, "base64"));
}
setCurrentDeck(deck) {
if (deck === null) {
this.currentDeckBuffer = null;
return;
}
this.currentDeckBuffer = DeckEncoder_1.encodeDeck(deck).toString("base64");
this.currentDeckBuffer = (0, DeckEncoder_1.encodeDeck)(deck).toString("base64");
}
getCurrentDeck() {
return DeckEncoder_1.decodeDeck(Buffer.from(this.currentDeckBuffer, "base64"));
return (0, DeckEncoder_1.decodeDeck)(Buffer.from(this.currentDeckBuffer, "base64"));
}
duelLog;
static fromDuelLogPlayerInfo(info) {
const p = new DuelLogPlayer_1();
p.name = info.name;
......@@ -47,55 +57,55 @@ let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.B
p.cardCount = info.cardCount;
p.isFirst = info.isFirst ? 1 : 0;
p.winner = info.winner ? 1 : 0;
p.startDeckBuffer = info.startDeckBuffer.toString("base64");
p.startDeckBuffer = info.startDeckBuffer?.toString("base64") || null;
p.setCurrentDeck(info.deck);
return p;
}
};
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 20 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 20 }),
__metadata("design:type", String)
], DuelLogPlayer.prototype, "realName", void 0);
__decorate([
typeorm_1.Column({ type: "varchar", length: 64, nullable: true }),
(0, typeorm_1.Column)({ type: "varchar", length: 64, nullable: true }),
__metadata("design:type", String)
], DuelLogPlayer.prototype, "ip", void 0);
__decorate([
typeorm_1.Column("tinyint", { unsigned: true }),
(0, typeorm_1.Column)("tinyint", { unsigned: true }),
__metadata("design:type", Number)
], DuelLogPlayer.prototype, "isFirst", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("tinyint"),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("tinyint"),
__metadata("design:type", Number)
], DuelLogPlayer.prototype, "score", void 0);
__decorate([
typeorm_1.Column("int", { nullable: true }),
(0, typeorm_1.Column)("int", { nullable: true }),
__metadata("design:type", Number)
], DuelLogPlayer.prototype, "lp", void 0);
__decorate([
typeorm_1.Column("smallint", { nullable: true }),
(0, typeorm_1.Column)("smallint", { nullable: true }),
__metadata("design:type", Number)
], DuelLogPlayer.prototype, "cardCount", void 0);
__decorate([
typeorm_1.Column("text", { nullable: true }),
(0, typeorm_1.Column)("text", { nullable: true }),
__metadata("design:type", String)
], DuelLogPlayer.prototype, "startDeckBuffer", void 0);
__decorate([
typeorm_1.Column("text", { nullable: true }),
(0, typeorm_1.Column)("text", { nullable: true }),
__metadata("design:type", String)
], DuelLogPlayer.prototype, "currentDeckBuffer", void 0);
__decorate([
typeorm_1.Column("tinyint"),
(0, typeorm_1.Column)("tinyint"),
__metadata("design:type", Number)
], DuelLogPlayer.prototype, "winner", void 0);
__decorate([
typeorm_1.ManyToOne(() => DuelLog_1.DuelLog, duelLog => duelLog.players),
(0, typeorm_1.ManyToOne)(() => DuelLog_1.DuelLog, duelLog => duelLog.players),
__metadata("design:type", DuelLog_1.DuelLog)
], DuelLogPlayer.prototype, "duelLog", void 0);
DuelLogPlayer = DuelLogPlayer_1 = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], DuelLogPlayer);
exports.DuelLogPlayer = DuelLogPlayer;
//# sourceMappingURL=DuelLogPlayer.js.map
\ No newline at end of file
......@@ -73,7 +73,7 @@ export class DuelLogPlayer extends BasePlayer {
p.cardCount = info.cardCount;
p.isFirst = info.isFirst ? 1 : 0;
p.winner = info.winner ? 1 : 0;
p.startDeckBuffer = info.startDeckBuffer.toString("base64");
p.startDeckBuffer = info.startDeckBuffer?.toString("base64") || null;
p.setCurrentDeck(info.deck);
return p;
}
......
......@@ -13,6 +13,11 @@ exports.RandomDuelBan = void 0;
const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
ip;
time;
count;
reasons;
needTip;
setNeedTip(need) {
this.needTip = need ? 1 : 0;
}
......@@ -21,27 +26,27 @@ let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.Create
}
};
__decorate([
typeorm_1.PrimaryColumn({ type: "varchar", length: 64 }),
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 64 }),
__metadata("design:type", String)
], RandomDuelBan.prototype, "ip", void 0);
__decorate([
typeorm_1.Column("datetime"),
(0, typeorm_1.Column)("datetime"),
__metadata("design:type", Date)
], RandomDuelBan.prototype, "time", void 0);
__decorate([
typeorm_1.Column("smallint"),
(0, typeorm_1.Column)("smallint"),
__metadata("design:type", Number)
], RandomDuelBan.prototype, "count", void 0);
__decorate([
typeorm_1.Column({ type: "simple-array" }),
(0, typeorm_1.Column)({ type: "simple-array" }),
__metadata("design:type", Array)
], RandomDuelBan.prototype, "reasons", void 0);
__decorate([
typeorm_1.Column({ type: "tinyint", unsigned: true }),
(0, typeorm_1.Column)({ type: "tinyint", unsigned: true }),
__metadata("design:type", Number)
], RandomDuelBan.prototype, "needTip", void 0);
RandomDuelBan = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], RandomDuelBan);
exports.RandomDuelBan = RandomDuelBan;
//# sourceMappingURL=RandomDuelBan.js.map
\ No newline at end of file
......@@ -13,6 +13,11 @@ exports.RandomDuelScore = void 0;
const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
name;
winCount;
loseCount;
fleeCount;
winCombo;
getDisplayName() {
return this.name.split("$")[0];
}
......@@ -44,30 +49,30 @@ let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.Cr
}
};
__decorate([
typeorm_1.PrimaryColumn({ type: "varchar", length: 20 }),
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 20 }),
__metadata("design:type", String)
], RandomDuelScore.prototype, "name", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "winCount", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "loseCount", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "fleeCount", void 0);
__decorate([
typeorm_1.Column("int", { unsigned: true, default: 0 }),
(0, typeorm_1.Column)("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "winCombo", void 0);
RandomDuelScore = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], RandomDuelScore);
exports.RandomDuelScore = RandomDuelScore;
//# sourceMappingURL=RandomDuelScore.js.map
\ No newline at end of file
......@@ -19,41 +19,48 @@ const VipKey_1 = require("./VipKey");
const moment_1 = __importDefault(require("moment"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let User = class User extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
key;
chatColor;
vipExpireDate;
isVip() {
return this.vipExpireDate && moment_1.default().isBefore(this.vipExpireDate);
return this.vipExpireDate && (0, moment_1.default)().isBefore(this.vipExpireDate);
}
victory;
words;
dialogues;
usedKeys;
};
__decorate([
typeorm_1.PrimaryColumn({ type: "varchar", length: 128 }),
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 128 }),
__metadata("design:type", String)
], User.prototype, "key", void 0);
__decorate([
typeorm_1.Column("varchar", { length: 16, nullable: true }),
(0, typeorm_1.Column)("varchar", { length: 16, nullable: true }),
__metadata("design:type", String)
], User.prototype, "chatColor", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("datetime", { nullable: true }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("datetime", { nullable: true }),
__metadata("design:type", Date)
], User.prototype, "vipExpireDate", void 0);
__decorate([
typeorm_1.Column("text", { nullable: true }),
(0, typeorm_1.Column)("text", { nullable: true }),
__metadata("design:type", String)
], User.prototype, "victory", void 0);
__decorate([
typeorm_1.Column("text", { nullable: true }),
(0, typeorm_1.Column)("text", { nullable: true }),
__metadata("design:type", String)
], User.prototype, "words", void 0);
__decorate([
typeorm_1.OneToMany(() => UserDialog_1.UserDialog, dialog => dialog.user),
(0, typeorm_1.OneToMany)(() => UserDialog_1.UserDialog, dialog => dialog.user),
__metadata("design:type", Array)
], User.prototype, "dialogues", void 0);
__decorate([
typeorm_1.OneToMany(() => VipKey_1.VipKey, vipKey => vipKey.usedBy),
(0, typeorm_1.OneToMany)(() => VipKey_1.VipKey, vipKey => vipKey.usedBy),
__metadata("design:type", Array)
], User.prototype, "usedKeys", void 0);
User = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], User);
exports.User = User;
//# sourceMappingURL=User.js.map
\ No newline at end of file
......@@ -13,26 +13,30 @@ exports.UserDialog = void 0;
const typeorm_1 = require("typeorm");
const User_1 = require("./User");
let UserDialog = class UserDialog {
id;
cardCode;
text;
user;
};
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }),
__metadata("design:type", Number)
], UserDialog.prototype, "id", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("int", { unsigned: true }),
__metadata("design:type", Number)
], UserDialog.prototype, "cardCode", void 0);
__decorate([
typeorm_1.Column("text"),
(0, typeorm_1.Column)("text"),
__metadata("design:type", String)
], UserDialog.prototype, "text", void 0);
__decorate([
typeorm_1.ManyToOne(() => User_1.User, user => user.dialogues),
(0, typeorm_1.ManyToOne)(() => User_1.User, user => user.dialogues),
__metadata("design:type", User_1.User)
], UserDialog.prototype, "user", void 0);
UserDialog = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], UserDialog);
exports.UserDialog = UserDialog;
//# sourceMappingURL=UserDialog.js.map
\ No newline at end of file
......@@ -14,34 +14,39 @@ const typeorm_1 = require("typeorm");
const User_1 = require("./User");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let VipKey = class VipKey extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
key;
type;
isUsed;
usedBy;
toJSON() {
return { key: this.key, type: this.type };
}
};
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }),
__metadata("design:type", Number)
], VipKey.prototype, "id", void 0);
__decorate([
typeorm_1.Index({ unique: true }),
typeorm_1.Column("varchar", { length: 30 }),
(0, typeorm_1.Index)({ unique: true }),
(0, typeorm_1.Column)("varchar", { length: 30 }),
__metadata("design:type", String)
], VipKey.prototype, "key", void 0);
__decorate([
typeorm_1.Column("int", { unsigned: true }),
(0, typeorm_1.Column)("int", { unsigned: true }),
__metadata("design:type", Number)
], VipKey.prototype, "type", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("tinyint", { unsigned: true, default: 0 }),
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)("tinyint", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], VipKey.prototype, "isUsed", void 0);
__decorate([
typeorm_1.ManyToOne(() => User_1.User, user => user.usedKeys),
(0, typeorm_1.ManyToOne)(() => User_1.User, user => user.usedKeys),
__metadata("design:type", User_1.User)
], VipKey.prototype, "usedBy", void 0);
VipKey = __decorate([
typeorm_1.Entity()
(0, typeorm_1.Entity)()
], VipKey);
exports.VipKey = VipKey;
//# sourceMappingURL=VipKey.js.map
\ No newline at end of file
......@@ -7,7 +7,7 @@
"lflist": 0,
"rule": 0,
"mode": 0,
"comment": "rule: 0=OCGONLY, 1=TCGONLY, 2=OT; mode: 0=SINGLE, 1=MATCH, 2=TAG",
"comment": "rule: 0=OCG-ONLY, 1=TCG-ONLY, 2=SC-ONLY, 3=CUSTOM-ONLY, 4=NO-UNIQUE, 5=ALL; mode: 0=SINGLE, 1=MATCH, 2=TAG",
"duel_rule": 5,
"no_check_deck": false,
"no_shuffle_deck": false,
......@@ -66,12 +66,14 @@
"tips": {
"enabled": true,
"split_zh": false,
"get": "https://api.moecube.com/biu-tips/tips.json",
"get_zh": false
"get": "https://sapi.moecube.com:444/biu-tips/tips.json",
"get_zh": false,
"interval": 30000,
"interval_ingame": 120000
},
"dialogues": {
"enabled": true,
"get_custom": "http://purerosefallen.github.io/ygopro-tips/dialogues-222.json",
"get_custom": "https://minio.momobako.com:9000/public/ygopro-tips/dialogues-222.json",
"get": "http://mercury233.me/ygosrv233/dialogues.json"
},
"words": {
......@@ -160,6 +162,7 @@
"post_detailed_score": true,
"post_score_midduel": true,
"cache_ttl": 60000,
"no_match_mode": false,
"options": {
"apiKey": "123"
},
......@@ -217,6 +220,7 @@
"source": "mycard-athletic"
},
"rankCount": 10,
"banCount": 0,
"ttl": 600
},
"test_mode": {
......
......@@ -85,6 +85,7 @@
"kick_count_down_arena_part2": " will be evicted for not getting ready or starting the game.",
"chat_order_main": "Mycard YGOPro Server function list",
"chat_order_help": "/help show this list",
"chat_order_refresh": "/refresh refresh field when stuck",
"chat_order_roomname": "/roomname show room name",
"chat_order_windbot": "/ai to add an AI, /ai name to add selected AI ",
"chat_order_tip": "/tip show a tip",
......@@ -203,6 +204,10 @@
"auto_death_part2": " minutes.",
"athletic_arena_tip": "During an athletic match, a game quit behavior is regarded as a surrender.",
"windbot_disable_random_room": "By adding the AI, this random game won't get any new player unless they enter the room name:",
"refresh_success": "Refresh field succeeded.",
"refresh_failed": "Refresh field failed.",
"banned_athletic_deck_part1": "Entertainment Mode does not allow top ",
"banned_athletic_deck_part2": " popular meta decks. Please change your deck.",
"using_athletic_deck": " is using a competitive deck."
},
"es-es": {
......@@ -437,6 +442,7 @@
"kick_count_down_arena_part2": "若不准备或开始游戏将视为投降",
"chat_order_main": "Mycard YGOPro Server 指令帮助",
"chat_order_help": "/help 显示这个帮助信息",
"chat_order_refresh": "/refresh 刷新场面信息,卡顿时用",
"chat_order_roomname": "/roomname 显示当前房间的名字",
"chat_order_windbot": "/ai 添加一个AI,/ai 角色名 可指定添加的角色",
"chat_order_tip": "/tip 显示一条提示",
......@@ -555,6 +561,10 @@
"auto_death_part2": "分钟后,将自动进入加时赛。",
"athletic_arena_tip": "在竞技匹配中,比赛开始前退出游戏也会视为投降。",
"windbot_disable_random_room": "因为添加了AI,本随机对战房间将只能通过房间名加入:",
"refresh_success": "刷新场面成功。",
"refresh_fail": "刷新场面失败。",
"banned_athletic_deck_part1": "娱乐匹配中禁止使用使用数前",
"banned_athletic_deck_part2": "的竞技卡组。请更换卡组。",
"using_athletic_deck": " 正在使用竞技卡组。"
},
"ko-kr": {
......
......@@ -2,8 +2,9 @@
"apps": [
{
"name": "ygopro-server",
"script": "/ygopro-server/ygopro-server.js",
"cwd": "/ygopro-server"
"script": "npm",
"cwd": "/ygopro-server",
"args": "start"
},
{
"name": "windbot",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -11,19 +11,15 @@
],
"author": "zh99998 <zh99998@gmail.com>, mercury233 <me@mercury233.me>, Nanahira <78877@qq.com>",
"dependencies": {
"@types/bunyan": "^1.8.6",
"@types/node": "^14.0.13",
"@types/underscore": "^1.10.24",
"async": "^3.2.0",
"axios": "^0.19.2",
"bunyan": "^1.8.14",
"challonge": "latest",
"coffeescript": "^2.5.1",
"deepmerge": "latest",
"formidable": "latest",
"geoip-country-lite": "latest",
"challonge": "^2.2.0",
"deepmerge": "^4.2.2",
"formidable": "^2.0.1",
"geoip-country-lite": "^1.0.0",
"jszip": "^3.5.0",
"load-json-file": "latest",
"load-json-file": "^6.2.0",
"lzma": "^2.3.2",
"moment": "^2.29.1",
"mysql": "^2.18.1",
......@@ -32,21 +28,27 @@
"q": "^1.5.1",
"querystring": "^0.2.0",
"reflect-metadata": "^0.1.13",
"request": "latest",
"sqlite3": "latest",
"request": "^2.88.2",
"sqlite3": "^5.0.2",
"typeorm": "^0.2.29",
"typescript": "^4.0.5",
"underscore": "^1.11.0",
"underscore.string": "latest",
"underscore.string": "^3.3.6",
"ws": "^1.1.1"
},
"license": "AGPL-3.0",
"scripts": {
"build": "coffee -c *.coffee && tsc",
"start": "node ygopro-server.js",
"start": "node ygopro-server.js | bunyan",
"tournament": "node ygopro-tournament.js",
"pre": "node ygopro-pre.js",
"updated": "node ygopro-update.js",
"webhook": "node ygopro-webhook.js"
},
"devDependencies": {
"@types/bunyan": "^1.8.8",
"@types/node": "^17.0.19",
"@types/underscore": "^1.11.4",
"coffeescript": "^2.6.1",
"typescript": "^4.5.5"
}
}
This diff is collapsed.
This diff is collapsed.
......@@ -113,4 +113,4 @@ translateHandler = (handler) ->
if client
client.system_kicked = true
client.destroy()
return
return '_cancel'
......@@ -185,6 +185,7 @@
client.system_kicked = true;
client.destroy();
}
return '_cancel';
};
}).call(this);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment