mirror of
				https://github.com/SikongJueluo/cc-utils.git
				synced 2025-11-04 19:27:50 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			1fe3052e5d
			...
			9d9dcade7b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9d9dcade7b | ||
| 
						 | 
					6304518f0e | 
@@ -22,9 +22,13 @@ interface CLIResult {
 | 
			
		||||
interface CLIContext {
 | 
			
		||||
  config: AccessConfig;
 | 
			
		||||
  configFilepath: string;
 | 
			
		||||
  reloadConfig: () => void;
 | 
			
		||||
  log: CCLog;
 | 
			
		||||
  chatBox: any; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
			
		||||
  groupNames: string[];
 | 
			
		||||
  chatBox: ChatBoxPeripheral;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getGroupNames(context: CLIContext) {
 | 
			
		||||
  return context.config.usersGroups.flatMap((value) => value.groupName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 基础命令处理器
 | 
			
		||||
@@ -43,8 +47,6 @@ class CLICommandProcessor {
 | 
			
		||||
    this.registerCommand(new DelCommand());
 | 
			
		||||
    this.registerCommand(new ListCommand());
 | 
			
		||||
    this.registerCommand(new SetCommand());
 | 
			
		||||
    this.registerCommand(new CreateGroupCommand());
 | 
			
		||||
    this.registerCommand(new RemoveGroupCommand());
 | 
			
		||||
    this.registerCommand(new EditCommand());
 | 
			
		||||
    this.registerCommand(new ShowConfigCommand());
 | 
			
		||||
    this.registerCommand(new HelpCommand());
 | 
			
		||||
@@ -73,7 +75,12 @@ class CLICommandProcessor {
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return command.execute(args, executor, this.context);
 | 
			
		||||
    const ret = command.execute(args, executor, this.context);
 | 
			
		||||
    if (ret.success) {
 | 
			
		||||
      this.context.reloadConfig();
 | 
			
		||||
      return ret;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getHelpCommand(): CLICommand {
 | 
			
		||||
@@ -82,7 +89,6 @@ class CLICommandProcessor {
 | 
			
		||||
 | 
			
		||||
  public sendResponse(result: CLIResult, executor: string) {
 | 
			
		||||
    if (result.message != null && result.message.length > 0) {
 | 
			
		||||
      // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
 | 
			
		||||
      this.context.chatBox.sendMessageToPlayer(
 | 
			
		||||
        result.message,
 | 
			
		||||
        executor,
 | 
			
		||||
@@ -125,10 +131,12 @@ class AddCommand implements CLICommand {
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!context.groupNames.includes(groupName)) {
 | 
			
		||||
    const groupNames = getGroupNames(context);
 | 
			
		||||
 | 
			
		||||
    if (!groupNames.includes(groupName)) {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Invalid group: ${groupName}. Available groups: ${context.groupNames.join(", ")}`,
 | 
			
		||||
        message: `Invalid group: ${groupName}. Available groups: ${groupNames.join(", ")}`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -180,10 +188,12 @@ class DelCommand implements CLICommand {
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!context.groupNames.includes(groupName)) {
 | 
			
		||||
    const groupNames = getGroupNames(context);
 | 
			
		||||
 | 
			
		||||
    if (!groupNames.includes(groupName)) {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Invalid group: ${groupName}. Available groups: ${context.groupNames.join(", ")}`,
 | 
			
		||||
        message: `Invalid group: ${groupName}. Available groups: ${groupNames.join(", ")}`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -300,24 +310,21 @@ class HelpCommand implements CLICommand {
 | 
			
		||||
  usage = "help";
 | 
			
		||||
 | 
			
		||||
  execute(_args: string[], _executor: string, context: CLIContext): CLIResult {
 | 
			
		||||
    const groupNames = getGroupNames(context);
 | 
			
		||||
    const helpMessage = `
 | 
			
		||||
Command Usage: @AC /<Command> [args]
 | 
			
		||||
Commands:
 | 
			
		||||
  - add <userGroup> <playerName>
 | 
			
		||||
      add player to group
 | 
			
		||||
      userGroup: ${context.groupNames.join(", ")}
 | 
			
		||||
      userGroup: ${groupNames.join(", ")}
 | 
			
		||||
  - del <userGroup> <playerName>
 | 
			
		||||
      delete player in the group, except Admin
 | 
			
		||||
      userGroup: ${context.groupNames.join(", ")}
 | 
			
		||||
      userGroup: ${groupNames.join(", ")}
 | 
			
		||||
  - list
 | 
			
		||||
      list all of the player with its group
 | 
			
		||||
  - set <options> [params]
 | 
			
		||||
      config access control settings
 | 
			
		||||
      options: warnInterval, detectInterval, detectRange
 | 
			
		||||
  - creategroup <groupName> <isAllowed> <isNotice>
 | 
			
		||||
      create new user group
 | 
			
		||||
  - removegroup <groupName>
 | 
			
		||||
      remove user group (except admin groups)
 | 
			
		||||
  - edit <target> [args]
 | 
			
		||||
      edit various configurations
 | 
			
		||||
      targets: group (edit group properties)
 | 
			
		||||
@@ -335,99 +342,6 @@ Commands:
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 创建用户组命令
 | 
			
		||||
class CreateGroupCommand implements CLICommand {
 | 
			
		||||
  name = "creategroup";
 | 
			
		||||
  description = "Create new user group";
 | 
			
		||||
  usage = "creategroup <groupName> <isAllowed> <isNotice>";
 | 
			
		||||
 | 
			
		||||
  execute(args: string[], _executor: string, context: CLIContext): CLIResult {
 | 
			
		||||
    if (args.length !== 3) {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Usage: ${this.usage}\nExample: creategroup VIP2 true false`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const [groupName, isAllowedStr, isNoticeStr] = args;
 | 
			
		||||
 | 
			
		||||
    // 检查组名是否已存在
 | 
			
		||||
    if (context.groupNames.includes(groupName) || groupName === "admin") {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Group ${groupName} already exists`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const isAllowed = isAllowedStr.toLowerCase() === "true";
 | 
			
		||||
    const isNotice = isNoticeStr.toLowerCase() === "true";
 | 
			
		||||
 | 
			
		||||
    const newGroup: UserGroupConfig = {
 | 
			
		||||
      groupName,
 | 
			
		||||
      isAllowed,
 | 
			
		||||
      isNotice,
 | 
			
		||||
      groupUsers: [],
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    context.config.usersGroups.push(newGroup);
 | 
			
		||||
    context.groupNames.push(groupName);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      success: true,
 | 
			
		||||
      message: `Created group ${groupName} (allowed: ${isAllowed}, notice: ${isNotice})`,
 | 
			
		||||
      shouldSaveConfig: true,
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除用户组命令
 | 
			
		||||
class RemoveGroupCommand implements CLICommand {
 | 
			
		||||
  name = "removegroup";
 | 
			
		||||
  description = "Remove user group";
 | 
			
		||||
  usage = "removegroup <groupName>";
 | 
			
		||||
 | 
			
		||||
  execute(args: string[], _executor: string, context: CLIContext): CLIResult {
 | 
			
		||||
    if (args.length !== 1) {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Usage: ${this.usage}`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const [groupName] = args;
 | 
			
		||||
 | 
			
		||||
    if (groupName === "admin") {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: "Cannot remove admin group",
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const groupIndex = context.config.usersGroups.findIndex(
 | 
			
		||||
      (group) => group.groupName === groupName,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (groupIndex === -1) {
 | 
			
		||||
      return {
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: `Group ${groupName} not found`,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    context.config.usersGroups.splice(groupIndex, 1);
 | 
			
		||||
    const nameIndex = context.groupNames.indexOf(groupName);
 | 
			
		||||
    if (nameIndex > -1) {
 | 
			
		||||
      context.groupNames.splice(nameIndex, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      success: true,
 | 
			
		||||
      message: `Removed group ${groupName}`,
 | 
			
		||||
      shouldSaveConfig: true,
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 统一编辑命令
 | 
			
		||||
class EditCommand implements CLICommand {
 | 
			
		||||
  name = "edit";
 | 
			
		||||
@@ -639,20 +553,6 @@ export class AccessControlCLI {
 | 
			
		||||
// 导出类型和工厂函数
 | 
			
		||||
export { CLIContext, CLIResult, CLICommand };
 | 
			
		||||
 | 
			
		||||
export function createAccessControlCLI(
 | 
			
		||||
  config: AccessConfig,
 | 
			
		||||
  configFilepath: string,
 | 
			
		||||
  log: CCLog,
 | 
			
		||||
  chatBox: any, // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
			
		||||
  groupNames: string[],
 | 
			
		||||
): AccessControlCLI {
 | 
			
		||||
  const context: CLIContext = {
 | 
			
		||||
    config,
 | 
			
		||||
    configFilepath,
 | 
			
		||||
    log,
 | 
			
		||||
    chatBox, // eslint-disable-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
    groupNames,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
export function createAccessControlCLI(context: CLIContext): AccessControlCLI {
 | 
			
		||||
  return new AccessControlCLI(context);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,24 @@
 | 
			
		||||
import { CCLog, DAY } from "@/lib/ccLog";
 | 
			
		||||
import { CCLog, DAY, LogLevel } from "@/lib/ccLog";
 | 
			
		||||
import { ToastConfig, UserGroupConfig, loadConfig } from "./config";
 | 
			
		||||
import { createAccessControlCLI } from "./cli";
 | 
			
		||||
import { launchAccessControlTUI } from "./tui";
 | 
			
		||||
import * as peripheralManager from "../lib/PeripheralManager";
 | 
			
		||||
import { deepCopy } from "@/lib/common";
 | 
			
		||||
 | 
			
		||||
const DEBUG = false;
 | 
			
		||||
const args = [...$vararg];
 | 
			
		||||
 | 
			
		||||
// Init Log
 | 
			
		||||
const logger = new CCLog("accesscontrol.log", true, DAY);
 | 
			
		||||
const logger = new CCLog("accesscontrol.log", {
 | 
			
		||||
  printTerminal: true,
 | 
			
		||||
  logInterval: DAY,
 | 
			
		||||
  outputMinLevel: LogLevel.Info,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Load Config
 | 
			
		||||
const configFilepath = `${shell.dir()}/access.config.json`;
 | 
			
		||||
let config = loadConfig(configFilepath);
 | 
			
		||||
logger.info("Load config successfully!");
 | 
			
		||||
if (DEBUG)
 | 
			
		||||
  logger.debug(textutils.serialise(config, { allow_repetitions: true }));
 | 
			
		||||
const groupNames = config.usersGroups.map((value) => value.groupName);
 | 
			
		||||
logger.debug(textutils.serialise(config, { allow_repetitions: true }));
 | 
			
		||||
 | 
			
		||||
// Peripheral
 | 
			
		||||
const playerDetector = peripheralManager.findByNameRequired("playerDetector");
 | 
			
		||||
@@ -34,6 +35,13 @@ interface ParseParams {
 | 
			
		||||
  info?: PlayerInfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function reloadConfig() {
 | 
			
		||||
  config = loadConfig(configFilepath);
 | 
			
		||||
  inRangePlayers = [];
 | 
			
		||||
  watchPlayersInfo = [];
 | 
			
		||||
  logger.info("Reload config successfully!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function safeParseTextComponent(
 | 
			
		||||
  component: MinecraftTextComponent,
 | 
			
		||||
  params?: ParseParams,
 | 
			
		||||
@@ -126,10 +134,8 @@ function sendWarn(player: string) {
 | 
			
		||||
 | 
			
		||||
function watchLoop() {
 | 
			
		||||
  while (true) {
 | 
			
		||||
    if (DEBUG) {
 | 
			
		||||
      const watchPlayerNames = watchPlayersInfo.flatMap((value) => value.name);
 | 
			
		||||
      logger.debug(`Watch Players [ ${watchPlayerNames.join(", ")} ]`);
 | 
			
		||||
    }
 | 
			
		||||
    const watchPlayerNames = watchPlayersInfo.flatMap((value) => value.name);
 | 
			
		||||
    logger.debug(`Watch Players [ ${watchPlayerNames.join(", ")} ]`);
 | 
			
		||||
    for (const player of watchPlayersInfo) {
 | 
			
		||||
      const playerInfo = playerDetector.getPlayerPos(player.name);
 | 
			
		||||
      if (inRangePlayers.includes(player.name)) {
 | 
			
		||||
@@ -144,7 +150,7 @@ function watchLoop() {
 | 
			
		||||
 | 
			
		||||
        // Record
 | 
			
		||||
        logger.warn(
 | 
			
		||||
          `${player.name} appear at ${playerInfo?.x}, ${playerInfo?.y}, ${playerInfo?.z}`,
 | 
			
		||||
          `Stranger ${player.name} appear at ${playerInfo?.x}, ${playerInfo?.y}, ${playerInfo?.z}`,
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        // Get rid of player from list
 | 
			
		||||
@@ -152,10 +158,10 @@ function watchLoop() {
 | 
			
		||||
          (value) => value.name != player.name,
 | 
			
		||||
        );
 | 
			
		||||
        logger.info(
 | 
			
		||||
          `${player.name} has left the range at ${playerInfo?.x}, ${playerInfo?.y}, ${playerInfo?.z}`,
 | 
			
		||||
          `Stranger ${player.name} has left the range at ${playerInfo?.x}, ${playerInfo?.y}, ${playerInfo?.z}`,
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      os.sleep(3);
 | 
			
		||||
      os.sleep(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    os.sleep(config.watchInterval);
 | 
			
		||||
@@ -165,10 +171,8 @@ function watchLoop() {
 | 
			
		||||
function mainLoop() {
 | 
			
		||||
  while (true) {
 | 
			
		||||
    const players = playerDetector.getPlayersInRange(config.detectRange);
 | 
			
		||||
    if (DEBUG) {
 | 
			
		||||
      const playersList = "[ " + players.join(",") + " ]";
 | 
			
		||||
      logger.debug(`Detected ${players.length} players: ${playersList}`);
 | 
			
		||||
    }
 | 
			
		||||
    const playersList = "[ " + players.join(",") + " ]";
 | 
			
		||||
    logger.debug(`Detected ${players.length} players: ${playersList}`);
 | 
			
		||||
 | 
			
		||||
    for (const player of players) {
 | 
			
		||||
      if (inRangePlayers.includes(player)) continue;
 | 
			
		||||
@@ -227,7 +231,7 @@ function keyboardLoop() {
 | 
			
		||||
        logger.error(`TUI error: ${textutils.serialise(error as object)}`);
 | 
			
		||||
      } finally {
 | 
			
		||||
        logger.setInTerminal(true);
 | 
			
		||||
        config = loadConfig(configFilepath);
 | 
			
		||||
        reloadConfig();
 | 
			
		||||
        logger.info("Reload config successfully!");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -239,13 +243,13 @@ function main(args: string[]) {
 | 
			
		||||
  if (args.length == 1) {
 | 
			
		||||
    if (args[0] == "start") {
 | 
			
		||||
      // 创建CLI处理器
 | 
			
		||||
      const cli = createAccessControlCLI(
 | 
			
		||||
        config,
 | 
			
		||||
        configFilepath,
 | 
			
		||||
        logger,
 | 
			
		||||
        chatBox,
 | 
			
		||||
        groupNames,
 | 
			
		||||
      );
 | 
			
		||||
      const cli = createAccessControlCLI({
 | 
			
		||||
        config: config,
 | 
			
		||||
        configFilepath: configFilepath,
 | 
			
		||||
        reloadConfig: () => reloadConfig(),
 | 
			
		||||
        log: logger,
 | 
			
		||||
        chatBox: chatBox,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      print(
 | 
			
		||||
        "Access Control System started. Press 'c' to open configuration TUI.",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
enum LogLevel {
 | 
			
		||||
export enum LogLevel {
 | 
			
		||||
  Debug = 0,
 | 
			
		||||
  Info = 1,
 | 
			
		||||
  Warn = 2,
 | 
			
		||||
@@ -12,20 +12,29 @@ export const HOUR = 60 * MINUTE;
 | 
			
		||||
export const DAY = 24 * HOUR;
 | 
			
		||||
export const WEEK = 7 * DAY;
 | 
			
		||||
 | 
			
		||||
export interface CCLogInitConfig {
 | 
			
		||||
  printTerminal?: boolean;
 | 
			
		||||
  logInterval?: number;
 | 
			
		||||
  outputMinLevel?: LogLevel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class CCLog {
 | 
			
		||||
  private fp: LuaFile | undefined;
 | 
			
		||||
  private filename?: string;
 | 
			
		||||
  private interval: number;
 | 
			
		||||
  private logInterval: number;
 | 
			
		||||
  private printTerminal: boolean;
 | 
			
		||||
  private outputMinLevel: LogLevel;
 | 
			
		||||
  private startTime: number;
 | 
			
		||||
  private currentTimePeriod: string;
 | 
			
		||||
  private inTerm: boolean;
 | 
			
		||||
 | 
			
		||||
  constructor(filename?: string, inTerm = true, interval: number = DAY) {
 | 
			
		||||
  constructor(filename?: string, config?: CCLogInitConfig) {
 | 
			
		||||
    term.clear();
 | 
			
		||||
    term.setCursorPos(1, 1);
 | 
			
		||||
 | 
			
		||||
    this.interval = interval;
 | 
			
		||||
    this.inTerm = inTerm;
 | 
			
		||||
    this.logInterval = config?.logInterval ?? DAY;
 | 
			
		||||
    this.printTerminal = config?.printTerminal ?? true;
 | 
			
		||||
    this.outputMinLevel = config?.outputMinLevel ?? LogLevel.Debug;
 | 
			
		||||
 | 
			
		||||
    this.startTime = os.time(os.date("*t"));
 | 
			
		||||
    this.currentTimePeriod = this.getTimePeriodString(this.startTime);
 | 
			
		||||
 | 
			
		||||
@@ -49,14 +58,14 @@ export class CCLog {
 | 
			
		||||
   * For SECOND interval: YYYY-MM-DD-HH-MM-SS
 | 
			
		||||
   */
 | 
			
		||||
  private getTimePeriodString(time: number): string {
 | 
			
		||||
    const periodStart = Math.floor(time / this.interval) * this.interval;
 | 
			
		||||
    const periodStart = Math.floor(time / this.logInterval) * this.logInterval;
 | 
			
		||||
    const d = os.date("*t", periodStart);
 | 
			
		||||
 | 
			
		||||
    if (this.interval >= DAY) {
 | 
			
		||||
    if (this.logInterval >= DAY) {
 | 
			
		||||
      return `${d.year}-${string.format("%02d", d.month)}-${string.format("%02d", d.day)}`;
 | 
			
		||||
    } else if (this.interval >= HOUR) {
 | 
			
		||||
    } else if (this.logInterval >= HOUR) {
 | 
			
		||||
      return `${d.year}-${string.format("%02d", d.month)}-${string.format("%02d", d.day)}_${string.format("%02d", d.hour)}`;
 | 
			
		||||
    } else if (this.interval >= MINUTE) {
 | 
			
		||||
    } else if (this.logInterval >= MINUTE) {
 | 
			
		||||
      return `${d.year}-${string.format("%02d", d.month)}-${string.format("%02d", d.day)}_${string.format("%02d", d.hour)}-${string.format("%02d", d.min)}`;
 | 
			
		||||
    }
 | 
			
		||||
    return `${d.year}-${string.format("%02d", d.month)}-${string.format("%02d", d.day)}_${string.format("%02d", d.hour)}-${string.format("%02d", d.min)}-${string.format("%02d", d.sec)}`;
 | 
			
		||||
@@ -118,7 +127,7 @@ export class CCLog {
 | 
			
		||||
    // Check if we need to rotate the log file
 | 
			
		||||
    this.checkAndRotateLogFile();
 | 
			
		||||
 | 
			
		||||
    if (this.inTerm) {
 | 
			
		||||
    if (this.printTerminal) {
 | 
			
		||||
      let originalColor: Color = 0;
 | 
			
		||||
      if (color != undefined) {
 | 
			
		||||
        originalColor = term.getTextColor();
 | 
			
		||||
@@ -138,23 +147,31 @@ export class CCLog {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public debug(msg: string) {
 | 
			
		||||
    this.writeLine(this.getFormatMsg(msg, LogLevel.Debug), colors.gray);
 | 
			
		||||
    if (LogLevel.Debug >= this.outputMinLevel)
 | 
			
		||||
      this.writeLine(this.getFormatMsg(msg, LogLevel.Debug), colors.gray);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public info(msg: string) {
 | 
			
		||||
    this.writeLine(this.getFormatMsg(msg, LogLevel.Info), colors.green);
 | 
			
		||||
    if (LogLevel.Info >= this.outputMinLevel)
 | 
			
		||||
      this.writeLine(this.getFormatMsg(msg, LogLevel.Info), colors.green);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public warn(msg: string) {
 | 
			
		||||
    this.writeLine(this.getFormatMsg(msg, LogLevel.Warn), colors.orange);
 | 
			
		||||
    if (LogLevel.Warn >= this.outputMinLevel)
 | 
			
		||||
      this.writeLine(this.getFormatMsg(msg, LogLevel.Warn), colors.orange);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public error(msg: string) {
 | 
			
		||||
    this.writeLine(this.getFormatMsg(msg, LogLevel.Error), colors.red);
 | 
			
		||||
    if (LogLevel.Error >= this.outputMinLevel)
 | 
			
		||||
      this.writeLine(this.getFormatMsg(msg, LogLevel.Error), colors.red);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public setInTerminal(value: boolean) {
 | 
			
		||||
    this.inTerm = value;
 | 
			
		||||
    this.printTerminal = value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public setLogLevel(value: LogLevel) {
 | 
			
		||||
    this.outputMinLevel = value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public close() {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
import { UIObject } from "./UIObject";
 | 
			
		||||
import { calculateLayout } from "./layout";
 | 
			
		||||
import { render as renderTree, clearScreen } from "./renderer";
 | 
			
		||||
import { CCLog, HOUR } from "../ccLog";
 | 
			
		||||
import { CCLog, DAY, LogLevel } from "../ccLog";
 | 
			
		||||
import { setLogger } from "./context";
 | 
			
		||||
import { InputProps } from "./components";
 | 
			
		||||
import { Setter } from "./reactivity";
 | 
			
		||||
@@ -30,7 +30,11 @@ export class Application {
 | 
			
		||||
    const [width, height] = term.getSize();
 | 
			
		||||
    this.termWidth = width;
 | 
			
		||||
    this.termHeight = height;
 | 
			
		||||
    this.logger = new CCLog("tui_debug.log", false, HOUR);
 | 
			
		||||
    this.logger = new CCLog("tui_debug.log", {
 | 
			
		||||
      printTerminal: false,
 | 
			
		||||
      logInterval: DAY,
 | 
			
		||||
      outputMinLevel: LogLevel.Info,
 | 
			
		||||
    });
 | 
			
		||||
    setLogger(this.logger);
 | 
			
		||||
    this.logger.debug("Application constructed.");
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -34,21 +34,18 @@ export const deepCopy = <T>(target: T): T => {
 | 
			
		||||
  if (target === null) {
 | 
			
		||||
    return target;
 | 
			
		||||
  }
 | 
			
		||||
  if (target instanceof Date) {
 | 
			
		||||
    return new Date(target.getTime()) as any;
 | 
			
		||||
  if (Array.isArray(target)) {
 | 
			
		||||
    return (target as unknown[]).map((v: unknown) => deepCopy(v)) as T;
 | 
			
		||||
  }
 | 
			
		||||
  if (target instanceof Array) {
 | 
			
		||||
    const cp = [] as any[];
 | 
			
		||||
    (target as any[]).forEach((v) => { cp.push(v); });
 | 
			
		||||
    return cp.map((n: any) => deepCopy<any>(n)) as any;
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof target === 'object') {
 | 
			
		||||
    const cp = { ...(target as { [key: string]: any }) } as { [key: string]: any };
 | 
			
		||||
    Object.keys(cp).forEach(k => {
 | 
			
		||||
      cp[k] = deepCopy<any>(cp[k]);
 | 
			
		||||
  if (typeof target === "object") {
 | 
			
		||||
    const cp = { ...(target as Record<string, unknown>) } as Record<
 | 
			
		||||
      string,
 | 
			
		||||
      unknown
 | 
			
		||||
    >;
 | 
			
		||||
    Object.keys(cp).forEach((k) => {
 | 
			
		||||
      cp[k] = deepCopy<unknown>(cp[k]);
 | 
			
		||||
    });
 | 
			
		||||
    return cp as T;
 | 
			
		||||
  }
 | 
			
		||||
  return target;
 | 
			
		||||
};
 | 
			
		||||
@MohammadFakhreddin
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user