diff options
| author | Yuqian Yang <crupest@crupest.life> | 2025-06-14 01:21:11 +0800 | 
|---|---|---|
| committer | Yuqian Yang <crupest@crupest.life> | 2025-06-14 02:35:01 +0800 | 
| commit | 8fe85fccf3881114202301ac986073564d5abd3f (patch) | |
| tree | fc58511731fd77296e3f1df54478bb0208e5fcc5 /deno | |
| parent | 42526fed6f86a3a3a352313078668fcc8b473a3b (diff) | |
| download | crupest-8fe85fccf3881114202301ac986073564d5abd3f.tar.gz crupest-8fe85fccf3881114202301ac986073564d5abd3f.tar.bz2 crupest-8fe85fccf3881114202301ac986073564d5abd3f.zip | |
deno(mail-server): drop custom logger, use builtin console.
Diffstat (limited to 'deno')
| -rw-r--r-- | deno/base/log.ts | 41 | ||||
| -rw-r--r-- | deno/deno.lock | 3 | ||||
| -rw-r--r-- | deno/mail-relay/app.ts | 21 | ||||
| -rw-r--r-- | deno/mail-relay/aws/app.ts | 27 | ||||
| -rw-r--r-- | deno/mail-relay/aws/deliver.ts | 15 | ||||
| -rw-r--r-- | deno/mail-relay/aws/fetch.ts | 35 | ||||
| -rw-r--r-- | deno/mail-relay/aws/mail.ts | 22 | ||||
| -rw-r--r-- | deno/mail-relay/dovecot.ts | 12 | ||||
| -rw-r--r-- | deno/mail-relay/dumb-smtp-server.ts | 37 | ||||
| -rw-r--r-- | deno/mail-relay/mail.test.ts | 4 | ||||
| -rw-r--r-- | deno/mail-relay/mail.ts | 63 | ||||
| -rw-r--r-- | deno/tools/generate-geosite-rules.ts | 75 | ||||
| -rw-r--r-- | deno/tools/manage-vm.ts | 7 | 
13 files changed, 132 insertions, 230 deletions
| diff --git a/deno/base/log.ts b/deno/base/log.ts index cc71dfa..403b9ce 100644 --- a/deno/base/log.ts +++ b/deno/base/log.ts @@ -2,19 +2,11 @@ import { join } from "@std/path";  import { toFileNameString } from "./date.ts"; -export type LogLevel = "error" | "warn" | "info"; - -export interface LogOptions { -  level?: LogLevel; -  cause?: unknown; -} -  export interface ExternalLogStream extends Disposable {    stream: WritableStream;  }  export class Logger { -  #defaultLevel = "info" as const;    #externalLogDir?: string;    get externalLogDir() { @@ -30,39 +22,6 @@ export class Logger {      }    } -  write(message: string, options?: LogOptions): void { -    const logFunction = console[options?.level ?? this.#defaultLevel]; -    if (options?.cause != null) { -      logFunction.call(console, message, options.cause); -    } else { -      logFunction.call(console, message); -    } -  } - -  info(message: string) { -    this.write(message, { level: "info" }); -  } - -  tagInfo(tag: string, message: string) { -    this.info(tag + " " + message); -  } - -  warn(message: string) { -    this.write(message, { level: "warn" }); -  } - -  tagWarn(tag: string, message: string) { -    this.warn(tag + " " + message); -  } - -  error(message: string, cause?: unknown) { -    this.write(message, { level: "info", cause }); -  } - -  tagError(tag: string, message: string, cause?: unknown) { -    this.error(tag + " " + message, cause); -  } -    async createExternalLogStream(      name: string,      options?: { diff --git a/deno/deno.lock b/deno/deno.lock index 0fc543b..871a9ae 100644 --- a/deno/deno.lock +++ b/deno/deno.lock @@ -1326,8 +1326,7 @@        },        "tools": {          "dependencies": [ -          "npm:mustache@^4.2.0", -          "npm:yargs@18" +          "npm:mustache@^4.2.0"          ]        }      } diff --git a/deno/mail-relay/app.ts b/deno/mail-relay/app.ts index d96fa1d..0b9da07 100644 --- a/deno/mail-relay/app.ts +++ b/deno/mail-relay/app.ts @@ -35,15 +35,11 @@ export function createInbound(    return deliverer;  } -export function createHono( -  logger: Logger, -  outbound: MailDeliverer, -  inbound: MailDeliverer, -) { +export function createHono(outbound: MailDeliverer, inbound: MailDeliverer) {    const hono = new Hono();    hono.onError((err, c) => { -    logger.error("Hono handler throws an error.", err); +    console.error("Hono handler throws an error.", err);      return c.json({ msg: "Server error, check its log." }, 500);    });    hono.use(honoLogger()); @@ -66,11 +62,11 @@ export function createHono(    return hono;  } -export function createSmtp(logger: Logger, outbound: MailDeliverer) { -  return new DumbSmtpServer(logger, outbound); +export function createSmtp(outbound: MailDeliverer) { +  return new DumbSmtpServer(outbound);  } -export async function sendMail(logger: Logger, port: number) { +export async function sendMail(port: number) {    const decoder = new TextDecoder();    let text = "";    for await (const chunk of Deno.stdin.readable) { @@ -81,9 +77,8 @@ export async function sendMail(logger: Logger, port: number) {      method: "post",      body: text,    }); -  logger.write(Deno.inspect(res), { level: res.ok ? "info" : "error" }); -  logger.write(Deno.inspect(await res.text()), { -    level: res.ok ? "info" : "error", -  }); +  const fn = res.ok ? "info" : "error"; +  console[fn](res); +  console[fn](await res.text());    if (!res.ok) Deno.exit(-1);  } diff --git a/deno/mail-relay/aws/app.ts b/deno/mail-relay/aws/app.ts index 05d93cd..b7d0154 100644 --- a/deno/mail-relay/aws/app.ts +++ b/deno/mail-relay/aws/app.ts @@ -94,11 +94,10 @@ function createAwsOptions({  }  function createOutbound( -  logger: Logger,    awsOptions: ReturnType<typeof createAwsOptions>,    db: DbService,  ) { -  const deliverer = new AwsMailDeliverer(logger, awsOptions); +  const deliverer = new AwsMailDeliverer(awsOptions);    deliverer.preHooks.push(      new AwsMailMessageIdRewriteHook(db.messageIdToAws.bind(db)),    ); @@ -168,11 +167,7 @@ function createAwsFetchOnlyServices() {      password: config.get("awsPassword"),      region: config.get("awsRegion"),    }); -  const fetcher = new AwsMailFetcher( -    logger, -    awsOptions, -    config.get("awsMailBucket"), -  ); +  const fetcher = new AwsMailFetcher(awsOptions, config.get("awsMailBucket"));    return { config, logger, awsOptions, fetcher };  } @@ -195,7 +190,7 @@ function createAwsServices() {    const { config, logger, inbound, awsOptions, fetcher, recycler } =      createAwsRecycleOnlyServices();    const dbService = new DbService(join(config.get("dataPath"), "db.sqlite")); -  const outbound = createOutbound(logger, awsOptions, dbService); +  const outbound = createOutbound(awsOptions, dbService);    return {      config, @@ -211,10 +206,10 @@ function createAwsServices() {  function createServerServices() {    const services = createAwsServices(); -  const { logger, config, outbound, inbound, fetcher } = services; -  const smtp = createSmtp(logger, outbound); +  const { config, outbound, inbound, fetcher } = services; +  const smtp = createSmtp(outbound); -  const hono = createHono(logger, outbound, inbound); +  const hono = createHono(outbound, inbound);    setupAwsHono(hono, {      path: config.get("awsInboundPath"),      auth: config.get("awsInboundKey"), @@ -252,11 +247,11 @@ function serve(cron: boolean = false) {  }  async function listLives() { -  const { logger, fetcher } = createAwsFetchOnlyServices(); +  const { fetcher } = createAwsFetchOnlyServices();    const liveMails = await fetcher.listLiveMails(); -  logger.info(`Total ${liveMails.length}:`); +  console.info(`Total ${liveMails.length}:`);    if (liveMails.length !== 0) { -    logger.info(liveMails.join("\n")); +    console.info(liveMails.join("\n"));    }  } @@ -272,8 +267,8 @@ if (import.meta.main) {        command: "sendmail",        describe: "send mail via this server's endpoint",        handler: async (_argv) => { -        const { logger, config } = createBaseServices(); -        await sendMail(logger, config.getInt("httpPort")); +        const { config } = createBaseServices(); +        await sendMail(config.getInt("httpPort"));        },      })      .command({ diff --git a/deno/mail-relay/aws/deliver.ts b/deno/mail-relay/aws/deliver.ts index 117e87a..a002eda 100644 --- a/deno/mail-relay/aws/deliver.ts +++ b/deno/mail-relay/aws/deliver.ts @@ -4,7 +4,6 @@ import {    SESv2ClientConfig,  } from "@aws-sdk/client-sesv2"; -import { Logger } from "@crupest/base/log";  import { Mail, MailDeliverContext, SyncMailDeliverer } from "../mail.ts";  declare module "../mail.ts" { @@ -15,13 +14,11 @@ declare module "../mail.ts" {  export class AwsMailDeliverer extends SyncMailDeliverer {    readonly name = "aws"; -  readonly #logger;    readonly #aws;    readonly #ses; -  constructor(logger: Logger, aws: SESv2ClientConfig) { -    super(logger); -    this.#logger = logger; +  constructor(aws: SESv2ClientConfig) { +    super();      this.#aws = aws;      this.#ses = new SESv2Client(aws);    } @@ -30,7 +27,7 @@ export class AwsMailDeliverer extends SyncMailDeliverer {      mail: Mail,      context: MailDeliverContext,    ): Promise<void> { -    this.#logger.info("Begin to call aws send-email api..."); +    console.info("Begin to call aws send-email api...");      try {        const sendCommand = new SendEmailCommand({ @@ -41,9 +38,11 @@ export class AwsMailDeliverer extends SyncMailDeliverer {        const res = await this.#ses.send(sendCommand);        if (res.MessageId == null) { -        this.#logger.warn("Aws send-email returns no message id."); +        console.warn("Aws send-email returns no message id.");        } else { -        context.result.awsMessageId = `${res.MessageId}@${this.#aws.region}.amazonses.com`; +        context.result.awsMessageId = `${res.MessageId}@${ +          this.#aws.region +        }.amazonses.com`;        }        context.result.recipients.set("*", { diff --git a/deno/mail-relay/aws/fetch.ts b/deno/mail-relay/aws/fetch.ts index ef1ba5f..bbb671a 100644 --- a/deno/mail-relay/aws/fetch.ts +++ b/deno/mail-relay/aws/fetch.ts @@ -8,7 +8,6 @@ import {  } from "@aws-sdk/client-s3";  import { toFileNameString } from "@crupest/base/date"; -import { Logger } from "@crupest/base/log";  import { Mail } from "../mail.ts"; @@ -42,18 +41,16 @@ export type AwsS3MailConsumer = (  export class AwsMailFetcher {    readonly #livePrefix = "mail/live/";    readonly #archivePrefix = "mail/archive/"; -  readonly #logger;    readonly #s3;    readonly #bucket; -  constructor(logger: Logger, aws: S3ClientConfig, bucket: string) { -    this.#logger = logger; +  constructor(aws: S3ClientConfig, bucket: string) {      this.#s3 = new S3Client(aws);      this.#bucket = bucket;    }    async listLiveMails(): Promise<string[]> { -    this.#logger.info("Begin to retrieve live mails."); +    console.info("Begin to retrieve live mails.");      const listCommand = new ListObjectsV2Command({        Bucket: this.#bucket, @@ -62,16 +59,14 @@ export class AwsMailFetcher {      const res = await this.#s3.send(listCommand);      if (res.Contents == null) { -      this.#logger.warn("Listing live mails in S3 returns null Content."); +      console.warn("Listing live mails in S3 returns null Content.");        return [];      }      const result: string[] = [];      for (const object of res.Contents) {        if (object.Key == null) { -        this.#logger.warn( -          "Listing live mails in S3 returns an object with no Key.", -        ); +        console.warn("Listing live mails in S3 returns an object with no Key.");          continue;        } @@ -83,9 +78,9 @@ export class AwsMailFetcher {    }    async consumeS3Mail(s3Key: string, consumer: AwsS3MailConsumer) { -    this.#logger.info(`Begin to consume s3 mail ${s3Key} ...`); +    console.info(`Begin to consume s3 mail ${s3Key} ...`); -    this.#logger.info(`Fetching s3 mail ${s3Key}...`); +    console.info(`Fetching s3 mail ${s3Key}...`);      const mailPath = `${this.#livePrefix}${s3Key}`;      const command = new GetObjectCommand({        Bucket: this.#bucket, @@ -98,14 +93,14 @@ export class AwsMailFetcher {      }      const rawMail = await res.Body.transformToString(); -    this.#logger.info(`Done fetching s3 mail ${s3Key}.`); +    console.info(`Done fetching s3 mail ${s3Key}.`); -    this.#logger.info(`Calling consumer...`); +    console.info(`Calling consumer...`);      await consumer(rawMail, s3Key); -    this.#logger.info(`Done consuming s3 mail ${s3Key}.`); +    console.info(`Done consuming s3 mail ${s3Key}.`);      const date = new Mail(rawMail) -      .startSimpleParse(this.#logger) +      .startSimpleParse()        .sections()        .headers()        .date(); @@ -113,17 +108,17 @@ export class AwsMailFetcher {        date != null ? toFileNameString(date, true) : "invalid-date";      const newPath = `${this.#archivePrefix}${dateString}/${s3Key}`; -    this.#logger.info(`Archiving s3 mail ${s3Key} to ${newPath}...`); +    console.info(`Archiving s3 mail ${s3Key} to ${newPath}...`);      await s3MoveObject(this.#s3, this.#bucket, mailPath, newPath); -    this.#logger.info(`Done archiving s3 mail ${s3Key}.`); +    console.info(`Done archiving s3 mail ${s3Key}.`); -    this.#logger.info(`Done consuming s3 mail ${s3Key}.`); +    console.info(`Done consuming s3 mail ${s3Key}.`);    }    async recycleLiveMails(consumer: AwsS3MailConsumer) { -    this.#logger.info("Begin to recycle live mails..."); +    console.info("Begin to recycle live mails...");      const mails = await this.listLiveMails(); -    this.#logger.info(`Found ${mails.length} live mails`); +    console.info(`Found ${mails.length} live mails`);      for (const s3Key of mails) {        await this.consumeS3Mail(s3Key, consumer);      } diff --git a/deno/mail-relay/aws/mail.ts b/deno/mail-relay/aws/mail.ts index d2cfad1..cc05d23 100644 --- a/deno/mail-relay/aws/mail.ts +++ b/deno/mail-relay/aws/mail.ts @@ -8,17 +8,17 @@ export class AwsMailMessageIdRewriteHook implements MailDeliverHook {    }    async callback(context: MailDeliverContext): Promise<void> { -    context.logger.info("Rewrite message ids..."); +    console.info("Rewrite message ids...");      const addresses = context.mail.simpleFindAllAddresses(); -    context.logger.info(`Addresses found in mail: ${addresses.join(", ")}.`); +    console.info(`Addresses found in mail: ${addresses.join(", ")}.`);      for (const address of addresses) {        const awsMessageId = await this.#lookup(address);        if (awsMessageId != null && awsMessageId.length !== 0) { -        context.logger.info(`Rewrite ${address} to ${awsMessageId}.`); +        console.info(`Rewrite ${address} to ${awsMessageId}.`);          context.mail.raw = context.mail.raw.replaceAll(address, awsMessageId);        }      } -    context.logger.info("Done rewrite message ids."); +    console.info("Done rewrite message ids.");    }  } @@ -30,24 +30,20 @@ export class AwsMailMessageIdSaveHook implements MailDeliverHook {    }    async callback(context: MailDeliverContext): Promise<void> { -    context.logger.info("Save aws message ids..."); +    console.info("Save aws message ids...");      const messageId = context.mail -      .startSimpleParse(context.logger) +      .startSimpleParse()        .sections()        .headers()        .messageId();      if (messageId == null) { -      context.logger.info( -        "Original mail does not have message id. Skip saving.", -      ); +      console.info("Original mail does not have message id. Skip saving.");        return;      }      if (context.result.awsMessageId != null) { -      context.logger.info( -        `Saving ${messageId} => ${context.result.awsMessageId}.`, -      ); +      console.info(`Saving ${messageId} => ${context.result.awsMessageId}.`);        await this.#record(messageId, context.result.awsMessageId);      } -    context.logger.info("Done save message ids."); +    console.info("Done save message ids.");    }  } diff --git a/deno/mail-relay/dovecot.ts b/deno/mail-relay/dovecot.ts index 124a82b..748d6fa 100644 --- a/deno/mail-relay/dovecot.ts +++ b/deno/mail-relay/dovecot.ts @@ -6,10 +6,12 @@ import { Mail, MailDeliverContext, MailDeliverer } from "./mail.ts";  export class DovecotMailDeliverer extends MailDeliverer {    readonly name = "dovecot"; +  readonly #logger;    readonly #ldaPath;    constructor(logger: Logger, ldaPath: string) { -    super(logger); +    super(); +    this.#logger = logger;      this.#ldaPath = ldaPath;    } @@ -29,12 +31,12 @@ export class DovecotMailDeliverer extends MailDeliverer {        return;      } -    this.logger.info(`Deliver to dovecot users: ${recipients.join(", ")}.`); +    console.info(`Deliver to dovecot users: ${recipients.join(", ")}.`);      for (const recipient of recipients) {        try {          const commandArgs = ["-d", recipient]; -        this.logger.info(`Run ${ldaBinName} ${commandArgs.join(" ")}...`); +        console.info(`Run ${ldaBinName} ${commandArgs.join(" ")}...`);          const ldaCommand = new Deno.Command(ldaPath, {            args: commandArgs, @@ -45,7 +47,7 @@ export class DovecotMailDeliverer extends MailDeliverer {          const ldaProcess = ldaCommand.spawn();          using logFiles = -          await this.logger.createExternalLogStreamsForProgram(ldaBinName); +          await this.#logger.createExternalLogStreamsForProgram(ldaBinName);          ldaProcess.stdout.pipeTo(logFiles.stdout);          ldaProcess.stderr.pipeTo(logFiles.stderr); @@ -90,6 +92,6 @@ export class DovecotMailDeliverer extends MailDeliverer {        }      } -    this.logger.info("Done handling all recipients."); +    console.info("Done handling all recipients.");    }  } diff --git a/deno/mail-relay/dumb-smtp-server.ts b/deno/mail-relay/dumb-smtp-server.ts index 1a1090a..ac7069c 100644 --- a/deno/mail-relay/dumb-smtp-server.ts +++ b/deno/mail-relay/dumb-smtp-server.ts @@ -1,4 +1,3 @@ -import { Logger } from "@crupest/base/log";  import { MailDeliverer } from "./mail.ts";  const CRLF = "\r\n"; @@ -20,26 +19,24 @@ function createResponses(host: string, port: number | string) {  const LOG_TAG = "[dumb-smtp]";  export class DumbSmtpServer { -  #logger;    #deliverer;    #responses: ReturnType<typeof createResponses> = createResponses(      "invalid",      "invalid",    ); -  constructor(logger: Logger, deliverer: MailDeliverer) { -    this.#logger = logger; +  constructor(deliverer: MailDeliverer) {      this.#deliverer = deliverer;    }    async #handleConnection(conn: Deno.Conn) {      using disposeStack = new DisposableStack();      disposeStack.defer(() => { -      this.#logger.tagInfo(LOG_TAG, "Close session's tcp connection."); +      console.info(LOG_TAG, "Close session's tcp connection.");        conn.close();      }); -    this.#logger.tagInfo(LOG_TAG, "New session's tcp connection established."); +    console.info(LOG_TAG, "New session's tcp connection established.");      const writer = conn.writable.getWriter();      disposeStack.defer(() => writer.releaseLock()); @@ -49,7 +46,7 @@ export class DumbSmtpServer {      const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];      const decode = (data: Uint8Array) => decoder.decode(data);      const send = async (s: string) => { -      this.#logger.tagInfo(LOG_TAG, "Send line: " + s); +      console.info(LOG_TAG, "Send line: " + s);        await writer.write(encoder.encode(s + CRLF));      }; @@ -72,7 +69,7 @@ export class DumbSmtpServer {          buffer = buffer.slice(eolPos + CRLF.length);          if (rawMail == null) { -          this.#logger.tagInfo(LOG_TAG, "Received line: " + line); +          console.info(LOG_TAG, "Received line: " + line);            const upperLine = line.toUpperCase();            if (upperLine.startsWith("EHLO") || upperLine.startsWith("HELO")) {              await send(this.#responses["EHLO"]); @@ -82,32 +79,26 @@ export class DumbSmtpServer {              await send(this.#responses["RCPT"]);            } else if (upperLine === "DATA") {              await send(this.#responses["DATA"]); -            this.#logger.tagInfo(LOG_TAG, "Begin to receive mail data..."); +            console.info(LOG_TAG, "Begin to receive mail data...");              rawMail = "";            } else if (upperLine === "QUIT") {              await send(this.#responses["QUIT"]);              return;            } else { -            this.#logger.tagWarn( -              LOG_TAG, -              "Unrecognized command from client: " + line, -            ); +            console.warn(LOG_TAG, "Unrecognized command from client: " + line);              await send(this.#responses["INVALID"]);              return;            }          } else {            if (line === ".") {              try { -              this.#logger.tagInfo( -                LOG_TAG, -                "Mail data Received, begin to relay...", -              ); +              console.info(LOG_TAG, "Mail data Received, begin to relay...");                const { message } = await this.#deliverer.deliverRaw(rawMail);                await send(`250 2.6.0 ${message}`);                rawMail = null; -              this.#logger.tagInfo(LOG_TAG, "Relay succeeded."); +              console.info(LOG_TAG, "Relay succeeded.");              } catch (err) { -              this.#logger.tagError(LOG_TAG, "Relay failed.", err); +              console.error(LOG_TAG, "Relay failed.", err);                await send("554 5.3.0 Error: check server log");                return;              } @@ -123,7 +114,7 @@ export class DumbSmtpServer {    async serve(options: { hostname: string; port: number }) {      const listener = Deno.listen(options);      this.#responses = createResponses(options.hostname, options.port); -    this.#logger.tagInfo( +    console.info(        LOG_TAG,        `Dumb SMTP server starts to listen on ${this.#responses.serverName}.`,      ); @@ -132,11 +123,7 @@ export class DumbSmtpServer {        try {          await this.#handleConnection(conn);        } catch (cause) { -        this.#logger.tagError( -          LOG_TAG, -          "Tcp connection throws an error.", -          cause, -        ); +        console.error(LOG_TAG, "Tcp connection throws an error.", cause);        }      }    } diff --git a/deno/mail-relay/mail.test.ts b/deno/mail-relay/mail.test.ts index 09cf8eb..6abb7d7 100644 --- a/deno/mail-relay/mail.test.ts +++ b/deno/mail-relay/mail.test.ts @@ -1,8 +1,6 @@  import { describe, it } from "@std/testing/bdd";  import { expect, fn } from "@std/expect"; -import { Logger } from "@crupest/base/log"; -  import { Mail, MailDeliverContext, MailDeliverer } from "./mail.ts";  const mockDate = "Fri, 02 May 2025 08:33:02 +0000"; @@ -119,7 +117,7 @@ describe("MailDeliverer", () => {        return Promise.resolve();      }) as MailDeliverer["doDeliver"];    } -  const mockDeliverer = new MockMailDeliverer(new Logger()); +  const mockDeliverer = new MockMailDeliverer();    it("deliver success", async () => {      await mockDeliverer.deliverRaw(mockMailStr); diff --git a/deno/mail-relay/mail.ts b/deno/mail-relay/mail.ts index 12d5972..d6dfe65 100644 --- a/deno/mail-relay/mail.ts +++ b/deno/mail-relay/mail.ts @@ -2,19 +2,10 @@ import { encodeBase64 } from "@std/encoding/base64";  import { parse } from "@std/csv/parse";  import emailAddresses from "email-addresses"; -import { Logger } from "@crupest/base/log"; -  class MailSimpleParseError extends Error {}  class MailSimpleParsedHeaders { -  #logger; - -  constructor( -    logger: Logger | undefined, -    public fields: [key: string, value: string][], -  ) { -    this.#logger = logger; -  } +  constructor(public fields: [key: string, value: string][]) {}    getFirst(fieldKey: string): string | undefined {      for (const [key, value] of this.fields) { @@ -31,9 +22,7 @@ class MailSimpleParsedHeaders {      if (match != null) {        return match[1];      } else { -      this.#logger?.warn( -        "Invalid message-id header of mail: " + messageIdField, -      ); +      console.warn("Invalid message-id header of mail: " + messageIdField);        return undefined;      }    } @@ -44,7 +33,7 @@ class MailSimpleParsedHeaders {      const date = new Date(dateField);      if (invalidToUndefined && isNaN(date.getTime())) { -      this.#logger?.warn(`Invalid date string (${dateField}) found in header.`); +      console.warn(`Invalid date string (${dateField}) found in header.`);        return undefined;      }      return date; @@ -76,11 +65,7 @@ class MailSimpleParsedSections {    eol: string;    sep: string; -  #logger; - -  constructor(logger: Logger | undefined, raw: string) { -    this.#logger = logger; - +  constructor(raw: string) {      const twoEolMatch = raw.match(/(\r?\n)(\r?\n)/);      if (twoEolMatch == null) {        throw new MailSimpleParseError( @@ -91,7 +76,7 @@ class MailSimpleParsedSections {      const [eol, sep] = [twoEolMatch[1], twoEolMatch[2]];      if (eol !== sep) { -      logger?.warn("Different EOLs (\\r\\n, \\n) found."); +      console.warn("Different EOLs (\\r\\n, \\n) found.");      }      this.header = raw.slice(0, twoEolMatch.index!); @@ -131,7 +116,7 @@ class MailSimpleParsedSections {      handleField(); -    return new MailSimpleParsedHeaders(this.#logger, headers); +    return new MailSimpleParsedHeaders(headers);    }  } @@ -147,8 +132,8 @@ export class Mail {      return encodeBase64(this.raw);    } -  startSimpleParse(logger?: Logger) { -    return { sections: () => new MailSimpleParsedSections(logger, this.raw) }; +  startSimpleParse() { +    return { sections: () => new MailSimpleParsedSections(this.raw) };    }    simpleFindAllAddresses(): string[] { @@ -195,10 +180,7 @@ export class MailDeliverContext {    readonly recipients: Set<string> = new Set();    readonly result; -  constructor( -    public readonly logger: Logger, -    public mail: Mail, -  ) { +  constructor(public mail: Mail) {      this.result = new MailDeliverResult(this.mail);    }  } @@ -212,8 +194,6 @@ export abstract class MailDeliverer {    preHooks: MailDeliverHook[] = [];    postHooks: MailDeliverHook[] = []; -  constructor(protected readonly logger: Logger) {} -    protected abstract doDeliver(      mail: Mail,      context: MailDeliverContext, @@ -227,9 +207,9 @@ export abstract class MailDeliverer {      mail: Mail;      recipients?: string[];    }): Promise<MailDeliverResult> { -    this.logger.info(`Begin to deliver mail via ${this.name}...`); +    console.info(`Begin to deliver mail via ${this.name}...`); -    const context = new MailDeliverContext(this.logger, options.mail); +    const context = new MailDeliverContext(options.mail);      options.recipients?.forEach((r) => context.recipients.add(r));      for (const hook of this.preHooks) { @@ -242,7 +222,8 @@ export abstract class MailDeliverer {        await hook.callback(context);      } -    context.logger.info("Deliver result:\n" + Deno.inspect(context.result)); +    console.info("Deliver result:"); +    console.info(context.result);      if (context.result.hasError()) {        throw new Error("Mail failed to deliver."); @@ -259,7 +240,7 @@ export abstract class SyncMailDeliverer extends MailDeliverer {      mail: Mail;      recipients?: string[];    }): Promise<MailDeliverResult> { -    this.logger.info( +    console.info(        "The mail deliverer is sync. Wait for last delivering done...",      );      await this.#last; @@ -277,12 +258,12 @@ export class RecipientFromHeadersHook implements MailDeliverHook {    callback(context: MailDeliverContext) {      if (context.recipients.size !== 0) { -      context.logger.warn( +      console.warn(          "Recipients are already filled. Won't set them with ones in headers.",        );      } else {        context.mail -        .startSimpleParse(context.logger) +        .startSimpleParse()          .sections()          .headers()          .recipients({ @@ -290,7 +271,7 @@ export class RecipientFromHeadersHook implements MailDeliverHook {          })          .forEach((r) => context.recipients.add(r)); -      context.logger.info( +      console.info(          "Recipients found from mail headers: " +            [...context.recipients].join(", "),        ); @@ -304,7 +285,7 @@ export class FallbackRecipientHook implements MailDeliverHook {    callback(context: MailDeliverContext) {      if (context.recipients.size === 0) { -      context.logger.info( +      console.info(          "No recipients, fill with fallback: " + [...this.fallback].join(", "),        );        this.fallback.forEach((a) => context.recipients.add(a)); @@ -320,10 +301,10 @@ export class AliasRecipientMailHook implements MailDeliverHook {      this.#aliasFile = aliasFile;    } -  async #parseAliasFile(logger: Logger): Promise<Map<string, string>> { +  async #parseAliasFile(): Promise<Map<string, string>> {      const result = new Map();      if ((await Deno.stat(this.#aliasFile)).isFile) { -      logger.info(`Found recipients alias file: ${this.#aliasFile}.`); +      console.info(`Found recipients alias file: ${this.#aliasFile}.`);        const text = await Deno.readTextFile(this.#aliasFile);        const csv = parse(text);        for (const [real, ...aliases] of csv) { @@ -334,11 +315,11 @@ export class AliasRecipientMailHook implements MailDeliverHook {    }    async callback(context: MailDeliverContext) { -    const aliases = await this.#parseAliasFile(context.logger); +    const aliases = await this.#parseAliasFile();      for (const recipient of [...context.recipients]) {        const realRecipients = aliases.get(recipient);        if (realRecipients != null) { -        context.logger.info( +        console.info(            `Recipient alias resolved: ${recipient} => ${realRecipients}.`,          );          context.recipients.delete(recipient); diff --git a/deno/tools/generate-geosite-rules.ts b/deno/tools/generate-geosite-rules.ts index c59d34f..bfa53ba 100644 --- a/deno/tools/generate-geosite-rules.ts +++ b/deno/tools/generate-geosite-rules.ts @@ -1,7 +1,8 @@ -const PROXY_NAME = "node-select" -const ATTR = "cn" +const PROXY_NAME = "node-select"; +const ATTR = "cn";  const REPO_NAME = "domain-list-community"; -const URL = "https://github.com/v2fly/domain-list-community/archive/refs/heads/master.zip" +const URL = +  "https://github.com/v2fly/domain-list-community/archive/refs/heads/master.zip";  const SITES = [    "github",    "google", @@ -39,9 +40,9 @@ const SITES = [    "ieee",    "sci-hub",    "libgen", -] +]; -const prefixes = ["include", "domain", "keyword", "full", "regexp"] as const +const prefixes = ["include", "domain", "keyword", "full", "regexp"] as const;  interface Rule {    kind: (typeof prefixes)[number]; @@ -52,20 +53,20 @@ interface Rule {  type FileProvider = (name: string) => string;  function extract(starts: string[], provider: FileProvider): Rule[] { -function parseLine(line: string): Rule { -  let kind = prefixes.find((p) => line.startsWith(p + ":")); -  if (kind != null) { -    line = line.slice(line.indexOf(":") + 1); -  } else { -    kind = "domain"; +  function parseLine(line: string): Rule { +    let kind = prefixes.find((p) => line.startsWith(p + ":")); +    if (kind != null) { +      line = line.slice(line.indexOf(":") + 1); +    } else { +      kind = "domain"; +    } +    const segs = line.split("@"); +    return { +      kind, +      value: segs[0].trim(), +      attrs: [...segs.slice(1)].map((s) => s.trim()), +    };    } -  const segs = line.split("@"); -  return { -    kind, -    value: segs[0].trim(), -    attrs: [...segs.slice(1)].map((s) => s.trim()), -  }; -}    function parse(text: string): Rule[] {      return text @@ -76,10 +77,10 @@ function parseLine(line: string): Rule {        .map((l) => parseLine(l));    } -  const visited = [] as string[] -  const rules = [] as Rule[] +  const visited = [] as string[]; +  const rules = [] as Rule[]; -  function add(name :string) { +  function add(name: string) {      const text = provider(name);      for (const rule of parse(text)) {        if (rule.kind === "include") { @@ -100,25 +101,25 @@ function parseLine(line: string): Rule {      add(start);    } -  return rules +  return rules;  }  function toNewFormat(rules: Rule[], attr: string): [string, string] {    function toLine(rule: Rule) {      const prefixMap = { -      "domain": "DOMAIN-SUFFIX", -      "full": "DOMAIN", -      "keyword": "DOMAIN-KEYWORD", -      "regexp": "DOMAIN-REGEX", +      domain: "DOMAIN-SUFFIX", +      full: "DOMAIN", +      keyword: "DOMAIN-KEYWORD", +      regexp: "DOMAIN-REGEX",      } as const;      if (rule.kind === "include") { -      throw new Error("Include rule not parsed.") +      throw new Error("Include rule not parsed.");      } -    return `${prefixMap[rule.kind]},${rule.value}` +    return `${prefixMap[rule.kind]},${rule.value}`;    }    function toLines(rules: Rule[]) { -    return rules.map(r => toLine(r)).join("\n") +    return rules.map((r) => toLine(r)).join("\n");    }    const has: Rule[] = []; @@ -128,7 +129,6 @@ function toNewFormat(rules: Rule[], attr: string): [string, string] {    return [toLines(has), toLines(notHas)];  } -  if (import.meta.main) {    const tmpDir = Deno.makeTempDirSync({ prefix: "geosite-rules-" });    console.log("Work dir is ", tmpDir); @@ -150,12 +150,11 @@ if (import.meta.main) {    const provider = (name: string) =>      Deno.readTextFileSync(dataDir + "/" + name); -  const rules = extract(SITES, provider) -  const [has, notHas] = toNewFormat(rules, ATTR) -  const hasFile = tmpDir + "/has-rule" -  const notHasFile = tmpDir + "/not-has-rule" -  console.log("Write result to: " + hasFile + " , " + notHasFile) -  Deno.writeTextFileSync(hasFile, has) -  Deno.writeTextFileSync(notHasFile, notHas) +  const rules = extract(SITES, provider); +  const [has, notHas] = toNewFormat(rules, ATTR); +  const hasFile = tmpDir + "/has-rule"; +  const notHasFile = tmpDir + "/not-has-rule"; +  console.log("Write result to: " + hasFile + " , " + notHasFile); +  Deno.writeTextFileSync(hasFile, has); +  Deno.writeTextFileSync(notHasFile, notHas);  } - diff --git a/deno/tools/manage-vm.ts b/deno/tools/manage-vm.ts index a1388b1..bb985ce 100644 --- a/deno/tools/manage-vm.ts +++ b/deno/tools/manage-vm.ts @@ -1,9 +1,8 @@ -import os from "node:os" +import os from "node:os";  import { join } from "@std/path";  // @ts-types="npm:@types/yargs"  import yargs from "yargs"; -  type ArchAliasMap = { [name: string]: string[] };  const arches = {    x86_64: ["x86_64", "amd64"], @@ -13,9 +12,7 @@ type Arch = keyof typeof arches;  type GeneralArch = (typeof arches)[Arch][number];  function normalizeArch(generalName: GeneralArch): Arch { -  for (const [name, aliases] of Object.entries( -    arches as ArchAliasMap, -  )) { +  for (const [name, aliases] of Object.entries(arches as ArchAliasMap)) {      if (aliases.includes(generalName)) return name as Arch;    }    throw Error("Unknown architecture name."); | 
