Full Code of Flysoft-Studio/QQNTim for AI

dev 5cd25d12b7a8 cached
103 files
1.1 MB
240.5k tokens
1646 symbols
1 requests
Download .txt
Showing preview only (1,131K chars total). Download the full file or copy to clipboard to get everything.
Repository: Flysoft-Studio/QQNTim
Branch: dev
Commit: 5cd25d12b7a8
Files: 103
Total size: 1.1 MB

Directory structure:
gitextract_sv6t5qoj/

├── .gitattributes
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── .yarn/
│   └── sdks/
│       ├── integrations.yml
│       └── typescript/
│           ├── bin/
│           │   ├── tsc
│           │   └── tsserver
│           ├── lib/
│           │   ├── tsc.js
│           │   ├── tsserver.js
│           │   ├── tsserverlibrary.js
│           │   └── typescript.js
│           └── package.json
├── COPYING
├── COPYING.LESSER
├── DEVELOPMENT.md
├── MANUAL.md
├── README.md
├── build.ts
├── examples/
│   └── NT-API/
│       ├── consts.js
│       ├── qqntim.json
│       ├── renderer.js
│       └── settings.js
├── package.json
├── publish/
│   ├── _/
│   │   ├── install.ps1
│   │   └── uninstall.ps1
│   ├── install.cmd
│   ├── install.sh
│   ├── install_macos.sh
│   ├── uninstall.cmd
│   ├── uninstall.sh
│   └── uninstall_macos.sh
├── rome.json
├── scripts/
│   ├── pack.ps1
│   ├── pack.sh
│   ├── start.ps1
│   └── start.sh
├── src/
│   ├── builtins/
│   │   └── settings/
│   │       ├── package.json
│   │       ├── publish/
│   │       │   ├── qqntim.json
│   │       │   └── style.css
│   │       ├── src/
│   │       │   ├── _renderer.tsx
│   │       │   ├── exports/
│   │       │   │   ├── components.tsx
│   │       │   │   └── index.ts
│   │       │   ├── installer.ts
│   │       │   ├── main.ts
│   │       │   ├── nav.tsx
│   │       │   ├── panel.tsx
│   │       │   ├── qqntim-env.d.ts
│   │       │   ├── renderer.ts
│   │       │   └── utils/
│   │       │       ├── consts.ts
│   │       │       ├── hooks.tsx
│   │       │       ├── sep.ts
│   │       │       └── utils.ts
│   │       └── tsconfig.json
│   ├── common/
│   │   ├── global.ts
│   │   ├── ipc.ts
│   │   ├── loader.ts
│   │   ├── patch.ts
│   │   ├── paths.ts
│   │   ├── sep.ts
│   │   ├── utils/
│   │   │   ├── console.ts
│   │   │   ├── freePort.ts
│   │   │   ├── ntVersion.ts
│   │   │   └── process.ts
│   │   ├── version.ts
│   │   └── watch.ts
│   ├── electron/
│   │   ├── README.txt
│   │   └── package.json
│   ├── main/
│   │   ├── api.ts
│   │   ├── compatibility.ts
│   │   ├── config.ts
│   │   ├── debugger.ts
│   │   ├── loader.ts
│   │   ├── main.ts
│   │   ├── patch.ts
│   │   └── plugins.ts
│   ├── qqntim-env.d.ts
│   ├── renderer/
│   │   ├── api/
│   │   │   ├── app.ts
│   │   │   ├── browserWindow.ts
│   │   │   ├── dialog.ts
│   │   │   ├── getVueId.ts
│   │   │   ├── index.ts
│   │   │   ├── nt/
│   │   │   │   ├── call.ts
│   │   │   │   ├── constructor.ts
│   │   │   │   ├── destructor.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── media.ts
│   │   │   │   └── watcher.ts
│   │   │   ├── waitForElement.ts
│   │   │   └── windowLoadPromise.ts
│   │   ├── debugger.ts
│   │   ├── loader.ts
│   │   ├── main.ts
│   │   ├── patch.ts
│   │   └── vueHelper.ts
│   └── typings/
│       ├── COPYING
│       ├── COPYING.LESSER
│       ├── electron.d.ts
│       ├── index.d.ts
│       ├── package.json
│       └── tsconfig.json
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
/.yarn/**            linguist-vendored
/.yarn/releases/*    binary
/.yarn/plugins/**/*  binary
/.pnp.*              binary linguist-generated


================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  - package-ecosystem: "npm" # See documentation for possible values
    directory: "/" # Location of package manifests
    schedule:
      interval: "daily"


================================================
FILE: .github/workflows/build.yml
================================================
name: Build

on:
    workflow_dispatch:
    push:

jobs:
    build:
        runs-on: ubuntu-latest
        permissions:
            contents: write
        steps:
            - uses: actions/checkout@v3

            - name: Use Node.js
              uses: actions/setup-node@v3
              with:
                  node-version: 18.x

            - name: Setup Corepack
              run: corepack enable

            - name: Cache Yarn dependencies
              id: yarn-cache
              uses: actions/cache@v3
              with:
                  path: |
                      .yarn/cache
                      .yarn/unplugged
                      .yarn/install-state.gz
                      .pnp.cjs
                  key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
                  restore-keys: |
                      ${{ runner.os }}-yarn-

            - name: Install Yarn dependencies
              run: yarn install

            - name: Build
              run: yarn build:linux

            - name: Compress files
              run: |
                  mkdir upload
                  pushd dist
                  tar -zcvf ../upload/qqntim-build.tar.gz . 
                  zip -r9 ../upload/qqntim-build.zip .
                  popd

            - name: Upload artifact
              uses: actions/upload-artifact@v3
              with:
                  name: build
                  path: upload/*

            - name: Create release
              if: github.ref_type == 'tag'
              uses: softprops/action-gh-release@v1
              with:
                  files: upload/*
                  generate_release_notes: true
                  tag_name: ${{ github.ref_name }}
                  prerelease: ${{ endsWith(github.ref_name, 'alpha') }}
                  draft: false
                  name: ${{ github.ref_name }}

            - name: Setup .yarnrc.yml
              if: github.ref_type == 'tag'
              run: |
                  yarn config set npmRegistryServer https://registry.npmjs.org
                  yarn config set npmAlwaysAuth true
                  yarn config set npmAuthToken $NPM_AUTH_TOKEN
              env:
                  NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

            - name: Publish NPM Package
              if: github.ref_type == 'tag'
              run: yarn workspace @flysoftbeta/qqntim-typings npm publish


================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Swap the comments on the following lines if you don't wish to use zero-installs
# Documentation here: https://yarnpkg.com/features/zero-installs
# !.yarn/cache
.pnp.*

test.sh

================================================
FILE: .vscode/extensions.json
================================================
{
    "recommendations": ["arcanis.vscode-zipfs"]
}


================================================
FILE: .vscode/settings.json
================================================
{
    "search.exclude": {
        "**/.yarn": true,
        "**/.pnp.*": true
    },
    "typescript.tsdk": ".yarn/sdks/typescript/lib",
    "typescript.enablePromptUseWorkspaceTsdk": true
}


================================================
FILE: .yarn/sdks/integrations.yml
================================================
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!

integrations:
  - vscode


================================================
FILE: .yarn/sdks/typescript/bin/tsc
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/bin/tsc
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/bin/tsc your application uses
module.exports = absRequire(`typescript/bin/tsc`);


================================================
FILE: .yarn/sdks/typescript/bin/tsserver
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/bin/tsserver
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/bin/tsserver your application uses
module.exports = absRequire(`typescript/bin/tsserver`);


================================================
FILE: .yarn/sdks/typescript/lib/tsc.js
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/lib/tsc.js
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/lib/tsc.js your application uses
module.exports = absRequire(`typescript/lib/tsc.js`);


================================================
FILE: .yarn/sdks/typescript/lib/tsserver.js
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

const moduleWrapper = tsserver => {
  if (!process.versions.pnp) {
    return tsserver;
  }

  const {isAbsolute} = require(`path`);
  const pnpApi = require(`pnpapi`);

  const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
  const isPortal = str => str.startsWith("portal:/");
  const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);

  const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
    return `${locator.name}@${locator.reference}`;
  }));

  // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
  // doesn't understand. This layer makes sure to remove the protocol
  // before forwarding it to TS, and to add it back on all returned paths.

  function toEditorPath(str) {
    // We add the `zip:` prefix to both `.zip/` paths and virtual paths
    if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
      // We also take the opportunity to turn virtual paths into physical ones;
      // this makes it much easier to work with workspaces that list peer
      // dependencies, since otherwise Ctrl+Click would bring us to the virtual
      // file instances instead of the real ones.
      //
      // We only do this to modules owned by the the dependency tree roots.
      // This avoids breaking the resolution when jumping inside a vendor
      // with peer dep (otherwise jumping into react-dom would show resolution
      // errors on react).
      //
      const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
      if (resolved) {
        const locator = pnpApi.findPackageLocator(resolved);
        if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
          str = resolved;
        }
      }

      str = normalize(str);

      if (str.match(/\.zip\//)) {
        switch (hostInfo) {
          // Absolute VSCode `Uri.fsPath`s need to start with a slash.
          // VSCode only adds it automatically for supported schemes,
          // so we have to do it manually for the `zip` scheme.
          // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
          //
          // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
          //
          // 2021-10-08: VSCode changed the format in 1.61.
          // Before | ^zip:/c:/foo/bar.zip/package.json
          // After  | ^/zip//c:/foo/bar.zip/package.json
          //
          // 2022-04-06: VSCode changed the format in 1.66.
          // Before | ^/zip//c:/foo/bar.zip/package.json
          // After  | ^/zip/c:/foo/bar.zip/package.json
          //
          // 2022-05-06: VSCode changed the format in 1.68
          // Before | ^/zip/c:/foo/bar.zip/package.json
          // After  | ^/zip//c:/foo/bar.zip/package.json
          //
          case `vscode <1.61`: {
            str = `^zip:${str}`;
          } break;

          case `vscode <1.66`: {
            str = `^/zip/${str}`;
          } break;

          case `vscode <1.68`: {
            str = `^/zip${str}`;
          } break;

          case `vscode`: {
            str = `^/zip/${str}`;
          } break;

          // To make "go to definition" work,
          // We have to resolve the actual file system path from virtual path
          // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
          case `coc-nvim`: {
            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
            str = resolve(`zipfile:${str}`);
          } break;

          // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
          // We have to resolve the actual file system path from virtual path,
          // everything else is up to neovim
          case `neovim`: {
            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
            str = `zipfile://${str}`;
          } break;

          default: {
            str = `zip:${str}`;
          } break;
        }
      } else {
        str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
      }
    }

    return str;
  }

  function fromEditorPath(str) {
    switch (hostInfo) {
      case `coc-nvim`: {
        str = str.replace(/\.zip::/, `.zip/`);
        // The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
        // So in order to convert it back, we use .* to match all the thing
        // before `zipfile:`
        return process.platform === `win32`
          ? str.replace(/^.*zipfile:\//, ``)
          : str.replace(/^.*zipfile:/, ``);
      } break;

      case `neovim`: {
        str = str.replace(/\.zip::/, `.zip/`);
        // The path for neovim is in format of zipfile:///<pwd>/.yarn/...
        return str.replace(/^zipfile:\/\//, ``);
      } break;

      case `vscode`:
      default: {
        return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
      } break;
    }
  }

  // Force enable 'allowLocalPluginLoads'
  // TypeScript tries to resolve plugins using a path relative to itself
  // which doesn't work when using the global cache
  // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
  // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
  // TypeScript already does local loads and if this code is running the user trusts the workspace
  // https://github.com/microsoft/vscode/issues/45856
  const ConfiguredProject = tsserver.server.ConfiguredProject;
  const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
  ConfiguredProject.prototype.enablePluginsWithOptions = function() {
    this.projectService.allowLocalPluginLoads = true;
    return originalEnablePluginsWithOptions.apply(this, arguments);
  };

  // And here is the point where we hijack the VSCode <-> TS communications
  // by adding ourselves in the middle. We locate everything that looks
  // like an absolute path of ours and normalize it.

  const Session = tsserver.server.Session;
  const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
  let hostInfo = `unknown`;

  Object.assign(Session.prototype, {
    onMessage(/** @type {string | object} */ message) {
      const isStringMessage = typeof message === 'string';
      const parsedMessage = isStringMessage ? JSON.parse(message) : message;

      if (
        parsedMessage != null &&
        typeof parsedMessage === `object` &&
        parsedMessage.arguments &&
        typeof parsedMessage.arguments.hostInfo === `string`
      ) {
        hostInfo = parsedMessage.arguments.hostInfo;
        if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
          const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
            // The RegExp from https://semver.org/ but without the caret at the start
            /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
          ) ?? []).map(Number)

          if (major === 1) {
            if (minor < 61) {
              hostInfo += ` <1.61`;
            } else if (minor < 66) {
              hostInfo += ` <1.66`;
            } else if (minor < 68) {
              hostInfo += ` <1.68`;
            }
          }
        }
      }

      const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
        return typeof value === 'string' ? fromEditorPath(value) : value;
      });

      return originalOnMessage.call(
        this,
        isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
      );
    },

    send(/** @type {any} */ msg) {
      return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
        return typeof value === `string` ? toEditorPath(value) : value;
      })));
    }
  });

  return tsserver;
};

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/lib/tsserver.js
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/lib/tsserver.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));


================================================
FILE: .yarn/sdks/typescript/lib/tsserverlibrary.js
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

const moduleWrapper = tsserver => {
  if (!process.versions.pnp) {
    return tsserver;
  }

  const {isAbsolute} = require(`path`);
  const pnpApi = require(`pnpapi`);

  const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
  const isPortal = str => str.startsWith("portal:/");
  const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);

  const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
    return `${locator.name}@${locator.reference}`;
  }));

  // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
  // doesn't understand. This layer makes sure to remove the protocol
  // before forwarding it to TS, and to add it back on all returned paths.

  function toEditorPath(str) {
    // We add the `zip:` prefix to both `.zip/` paths and virtual paths
    if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
      // We also take the opportunity to turn virtual paths into physical ones;
      // this makes it much easier to work with workspaces that list peer
      // dependencies, since otherwise Ctrl+Click would bring us to the virtual
      // file instances instead of the real ones.
      //
      // We only do this to modules owned by the the dependency tree roots.
      // This avoids breaking the resolution when jumping inside a vendor
      // with peer dep (otherwise jumping into react-dom would show resolution
      // errors on react).
      //
      const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
      if (resolved) {
        const locator = pnpApi.findPackageLocator(resolved);
        if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
          str = resolved;
        }
      }

      str = normalize(str);

      if (str.match(/\.zip\//)) {
        switch (hostInfo) {
          // Absolute VSCode `Uri.fsPath`s need to start with a slash.
          // VSCode only adds it automatically for supported schemes,
          // so we have to do it manually for the `zip` scheme.
          // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
          //
          // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
          //
          // 2021-10-08: VSCode changed the format in 1.61.
          // Before | ^zip:/c:/foo/bar.zip/package.json
          // After  | ^/zip//c:/foo/bar.zip/package.json
          //
          // 2022-04-06: VSCode changed the format in 1.66.
          // Before | ^/zip//c:/foo/bar.zip/package.json
          // After  | ^/zip/c:/foo/bar.zip/package.json
          //
          // 2022-05-06: VSCode changed the format in 1.68
          // Before | ^/zip/c:/foo/bar.zip/package.json
          // After  | ^/zip//c:/foo/bar.zip/package.json
          //
          case `vscode <1.61`: {
            str = `^zip:${str}`;
          } break;

          case `vscode <1.66`: {
            str = `^/zip/${str}`;
          } break;

          case `vscode <1.68`: {
            str = `^/zip${str}`;
          } break;

          case `vscode`: {
            str = `^/zip/${str}`;
          } break;

          // To make "go to definition" work,
          // We have to resolve the actual file system path from virtual path
          // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
          case `coc-nvim`: {
            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
            str = resolve(`zipfile:${str}`);
          } break;

          // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
          // We have to resolve the actual file system path from virtual path,
          // everything else is up to neovim
          case `neovim`: {
            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
            str = `zipfile://${str}`;
          } break;

          default: {
            str = `zip:${str}`;
          } break;
        }
      } else {
        str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
      }
    }

    return str;
  }

  function fromEditorPath(str) {
    switch (hostInfo) {
      case `coc-nvim`: {
        str = str.replace(/\.zip::/, `.zip/`);
        // The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
        // So in order to convert it back, we use .* to match all the thing
        // before `zipfile:`
        return process.platform === `win32`
          ? str.replace(/^.*zipfile:\//, ``)
          : str.replace(/^.*zipfile:/, ``);
      } break;

      case `neovim`: {
        str = str.replace(/\.zip::/, `.zip/`);
        // The path for neovim is in format of zipfile:///<pwd>/.yarn/...
        return str.replace(/^zipfile:\/\//, ``);
      } break;

      case `vscode`:
      default: {
        return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
      } break;
    }
  }

  // Force enable 'allowLocalPluginLoads'
  // TypeScript tries to resolve plugins using a path relative to itself
  // which doesn't work when using the global cache
  // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
  // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
  // TypeScript already does local loads and if this code is running the user trusts the workspace
  // https://github.com/microsoft/vscode/issues/45856
  const ConfiguredProject = tsserver.server.ConfiguredProject;
  const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
  ConfiguredProject.prototype.enablePluginsWithOptions = function() {
    this.projectService.allowLocalPluginLoads = true;
    return originalEnablePluginsWithOptions.apply(this, arguments);
  };

  // And here is the point where we hijack the VSCode <-> TS communications
  // by adding ourselves in the middle. We locate everything that looks
  // like an absolute path of ours and normalize it.

  const Session = tsserver.server.Session;
  const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
  let hostInfo = `unknown`;

  Object.assign(Session.prototype, {
    onMessage(/** @type {string | object} */ message) {
      const isStringMessage = typeof message === 'string';
      const parsedMessage = isStringMessage ? JSON.parse(message) : message;

      if (
        parsedMessage != null &&
        typeof parsedMessage === `object` &&
        parsedMessage.arguments &&
        typeof parsedMessage.arguments.hostInfo === `string`
      ) {
        hostInfo = parsedMessage.arguments.hostInfo;
        if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
          const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
            // The RegExp from https://semver.org/ but without the caret at the start
            /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
          ) ?? []).map(Number)

          if (major === 1) {
            if (minor < 61) {
              hostInfo += ` <1.61`;
            } else if (minor < 66) {
              hostInfo += ` <1.66`;
            } else if (minor < 68) {
              hostInfo += ` <1.68`;
            }
          }
        }
      }

      const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
        return typeof value === 'string' ? fromEditorPath(value) : value;
      });

      return originalOnMessage.call(
        this,
        isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
      );
    },

    send(/** @type {any} */ msg) {
      return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
        return typeof value === `string` ? toEditorPath(value) : value;
      })));
    }
  });

  return tsserver;
};

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/lib/tsserverlibrary.js
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/lib/tsserverlibrary.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));


================================================
FILE: .yarn/sdks/typescript/lib/typescript.js
================================================
#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../../.pnp.cjs";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require typescript/lib/typescript.js
    require(absPnpApiPath).setup();
  }
}

// Defer to the real typescript/lib/typescript.js your application uses
module.exports = absRequire(`typescript/lib/typescript.js`);


================================================
FILE: .yarn/sdks/typescript/package.json
================================================
{
  "name": "typescript",
  "version": "5.0.4-sdk",
  "main": "./lib/typescript.js",
  "type": "commonjs"
}


================================================
FILE: COPYING
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: COPYING.LESSER
================================================
                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.


================================================
FILE: DEVELOPMENT.md
================================================
# 开发文档

此文档包含了插件开发文档(插件清单规范 v2.0)。

**在开始之前,强烈建议你使用我们的[插件模板仓库](https://github.com/Flysoft-Studio/QQNTim-Plugin-Template)进行开发。** 模板仓库已经包含了 TypeScript 类型定义、自动构建及发布等内容,无需手动配置。

## 文件结构

### 数据文件夹

请查看 [使用手册-数据文件夹](MANUAL.md#数据文件夹) 查看默认的数据文件夹路径及其修改方式。

数据文件夹存放了所有插件和设置。

以下是一个结构示意图:

```
QQNTim
  ├─ plugins
  ├─ plugins-user
  └─ config.json
```

### `plugins` 文件夹

存放所有插件的文件夹。在此文件夹下的插件**对所有账户都生效**。

以下是一个结构示意图:

```
plugins
  ├─ 插件1 (文件夹)
  │  ├─ qqntim.json
  │  ├─ renderer.js
  │  └─ style.css
  └─ 插件2 (文件夹)
     ├─ qqntim.json
     ├─ main.js
     ├─ renderer.js
     ├─ example.jpg
     └─ native.node
```

### `plugins-user` 文件夹

存放指定账户插件的文件夹。在此文件夹下的插件**只对指定账户生效**。

以下是一个结构示意图:

```
plugins-user
  ├─ 10000
  │  ├─ 插件1
  │  └─ 插件2
  └─ 10001
     └─ ...
```

### `config.json` 文件

存放 QQNTim 配置的文件。

一个示例配置文件如下所示:

```json
{
    // (可选) 插件加载相关设置
    "plugins": {
        // 插件加载黑、白名单
        // (应指定插件的 ID,可以在插件的 qqntim.json 内的 id 栏查看)
        // ----------------------------------------------------
        // (string[] 可选) 插件加载白名单
        "whitelist": [],
        // (string[] 可选) 插件加载黑名单
        "blacklist": ["mica", "mica-ui"]
        // ----------------------------------------------------
    }
}
```

## 插件文件夹

插件文件夹存放了所有插件和设置。

### `qqntim.json` 文件

存放插件信息的清单文件,包含了插件的基本信息、插件加载条件、要注入的 [JS 脚本](#js-文件)等。

类型:[Manifest](#manifest)

一个完整的示例如下:

```json
{
    "manifestVersion": "2.0",
    "id": "my-plugin",
    "name": "我的插件",
    "author": "Flysoft",
    "requirements": {
        "os": [
            {
                "platform": "win32",
                "lte": "10.0.22621",
                "gte": "6.1.0"
            }
        ]
    },
    "injections": [
        {
            "type": "main",
            "script": "main.js"
        },
        {
            "type": "renderer",
            "page": ["main", "chat"],
            "script": "main.js",
            "stylesheet": "style.css"
        }
    ]
}
```

### `*.js` 文件

脚本入口文件。

#### 主进程脚本

该脚本必须使用 CommonJS 标准默认导出一个实现 [`QQNTim.Entry.Main`](src/typings/index.d.ts) 的类。

一个示例如下:

```typescript
import { QQNTim } from "@flysoftbeta/qqntim-typings";
// 例子:QQNT 启动时显示一条 Hello world! 控制台信息
// `qqntim` 内包含了很多实用的 API,可以帮助你对 QQNT 做出修改
export default class Entry implements QQNTim.Entry.Main {
    constructor(qqntim: QQNTim.API.Main.API) {
        console.log("Hello world!", qqntim);
    }
}
```

#### 渲染进程脚本

该脚本必须使用 CommonJS 标准默认导出一个实现 `QQNTim.Entry.Renderer` 的类。

一个示例如下:

```typescript
import { QQNTim } from "@flysoftbeta/qqntim-typings";
// 例子:QQNT 启动时显示一条 Hello world! 控制台信息
// `qqntim` 内包含了很多实用的 API,可以帮助你对 QQNT 做出修改
export default class Entry implements QQNTim.Entry.Renderer {
    constructor(qqntim: QQNTim.API.Renderer.API) {
        console.log("Hello world!", qqntim);
    }
}
```

## 类型定义

请查看 QQNTim 的 [TypeScript 类型定义文件](src/typings/index.d.ts)。此类型定义可通过安装 NPM 包 `@flysoftbeta/qqntim-typings` 添加到你的项目中。


================================================
FILE: MANUAL.md
================================================
# 使用手册

此文档包含了使用教程。

## 已知支持的 QQNT 版本

| 操作系统 | 最高版本 | 最低版本 |
| -------- | -------- | -------- |
| Windows  | 9.9.1    | 9.8.0    |
| Linux    | 3.1.2    | 3.0.0    |
| macOS    | 6.9.17 (12118)     | 6.9.12 (10951)     |

## 安装

**请务必仔细阅读本章节内容以避免不必要的麻烦!**

QQNTim 支持 LiteLoader,但**不支持 BetterQQNT**。

> ### LiteLoader 相关安装教程:
>
> #### 如果你已经安装了 LiteLoader,想安装 QQNTim:
>
> 1. **确保 LiteLoader 文件夹名称为 `LiteLoader` 或 `LiteLoaderQQNT`。否则 LiteLoader 将不会被加载!**
>
> 2. 到 `QQNT 根目录/resources/app` 下修改 `package.json`,将 `"LiteLoader"` 修改为 `"./app_launcher/index.js"`,之后再运行 QQNTim 的安装脚本即可。
>
> #### 如果你已经安装了 QQNTim,想安装 LiteLoader:
>
> 请遵循 [LiteLoader 官方安装教程](https://github.com/mo-jinran/LiteLoaderQQNT/blob/main/README.md#安装方法) 进行安装即可,但请注意以下两点:
>
> 1. **确保 LiteLoader 文件夹名称为 `LiteLoader` 或 `LiteLoaderQQNT`。否则 LiteLoader 将不会被加载!**
>
> 2. **不要按照教程中的方法修改 `package.json`!否则 QQNTim 将不会加载。你只需保持它原样即可。**

安装前请确保电脑上已经安装了 QQNT。

如果你正在使用的是 **[不支持的 QQNT 版本](#已知支持的-qqnt-版本)、发现 QQNTim 无法正常使用且希望申请适配**,请通过 [附录-显示终端日志](#显示终端日志) 中提供的方法收集日志,并[向我们**提交此问题**](https://github.com/Flysoft-Studio/QQNTim/issues)。

请先从 [Releases](https://github.com/Flysoft-Studio/QQNTim/releases) 中下载最新的版本(对于一般用户,建议下载 `qqntim-build.zip`),下载后,请确保你**解压了所有文件(必须包含 `_` 文件夹)**!

在 Windows 下,请运行 `install.cmd` 安装或运行 `uninstall.cmd` 卸载。

在 Linux 下,请在安装文件夹下运行:

```bash
# 安装
chmod +x ./install.sh
./install.sh
# 卸载
chmod +x ./uninstall.sh
./uninstall.sh
```
在 macOS 下,打开 `终端.app` 执行以下操作:

```zsh
# 安装
chmod +x <install_macos.sh>    <----将 install_macos.sh 文件拖进终端窗口后按回车运行
<install_macos.sh>             <----将 install_macos.sh 文件拖进终端窗口后按回车运行
# 卸载
chmod +x <uninstall_macos.sh>    <----将 uninstall_macos.sh 文件拖进终端窗口后按回车运行
<uninstall_macos.sh>             <----将 uninstall_macos.sh 文件拖进终端窗口后按回车运行
```
需要输入管理员密码鉴权,同时在弹出的通知中选择允许终端修改App,或前往 `系统设置->隐私与安全性->App管理` 中打开/添加 `终端` 来允许终端修改文件。

安装后,打开 "设置" 页面:

![设置入口](.github/settings-entry.png)

如果左侧菜单出现 "QQNTim 设置",即代表安装成功:

![QQNTim 设置页面](.github/qqntim-settings-page.png)

如果此项目并未按预期出现,则可能代表 QQNTim 安装没有成功,或 QQNTim 加载失败。请通过 [附录-显示终端日志](#显示终端日志) 中提供的方法收集日志,并[向我们**提交此问题**](https://github.com/Flysoft-Studio/QQNTim/issues)。

## 插件管理

### 获取插件

**[Plugins Galaxy](https://github.com/FlysoftBeta/QQNTim-Plugins-Galaxy) 中拥有很多功能丰富的插件,欢迎下载。**

支持 QQNTim 3.0 及以上版本的插件:

| 名称                                                                                                     | 说明                                                  | 作者                                         |
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------- |
| [QQNTim-Plugin-Markdown](https://github.com/Flysoft-Studio/QQNTim-Plugin-Markdown)                       | 显示 Markdown 消息/LaTeX 渲染插件                     | [Flysoft](https://github.com/Flysoft-Studio) |
| [QQNTim-Plugin-Wallpaper](https://github.com/Flysoft-Studio/QQNTim-Plugin-Wallpaper)                     | 自定义你的壁纸                                        | [Flysoft](https://github.com/Flysoft-Studio) |
| [QQNTim-Plugin-No-Revoked-Messages](https://github.com/Flysoft-Studio/QQNTim-Plugin-No-Revoked-Messages) | 支持消息持久化保存的防撤回插件                        | [Flysoft](https://github.com/Flysoft-Studio) |
| [QQNTim-Plugins-Galaxy](https://github.com/FlysoftBeta/QQNTim-Plugins-Galaxy)                            | 插件商城(注意:只有 GaussianUI 插件支持 QQNTim 3.0) | [Flysoft](https://github.com/Flysoft-Studio) |

仅支持 QQNTim 2.2 及以下版本的插件:

| 名称                                                                          | 说明                                                   | 作者                                         |
| ----------------------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------- |
| [QQNTim-Plugin-NTHttp](https://github.com/Rei1mu/QQNTim-Plugin-NTHttp)        | WebSocket+Http 的通信实现                              | [Rei1mu](https://github.com/Rei1mu)          |
| [QQNTim-Plugin-NoUpdate](https://github.com/Rei1mu/QQNTim-Plugin-NoUpdate)    | 取消提示自动更新的烦人弹窗                             | [Rei1mu](https://github.com/Rei1mu)          |
| [QQNTim-Plugins-Galaxy](https://github.com/FlysoftBeta/QQNTim-Plugins-Galaxy) | 插件商城(注意:壁纸插件不支持 QQNTim 2.2 及以下版本) | [Flysoft](https://github.com/Flysoft-Studio) |

### 安装插件

要安装插件,请准备一个插件**压缩包 (.zip) 或文件夹**。

结构如下图所示(每个插件结构各不相同,这里提供的结构图仅供参考):

```
我的插件
  ├─ qqntim.json
  ├─ renderer.js
  ├─ style.css
  └─ ...
```

打开 "设置" 页面,选中 "插件管理":

![插件管理页面](.github/qqntim-plugin-management-page.png)

如果你登录了多个 QQ 账户,且希望某个插件只对当前账户生效,那么请点击 "仅对账号 [你的 QQ 号] 生效的插件" 右侧的安装按钮。

如果你希望插件对所有账户生效,那么请点击 "对所有账号生效的插件" 右侧的安装按钮进行安装。

**_注意:根据提示选择插件相关文件安装后,你可能需要重启 QQ 才能使这些插件开始生效。_**

安装插件后,如果插件没有按预期正常工作,请通过 [附录-显示终端日志](#显示终端日志) 中提供的方法收集日志,并向插件作者提交此问题。

### 管理现有插件

打开 "设置" 页面,选中 "插件管理":

![插件管理页面](.github/qqntim-plugin-management-page.png)

目前,你可以启用、禁用或删除插件。

**_注意:修改设置之后需要点击 "保存并重启" 才能使设置生效。_**

## 数据文件夹

数据文件夹存放了所有插件和设置。

在 Windows 下,默认数据文件夹位于 `%UserProfile%/.qqntim`(例如:`C:/Users/[你的用户名]/.qqntim`)。

在 Linux 下,默认数据文件夹位于 `$HOME/.local/share/QQNTim`(例如:`/home/[你的用户名]/.local/share/QQNTim`,可能需要启用**显示隐藏文件**选项才能显示出来)。

你可以修改 `QQNTIM_HOME` 环境变量以修改数据文件夹的位置。

## 附录

### 显示终端日志

#### 在 Windows 下显示终端日志

1. 桌面右键 QQ 图标,点击 "打开文件所在位置"。
2. 在出现的文件夹窗口内按住 `Shift` 右键,点击 "在此处打开命令窗口" 或 "在此处打开 PowerShell 窗口"。
3. 在弹出的控制台窗口内输入 ".\QQ.exe" 并按下 `Enter`。
4. 日志信息将会出现在控制台窗口内。

#### 在 GNOME (Linux) 下显示终端日志

1. 按两次 `Super` 键,打开 "所有应用"。
2. 输入 "终端",并按下 `Enter`。
3. 在弹出的控制台窗口内输入 "linuxqq ; qq" 并按下 `Enter`。
4. 日志信息将会出现在控制台窗口内。

#### 在 KDE (Linux) 下显示终端日志

1. 按一次次 `Super` 键,打开 "KDE 菜单"。
2. 输入 "Konsole",并按下 `Enter`。
3. 在弹出的控制台窗口内输入 "linuxqq ; qq" 并按下 `Enter`。
4. 日志信息将会出现在控制台窗口内。


================================================
FILE: README.md
================================================
# QQNT-Improved - PC 端 QQNT 插件管理器

此项目已废弃,我们正在全力开发全新 QQ 客户端——QPlugged,敬请期待。

[![Maintainability](https://api.codeclimate.com/v1/badges/bb8c6d1f5c2647ae38e8/maintainability)](https://codeclimate.com/github/Flysoft-Studio/QQNTim/maintainability) [![License](https://img.shields.io/github/license/FlysoftBeta/QQNTim)](https://github.com/Flysoft-Studio/QQNTim/blob/dev/COPYING.LESSER) [![Build](https://img.shields.io/github/actions/workflow/status/Flysoft-Studio/QQNTim/build.yml)](https://github.com/Flysoft-Studio/QQNTim/actions/workflows/build.yml)

![截图](.github/screenshot.png)

<!-- **注意:** 我们注意到 QQNT (Windows) 最近在进行大幅度修改。为了防止我们的前功尽弃,我们将适当减小更新频率。 -->

QQNT-Improved (简称 QQNTim) 是一个给 QQNT 的插件管理器,目前处于 Alpha 版本阶段,支持 Windows,Linux 等平台 (macOS 未测试,不保证可用性)。

本程序**不提供任何担保**(包括但不限于使用导致的系统故障、封号等)。

Telegram 群组:<https://t.me/qqntim>,欢迎加入。

> QQNTim 可以与 **[LiteLoaderQQNT](https://github.com/mo-jinran/LiteLoaderQQNT)** 并存,快去试试吧!
>
> 请阅读 [使用手册-安装](MANUAL.md#安装) 查看如何安装。

## 安装与使用

请查看我们的[使用手册](MANUAL.md)。

## 插件开发

请查看我们的[开发文档](DEVELOPMENT.md)。

## 协议

本程序使用 GNU Lesser General Public License v3.0 or later 协议发行。

请在此源代码树下的 [COPYING](./COPYING) 和 [COPYING.LESSER](./COPYING.LESSER) 查看完整的协议。


================================================
FILE: build.ts
================================================
import { BuildOptions, build } from "esbuild";
import { copy, emptyDir, ensureDir, readdir, writeFile } from "fs-extra";
import { dirname, sep as s } from "path";
import { getAllLocators, getPackageInformation } from "pnpapi";

type Package = {
    packageLocation: string;
    packageDependencies: Map<string, string>;
};
type Packages = Record<string, Record<string, Package>>;

const unpackedPackages = ["chii"];
const junkFiles = [
    ".d.ts",
    ".markdown",
    ".md",
    "/.eslintrc",
    "/.eslintrc.js",
    "/.prettierrc",
    "/.nycrc",
    ".yml",
    ".yaml",
    ".bak",
    "/.editorconfig",
    "/bower.json",
    "/.jscs.json",
    "/AUTHORS",
    "/LICENSE",
    "/License",
    "/yarn.lock",
    "/package-lock.json",
    ".map",
    ".debug.js",
    ".min.js",
    ".test.js",
    "/test/",
    "/bin/",
    "/tests/",
    "/.github/",
];

const isProduction = process.env["NODE_ENV"] == "production";
const commonOptions: Partial<BuildOptions> = {
    target: "node18",
    bundle: true,
    platform: "node",
    write: true,
    allowOverwrite: true,
    sourcemap: isProduction ? false : "inline",
    minify: isProduction,
    treeShaking: isProduction,
};

async function buildBundles() {
    const buildPromise = Promise.all([
        build({
            ...commonOptions,
            entryPoints: [`src${s}main${s}main.ts`],
            outfile: `dist${s}_${s}qqntim.js`,
            external: ["electron", "./index.js", ...unpackedPackages],
        }),
        build({
            ...commonOptions,
            entryPoints: [`src${s}renderer${s}main.ts`],
            outfile: `dist${s}_${s}qqntim-renderer.js`,
            external: ["electron", ...unpackedPackages],
        }),
    ]);

    return await buildPromise;
}

async function buildBuiltinPlugins() {
    const rootDir = `src${s}builtins`;
    const pluginsDir = await readdir(rootDir);
    await Promise.all(
        pluginsDir.map(async (dir) => {
            const pluginDir = `${rootDir}${s}${dir}`;
            const distDir = `dist${s}_${s}builtins${s}${dir}`;
            await ensureDir(pluginDir);
            await build({
                ...commonOptions,
                entryPoints: [`${pluginDir}${s}src${s}main.ts`, `${pluginDir}${s}src${s}renderer.ts`],
                outdir: distDir,
                external: ["electron", "react", "react/jsx-runtime", "react-dom", "react-dom/client", "qqntim/main", "qqntim/renderer"],
                format: "cjs",
            });
            await copy(`${pluginDir}${s}publish`, `${distDir}`);
        }),
    );
}

async function prepareDistDir() {
    await emptyDir("dist");
    await ensureDir(`dist${s}_`);
    await copy("publish", "dist");
}

function collectDeps() {
    const packages: Packages = {};
    getAllLocators().forEach((locator) => {
        if (!packages[locator.name]) packages[locator.name] = {};
        packages[locator.name][locator.reference] = getPackageInformation(locator);
    });
    return packages;
}

async function unpackPackage(packages: Packages, rootDir: string, name: string, reference?: string) {
    const item = packages[name];
    if (!item) return;
    const location = item[reference ? reference : Object.keys(item)[0]];
    const dir = `${rootDir}${s}node_modules${s}${name}`;
    await ensureDir(dir);
    await copy(location.packageLocation, dir, {
        filter: (src) => {
            for (const file of junkFiles) {
                if (src.includes(file)) return false;
            }
            return true;
        },
    });
    const promises: Promise<void>[] = [];
    location.packageDependencies.forEach((depReference, depName) => {
        if (name == depName) return;
        promises.push(unpackPackage(packages, dir, depName, depReference));
    });
    await Promise.all(promises);
}

const packages = collectDeps();
prepareDistDir().then(() => Promise.all([buildBundles(), buildBuiltinPlugins(), Promise.all(unpackedPackages.map((unpackedPackage) => unpackPackage(packages, `dist${s}_`, unpackedPackage)))]));


================================================
FILE: examples/NT-API/consts.js
================================================
module.exports = {
    id: "example-nt-api",
    defaults: {
        showAccountInfo: true,
        showHistoryMessages: true,
        historyMessageObject: "both",
        autoReply: true,
        testInputValue: "默认值",
    },
};


================================================
FILE: examples/NT-API/qqntim.json
================================================
{
    "manifestVersion": "3.0",
    "id": "example-nt-api",
    "name": "示例插件:NT API",
    "author": "Flysoft",
    "injections": [{ "type": "renderer", "script": "renderer.js", "page": "main" }, { "type": "renderer", "script": "settings.js", "page": "settings" }]
}


================================================
FILE: examples/NT-API/renderer.js
================================================
const path = require("path");
const qqntim = require("qqntim/renderer");
const { id, defaults } = require("./consts");

module.exports.default = class Entry {
    constructor() {
        const config = qqntim.env.config.plugins?.config?.[id];
        const showAccountInfo = config?.showAccountInfo != undefined ? config.showAccountInfo : defaults.showAccountInfo;
        const historyMessageObject = config?.historyMessageObject != undefined ? config.historyMessageObject : defaults.historyMessageObject;
        const showHistoryMessages = config?.showHistoryMessages != undefined ? config.showHistoryMessages : defaults.showHistoryMessages;
        const autoReply = config?.autoReply != undefined ? config.autoReply : defaults.autoReply;
        const testInputValue = config?.testInputValue != undefined ? config.testInputValue : defaults.testInputValue;

        //#region 示例:获取当前账号
        if (showAccountInfo)
            qqntim.nt.getAccountInfo().then((account) => {
                console.log("[Example-NT-API] 当前账号信息", account);
            });
        //#endregion

        //#region 示例:获取好友和群的最近 20 条历史消息
        if (showHistoryMessages) {
            if (historyMessageObject == "friends" || historyMessageObject == "both")
                qqntim.nt.getFriendsList().then((list) => {
                    console.log("[Example-NT-API] 好友列表", list);
                    list.forEach((friend) => qqntim.nt.getPreviousMessages({ chatType: "friend", uid: friend.uid }, 20).then((messages) => qqntim.nt.getUserInfo(friend.uid).then((user) => console.log("[Example-NT-API] 好友", user, "的最近 20 条消息:", messages))));
                });
            if (historyMessageObject == "groups" || historyMessageObject == "both")
                qqntim.nt.getGroupsList().then((list) => {
                    console.log("[Example-NT-API] 群组列表", list);
                    list.forEach((group) => qqntim.nt.getPreviousMessages({ chatType: "group", uid: group.uid }, 20).then((messages) => console.log(`[Example-NT-API] 群组 ${group.name} (${group.uid}) 的最近 20 条消息:`, messages)));
                });
        }
        //#endregion

        //#region 示例:自动回复
        if (autoReply)
            qqntim.nt.on("new-messages", (messages) => {
                console.log("[Example-NT-API] 收到新消息:", messages);
                messages.forEach((message) => {
                    if (message.peer.chatType != "friend") return;
                    message.allDownloadedPromise.then(() => {
                        qqntim.nt
                            .sendMessage(message.peer, [
                                {
                                    type: "text",
                                    content: "收到一条来自好友的消息:",
                                },
                                ...message.elements,
                                {
                                    type: "text",
                                    content: "(此消息两秒后自动撤回)\n示例图片:",
                                },
                                // 附带一个插件目录下的 example.jpg 作为图片发送
                                {
                                    type: "image",
                                    file: path.join(__dirname, "example.jpg"),
                                },
                            ])
                            .then((id) => {
                                setTimeout(() => {
                                    qqntim.nt.revokeMessage(message.peer, id);
                                }, 2000);
                            });
                    });
                });
            });
        //#endregion

        console.log("[Example-NT-API] 测试消息:", testInputValue);
    }
};


================================================
FILE: examples/NT-API/settings.js
================================================
const { Fragment, createElement } = require("react");
const { defineSettingsPanels } = require("qqntim-settings");
const { SettingsSection, SettingsBox, SettingsBoxItem, Switch, Input, Dropdown } = require("qqntim-settings/components");
const { id, defaults } = require("./consts");

function SettingsPanel({ config, setConfig }) {
    return createElement(
        Fragment,
        undefined,
        createElement(
            SettingsSection,
            { title: "插件设置" },
            createElement(
                SettingsBox,
                undefined,
                createElement(
                    SettingsBoxItem,
                    { title: "显示账户信息", description: ["在控制台中显示当前登录的账户信息。"] },
                    createElement(Switch, {
                        checked: config?.[id]?.showAccountInfo != undefined ? config?.[id]?.showAccountInfo : defaults.showAccountInfo,
                        onToggle: (state) =>
                            setConfig((prev) => {
                                return {
                                    ...(prev || {}),
                                    [id]: {
                                        ...(prev[id] || {}),
                                        showAccountInfo: state,
                                    },
                                };
                            }),
                    }),
                ),
                createElement(
                    SettingsBoxItem,
                    { title: "显示历史消息", description: ["在控制台中显示历史 20 条消息。"] },
                    createElement(Switch, {
                        checked: config?.[id]?.showHistoryMessages != undefined ? config?.[id]?.showHistoryMessages : defaults.showHistoryMessages,
                        onToggle: (state) =>
                            setConfig((prev) => {
                                return {
                                    ...(prev || {}),
                                    [id]: {
                                        ...(prev[id] || {}),
                                        showHistoryMessages: state,
                                    },
                                };
                            }),
                    }),
                ),
                (config?.[id]?.showHistoryMessages != undefined ? config?.[id]?.showHistoryMessages : defaults.showHistoryMessages) &&
                    createElement(
                        SettingsBoxItem,
                        { title: "获取历史消息的对象" },
                        createElement(Dropdown, {
                            items: [
                                ["friends", "好友"],
                                ["groups", "群"],
                                ["both", "好友和群"],
                            ],
                            selected: config?.[id]?.historyMessageObject != undefined ? config?.[id]?.historyMessageObject : defaults.historyMessageObject,
                            onChange: (state) =>
                                setConfig((prev) => {
                                    return {
                                        ...(prev || {}),
                                        [id]: {
                                            ...(prev[id] || {}),
                                            historyMessageObject: state,
                                        },
                                    };
                                }),
                            width: "150px",
                        }),
                    ),
                createElement(
                    SettingsBoxItem,
                    { title: "自动回复", description: ["自动回复私聊消息。"] },
                    createElement(Switch, {
                        checked: config?.[id]?.autoReply != undefined ? config?.[id]?.autoReply : defaults.autoReply,
                        onToggle: (state) =>
                            setConfig((prev) => {
                                return {
                                    ...(prev || {}),
                                    [id]: {
                                        ...(prev[id] || {}),
                                        autoReply: state,
                                    },
                                };
                            }),
                    }),
                ),
                createElement(
                    SettingsBoxItem,
                    { title: "测试", description: ["测试输入框。"], isLast: true },
                    createElement(Input, {
                        value: config?.[id]?.testInputValue != undefined ? config?.[id]?.testInputValue : defaults.testInputValue,
                        onChange: (state) =>
                            setConfig((prev) => {
                                return {
                                    ...(prev || {}),
                                    [id]: {
                                        ...(prev[id] || {}),
                                        testInputValue: state,
                                    },
                                };
                            }),
                    }),
                ),
            ),
        ),
    );
}

module.exports.default = class Entry {
    constructor() {
        defineSettingsPanels([
            "Example-NT-API 设置",
            SettingsPanel,
            `<svg viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.0005 15C17.8572 15 20.173 12.6842 20.173 9.82756C20.173 6.97092 17.8572 4.65515 15.0005 4.65515H10.188C10.0247 4.65515 10.2276 4.85861 10.3157 4.99608C10.5913 5.42594 11.1765 6.21463 10.654 7.02266C10.1314 7.83069 9.82812 8.79371 9.82812 9.82756C9.82812 12.6842 12.1439 15 15.0005 15Z" stroke="currentColor" stroke-width="1.75" stroke-linecap="square"></path><path d="M6.66406 24.3091C6.66406 21.2081 9.6191 18.1656 13.4146 18.1656C14.6987 18.1656 15.3023 18.1656 16.5864 18.1656C20.4854 18.1656 23.337 21.2081 23.337 24.3091C23.337 24.4334 23.2362 24.5341 23.1119 24.5341H6.88908C6.76481 24.5341 6.66406 24.4334 6.66406 24.3091Z" stroke="currentColor" stroke-width="1.75" stroke-linecap="square"></path></svg>`,
        ]);
    }
};


================================================
FILE: package.json
================================================
{
    "name": "qqnt-improved",
    "private": true,
    "version": "3.1.3",
    "license": "LGPL-3.0-or-later",
    "packageManager": "yarn@3.6.1",
    "workspaces": ["src/electron", "src/typings", "src/builtins/*"],
    "scripts": {
        "dev": "TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=development ts-node ./build.ts",
        "build:win": "TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=production ts-node ./build.ts && powershell -ExecutionPolicy Unrestricted -File ./scripts/pack.ps1",
        "build:linux": "TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=production ts-node ./build.ts && chmod +x ./scripts/pack.sh && ./scripts/pack.sh",
        "install:win": "QQNTIM_INSTALLER_NO_KILL_QQ=1 cmd /c start \"\" /wait cmd /c dist\\\\install.cmd",
        "install:linux": "chmod +x ./dist/install.sh && QQNTIM_INSTALLER_NO_KILL_QQ=1 ./dist/install.sh",
        "start:win": "powershell -ExecutionPolicy Unrestricted -File ./scripts/start.ps1",
        "start:linux": "chmod +x ./scripts/start.sh && ./scripts/start.sh",
        "lint": "tsc && rome check .",
        "lint:apply": "rome check . --apply",
        "lint:apply-unsafe": "rome check . --apply-unsafe",
        "format": "rome format . --write"
    },
    "dependencies": {
        "@electron/remote": "^2.0.11",
        "@flysoftbeta/qqntim-typings": "workspace:*",
        "axios": "^1.5.0",
        "chii": "^1.9.0",
        "electron": "workspace:*",
        "fs-extra": "^11.1.1",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "semver": "^7.5.4",
        "supports-color": "^9.4.0"
    },
    "devDependencies": {
        "@types/fs-extra": "^11.0.1",
        "@types/node": "^20.6.2",
        "@types/react": "^18.2.21",
        "@types/react-dom": "^18.2.7",
        "@types/semver": "^7.5.2",
        "@yarnpkg/sdks": "^3.0.0-rc.50",
        "esbuild": "^0.19.2",
        "rome": "12.1.3",
        "ts-node": "^10.9.1",
        "typed-emitter": "^2.1.0",
        "typescript": "^5.2.2"
    }
}


================================================
FILE: publish/_/install.ps1
================================================
$ErrorActionPreference = "Stop"

$Host.UI.RawUI.WindowTitle = "QQNTim 安装程序 (PowerShell)"
Set-Location (Split-Path -Parent $MyInvocation.MyCommand.Definition)
$CD = (Get-Location).Path

# 判断是否拥有管理员权限
if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
    if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
        throw "权限不足。" 
    }
}

# 从注册表获取 QQ 安装路径
foreach ($RegistryPath in @("HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*")) {
    try {
        foreach ($Item in (Get-ItemProperty $RegistryPath)) {
            if ($Item.PSChildName -eq "QQ") {
                $QQInstallDir = (Split-Path -Parent $Item.UninstallString)
                break
            }
        }
    }
    catch {}
}

if (($null -eq $QQInstallDir) -or ((Test-Path $QQInstallDir) -eq $false)) {
    throw "未找到 QQNT 安装目录。"
}

$QQExecutableFile = "$QQInstallDir\QQ.exe"
$QQExecutableBackupFile = "$QQInstallDir\QQ.exe.bak"
$QQExecutableHashFile = "$QQInstallDir\QQ.exe.md5"
$QQAppDir = "$QQInstallDir\resources\app"
$QQAppLauncherDir = "$QQAppDir\app_launcher"
$PackageJSONFile = "$QQAppDir\package.json"
$QQNTimFlagFile = "$QQAppLauncherDir\qqntim-flag.txt"
$SuccessFlagFile = "$env:TEMP\qqntim-install-successful.tmp"

# 清理旧版文件,恢复被修改的入口文件
if ((Test-Path "$QQAppLauncherDir\index.js.bak") -eq $true) {
    Write-Output "正在清理旧版 QQNTim……"
    Move-Item "$QQAppLauncherDir\index.js.bak" "$QQAppLauncherDir\index.js" -Force
    "" | Out-File $QQNTimFlagFile -Encoding UTF8 -Force
}

# 询问用户,如果存在旧版则不提示
if ((Test-Path $QQNTimFlagFile) -eq $false) {
    if ((Read-Host "是否要安装 QQNTim (y/n)?") -notcontains "y") {
        throw "安装已被用户取消。"
    }
}
else {
    Write-Output "检测到已有安装,正在更新……"
}

if ($env:QQNTIM_INSTALLER_NO_KILL_QQ -ne "1") {
    Write-Output "正在关闭 QQ……"
    Stop-Process -Name QQ -ErrorAction SilentlyContinue
}

Write-Output "正在复制文件……"
# 如果 node_modules 不存在或已经过期则执行复制
if ((Test-Path .\node_modules.zip.md5) -eq $true -and (Test-Path .\node_modules.zip) -eq $true) {
    if ((Test-Path "$QQAppLauncherDir\node_modules.zip.md5") -eq $false -or (Get-Content "$QQAppLauncherDir\node_modules.zip.md5" -Encoding UTF8 -Force) -ne (Get-Content .\node_modules.zip.md5 -Encoding UTF8 -Force)) {
        $SourceZipPath = "$CD\node_modules.zip";
        $DestinationDirPath = "$QQAppLauncherDir\node_modules"
        # 清空原有 node_modules 文件夹
        if ((Test-Path $DestinationDirPath) -eq $true) {
            Remove-Item $DestinationDirPath -Recurse -Force
        }
        New-Item $DestinationDirPath -ItemType Directory -Force | Out-Null
        try {
            # 回退 1 - 仅支持 .NET Framework 4.5 及以上
            Add-Type -AssemblyName System.IO.Compression.Filesystem
            [System.IO.Compression.ZipFile]::ExtractToDirectory($SourceZipPath, $DestinationDirPath)
        }
        catch { 
            # 回退 2 - 使用系统 COM 复制 API
            $Shell = New-Object -ComObject Shell.Application
            $Shell.NameSpace($DestinationDirPath).CopyHere($Shell.NameSpace($SourceZipPath).Items())
        }
    }
    Copy-Item ".\node_modules.zip.md5" $QQAppLauncherDir -Recurse -Force
}
elseif ((Test-Path .\node_modules) -eq $true) {
    Copy-Item ".\node_modules" $QQAppLauncherDir -Recurse -Force
}
Copy-Item ".\qqntim.js", ".\qqntim-renderer.js", ".\builtins" $QQAppLauncherDir -Recurse -Force

Write-Output "正在修补 package.json……"
# 使用 UTF-8 without BOM 进行保存
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($PackageJSONFile, ((Get-Content $PackageJSONFile -Encoding UTF8 -Force) -replace "./app_launcher/index.js", "./app_launcher/qqntim.js"), $Utf8NoBomEncoding)

# For QQ 9.9.1+
# 如果 QQ.exe 未被修补或已被新安装覆盖则进行修补
if ((Test-Path $QQExecutableHashFile) -eq $false -or (Get-Content $QQExecutableHashFile -Encoding UTF8 -Force) -replace "`r`n", "" -ne (Get-FileHash $QQExecutableFile -Algorithm MD5).Hash) {
    Write-Output "正在修补 QQ.exe,这可能需要一些时间……"
    Copy-Item $QQExecutableFile $QQExecutableBackupFile -Force
    # 引入 crypt32.dll 定义
    $Crypt32Def = @"
[DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptStringToBinary(
    string pszString,
    int cchString,
    int dwFlags,
    byte[] pbBinary,
    ref int pcbBinary,
    int pdwSkip,
    ref int pdwFlags
);
[DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptBinaryToString(
    byte[] pbBinary,
    int cbBinary,
    int dwFlags,
    StringBuilder pszString,
    ref int pcchString
);
"@
    Add-Type -MemberDefinition $Crypt32Def -Namespace PKI -Name Crypt32 -UsingNamespace "System.Text"
    $HexRawEncoding = 12

    $QQBin = [System.IO.File]::ReadAllBytes($QQExecutableFile)
    # Byte[] 转 Hex String
    $pcchString = 0 # Size
    if ([PKI.Crypt32]::CryptBinaryToString($QQBin, $QQBin.Length, $HexRawEncoding, $null, [ref]$pcchString)) {
        $QQHex = New-Object Text.StringBuilder $pcchString
        [void][PKI.Crypt32]::CryptBinaryToString($QQBin, $QQBin.Length, $HexRawEncoding, $QQHex, [ref]$pcchString)
        $PatchedQQHex = $QQHex.ToString() -replace "7061636b6167652e6a736f6e00696e6465782e6a73006c61756e636865722e6a73006c61756e636865722e6e6f646500", "696e6465782e6a730000000000696e6465782e6a73006c61756e636865722e6a73006c61756e636865722e6e6f646500" -replace "7061636b6167652e488d942400020000488902c742086a736f6e", "6c61756e63686572488d942400020000488902c742082e6a7300"
        # Hex String 转 Byte[]
        $pcbBinary = 0 # Size
        $pdwFlags = 0
        if ([PKI.Crypt32]::CryptStringToBinary($PatchedQQHex, $PatchedQQHex.Length, $HexRawEncoding, $null, [ref]$pcbBinary, 0, [ref]$pdwFlags)) {
            $PatchedQQBin = New-Object byte[] -ArgumentList $pcbBinary
            [void][PKI.Crypt32]::CryptStringToBinary($PatchedQQHex, $PatchedQQHex.Length, $HexRawEncoding, $PatchedQQBin, [ref]$pcbBinary, 0, [ref]$pdwFlags)

            # 写出文件
            [System.IO.File]::WriteAllBytes($QQExecutableFile, $PatchedQQBin)

            # 写出 MD5
            $QQFileHash = (Get-FileHash $QQExecutableFile -Algorithm MD5).Hash
            [System.IO.File]::WriteAllLines($QQExecutableHashFile, $QQFileHash, $Utf8NoBomEncoding)
        }
        else {
            throw $((New-Object ComponentModel.Win32Exception ([Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message)
        }
    }
    else {
        throw $((New-Object ComponentModel.Win32Exception ([Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message)
    }
}
else {
    Write-Output "QQ.exe 未更新,无需修补!"
}

if ((Test-Path $QQNTimFlagFile) -eq $false) {
    "" | Out-File $QQNTimFlagFile -Encoding UTF8 -Force
}

if ((Test-Path $SuccessFlagFile) -eq $false) {
    "" | Out-File $SuccessFlagFile -Encoding UTF8 -Force
}

if ($env:QQNTIM_INSTALLER_NO_DELAYED_EXIT -ne "1") {
    Write-Output "安装成功。安装程序将在 5 秒后自动退出。"
    Start-Sleep -Seconds 5
}
else {
    Write-Output "安装成功。"
}

================================================
FILE: publish/_/uninstall.ps1
================================================
$ErrorActionPreference = "Stop"

$Host.UI.RawUI.WindowTitle = "QQNTim 卸载程序 (PowerShell)"
Set-Location (Split-Path -Parent $MyInvocation.MyCommand.Definition)

# 判断是否拥有管理员权限
if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
    if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
        throw "权限不足。" 
    }
}

# 从注册表获取 QQ 安装路径
foreach ($RegistryPath in @("HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*")) {
    try {
        foreach ($Item in (Get-ItemProperty $RegistryPath)) {
            if ($Item.PSChildName -eq "QQ") {
                $QQInstallDir = (Split-Path -Parent $Item.UninstallString)
                break
            }
        }
    }
    catch {}
}

if (($null -eq $QQInstallDir) -or ((Test-Path $QQInstallDir) -eq $false)) {
    throw "未找到 QQNT 安装目录。"
}

$QQExecutableFile = "$QQInstallDir\QQ.exe"
$QQExecutableBackupFile = "$QQInstallDir\QQ.exe.bak"
$QQExecutableHashFile = "$QQInstallDir\QQ.exe.md5"
$QQAppDir = "$QQInstallDir\resources\app"
$QQAppLauncherDir = "$QQAppDir\app_launcher"
$QQNTimFlagFile = "$QQAppLauncherDir\qqntim-flag.txt"
$SuccessFlagFile = "$env:TEMP\qqntim-uninstall-successful.tmp"

if ((Test-Path $QQNTimFlagFile) -eq $false) {
    throw "QQNTim 未被安装。"
}

if ((Read-Host "是否要卸载 QQNTim (y/n)?") -notcontains "y") {
    throw "卸载已被用户取消。"
}

if ((Read-Host "是否需要同时移除所有数据 (y/n)?") -contains "y") {
    Remove-Item "${env:UserProfile}\.qqntim" -Recurse -Force -ErrorAction SilentlyContinue
}

if ($env:QQNTIM_UNINSTALLER_NO_KILL_QQ -ne "1") {
    Write-Output "正在关闭 QQ……"
    Stop-Process -Name QQ -ErrorAction SilentlyContinue
}

Write-Output "正在移除文件……"
if ((Test-Path "$QQAppLauncherDir\node_modules.zip.md5") -eq $true) {
    Remove-Item "$QQAppLauncherDir\node_modules.zip.md5" -Force
}
Remove-Item "$QQAppLauncherDir\qqntim.js", "$QQAppLauncherDir\qqntim-renderer.js", "$QQAppLauncherDir\node_modules", "$QQAppLauncherDir\builtins" -Recurse -Force

Write-Output "正在还原 package.json……"
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines("$QQAppDir\package.json", ((Get-Content "$QQAppDir\package.json" -Encoding UTF8 -Force) -replace "./app_launcher/qqntim.js", "./app_launcher/index.js"), $Utf8NoBomEncoding)

Write-Output "正在还原 QQ.exe……"
if ((Test-Path $QQExecutableHashFile) -eq $true) {
    Remove-Item $QQExecutableHashFile -Force
}
if ((Test-Path $QQExecutableBackupFile) -eq $true) {
    Remove-Item $QQExecutableFile -Force
    Move-Item $QQExecutableBackupFile $QQExecutableFile -Force
}

Remove-Item $QQNTimFlagFile -Force

if ((Test-Path $SuccessFlagFile) -eq $false) {
    "" | Out-File $SuccessFlagFile -Encoding UTF8 -Force
}

if ($env:QQNTIM_UNINSTALLER_NO_DELAYED_EXIT -ne "1") {
    Write-Output "卸载成功。卸载程序将在 5 秒后自动退出。"
    Start-Sleep -Seconds 5
}
else {
    Write-Output "卸载成功。"
}

================================================
FILE: publish/install.cmd
================================================
@setlocal enableextensions
@echo off
cd /d %~dp0_
color F0
mode con cols=65 lines=16

set PS_PREFIX=powershell -NoProfile -ExecutionPolicy Unrestricted

"%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" >nul 2>nul 
if "%ERRORLEVEL%" neq "0" (
    goto try_run_as
) else (
    goto main
)
goto:eof

:try_run_as
%PS_PREFIX% -WindowStyle Hidden -Command Start-Process -Wait -FilePath """%COMSPEC%""" -Verb RunAs -ArgumentList """/c""","""`"""%~f0`""""""
goto:eof

:main
set SUCCESS_FLAG=%TEMP%\qqntim-install-successful.tmp
if exist "%SUCCESS_FLAG%" (
    del /f /q "%SUCCESS_FLAG%"
)
%PS_PREFIX% -File .\install.ps1
if not exist "%SUCCESS_FLAG%" (
    echo Installation error. If you believe this is an issue of QQNTim, please report it to us.
    pause >nul 2>nul
)
goto:eof

================================================
FILE: publish/install.sh
================================================
#!/usr/bin/env bash

pushd "$( dirname "${BASH_SOURCE[0]}" )/_" > /dev/null

# 判断是否拥有 root 权限
if [ ! "$(whoami)" == "root" ]; then
    echo "正在提升权限……"
    popd > /dev/null
    sudo QQNTIM_INSTALLER_NO_KILL_QQ="$QQNTIM_INSTALLER_NO_KILL_QQ" QQNTIM_INSTALLER_NO_DELAYED_EXIT="$QQNTIM_INSTALLER_NO_DELAYED_EXIT" "${BASH_SOURCE[0]}"
    exit 0
fi

# 获取 QQ 安装路径
qq_installation_dir=$( dirname $( readlink $( which qq || which linuxqq ) ) 2>/dev/null || echo "/var/lib/flatpak/app/com.qq.QQ/current/active/files/extra/QQ" )

if [ ! -d "$qq_installation_dir" ]; then
    echo "未找到 QQNT 安装目录。"
fi

qq_app_dir="$qq_installation_dir/resources/app"
qq_applauncher_dir="$qq_app_dir/app_launcher"
qqntim_flag_file="$qq_applauncher_dir/qqntim-flag.txt"

# 询问用户,如果存在旧版则不提示
if [ ! -f "$qqntim_flag_file" ]; then
    read -p "是否要安装 QQNTim (y/n)?" choice
    case $choice in
    y) ;;
    Y) ;;
    *) exit -1 ;;
    esac
else
    echo "检测到已有安装,正在更新……"
fi

if [ "$QQNTIM_INSTALLER_NO_KILL_QQ" != "1" ]; then
    echo "正在关闭 QQ……"
    killall -w qq linuxqq > /dev/null 2>&1
fi

echo "正在复制文件……"

if [ -f "./node_modules.zip.md5" -a -f "./node_modules.zip" ]; then
    diff "$qq_applauncher_dir/node_modules.zip.md5" "./node_modules.zip.md5" > /dev/null 2>&1
    [ $? != 0 ] && unzip -qo ./node_modules.zip -d "$qq_applauncher_dir/node_modules"
    cp -f ../node_modules.zip.md5 "$qq_applauncher_dir"
elif [ -d "./node_modules" ]; then
    cp -rf ./node_modules "$qq_applauncher_dir"
fi
cp -rf ./qqntim.js ./qqntim-renderer.js ./builtins "$qq_applauncher_dir"

echo "正在修补 package.json……"
sed -i "s#\.\/app_launcher\/index\.js#\.\/app_launcher\/qqntim\.js#g" "$qq_app_dir/package.json"

touch "$qqntim_flag_file"

if [ "$QQNTIM_INSTALLER_NO_DELAYED_EXIT" != "1" ]; then
    echo "安装成功。安装程序将在 5 秒后自动退出。"
    sleep 5s
else
    echo "安装成功。"
fi

exit 0


================================================
FILE: publish/install_macos.sh
================================================
#!/usr/bin/env bash

pushd "$( dirname "${BASH_SOURCE[0]}" )/_" > /dev/null

# 判断是否拥有 root 权限
if [ ! "$(whoami)" == "root" ]; then
    echo "正在提升权限……"
    popd > /dev/null
    sudo QQNTIM_INSTALLER_NO_KILL_QQ="$QQNTIM_INSTALLER_NO_KILL_QQ" QQNTIM_INSTALLER_NO_DELAYED_EXIT="$QQNTIM_INSTALLER_NO_DELAYED_EXIT" "${BASH_SOURCE[0]}"
    exit 0
fi

# 获取 QQ 安装路径
qq_installation_dir="/Applications/QQ.app/Contents"

if [ ! -d "$qq_installation_dir" ]; then
    echo "未找到 QQNT 安装目录。"
fi

qq_app_dir="$qq_installation_dir/Resources/app"
qq_applauncher_dir="$qq_app_dir/app_launcher"
qqntim_flag_file="$qq_applauncher_dir/qqntim-flag.txt"

# 询问用户,如果存在旧版则不提示
if [ ! -f "$qqntim_flag_file" ]; then
    read -p "是否要安装 QQNTim (y/n)?" choice
    case $choice in
    y) ;;
    Y) ;;
    *) exit -1 ;;
    esac
else
    echo "检测到已有安装,正在更新……"
fi

if [ "$QQNTIM_INSTALLER_NO_KILL_QQ" != "1" ]; then
    echo "正在关闭 QQ……"
    pkill QQ > /dev/null 2>&1
fi

echo "正在复制文件……"

# 清理安装目录
if [ -d "$qq_applauncher_dir/node_modules" ]; then
    rm -rf
else
    mkdir $qq_applauncher_dir/node_modules
fi

if [ -f "./node_modules.zip.md5" -a -f "./node_modules.zip" ]; then
    diff "$qq_applauncher_dir/node_modules.zip.md5" "./node_modules.zip.md5" > /dev/null 2>&1
    [ $? != 0 ]
    unzip -qo ./node_modules.zip -d "$qq_applauncher_dir/node_modules"
    cp -f ./node_modules.zip.md5 "$qq_applauncher_dir"
elif [ -d "./node_modules" ]; then
    cp -rf ./node_modules "$qq_applauncher_dir"
fi
cp -rf ./qqntim.js ./qqntim-renderer.js ./builtins "$qq_applauncher_dir"

echo "正在修补 package.json……"
sed -i "" "s#\.\/app_launcher\/index\.js#\.\/app_launcher\/qqntim\.js#g" "$qq_app_dir/package.json"

touch "$qqntim_flag_file"

if [ "$QQNTIM_INSTALLER_NO_DELAYED_EXIT" != "1" ]; then
    echo "安装成功。安装程序将在 5 秒后自动退出。"
    sleep 5
else
    echo "安装成功。"
fi

exit 0


================================================
FILE: publish/uninstall.cmd
================================================
@setlocal enableextensions
@echo off
cd /d %~dp0_
color F0
mode con cols=65 lines=16

set PS_PREFIX=powershell -NoProfile -ExecutionPolicy Unrestricted

"%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" >nul 2>nul 
if "%ERRORLEVEL%" neq "0" (
    goto try_run_as
) else (
    goto main
)
goto:eof

:try_run_as
%PS_PREFIX% -WindowStyle Hidden -Command Start-Process -Wait -FilePath """%COMSPEC%""" -Verb RunAs -ArgumentList """/c""","""`"""%~f0`""""""
goto:eof

:main
set SUCCESS_FLAG=%TEMP%\qqntim-uninstall-successful.tmp
if exist "%SUCCESS_FLAG%" (
    del /f /q "%SUCCESS_FLAG%"
)
%PS_PREFIX% -File .\uninstall.ps1
if not exist "%SUCCESS_FLAG%" (
    echo Uninstallation error. If you believe this is an issue of QQNTim, please report it to us.
    pause >nul 2>nul
)
goto:eof

================================================
FILE: publish/uninstall.sh
================================================
#!/usr/bin/env bash

pushd "$( dirname "${BASH_SOURCE[0]}" )/_" > /dev/null

# 判断是否拥有 root 权限
if [ ! "$(whoami)" == "root" ]; then
    echo "正在提升权限……"
    popd > /dev/null
    sudo QQNTIM_UNINSTALLER_NO_KILL_QQ="$QQNTIM_UNINSTALLER_NO_KILL_QQ" QQNTIM_UNINSTALLER_NO_DELAYED_EXIT="$QQNTIM_UNINSTALLER_NO_DELAYED_EXIT" "${BASH_SOURCE[0]}"
    exit 0
fi

# 获取 QQ 安装路径
qq_installation_dir=$( dirname $( readlink $( which qq || which linuxqq ) ) 2>/dev/null || echo "/var/lib/flatpak/app/com.qq.QQ/current/active/files/extra/QQ"  )

if [ ! -d "$qq_installation_dir" ]; then
    echo "未找到 QQNT 安装目录。"
fi

qq_app_dir="$qq_installation_dir/resources/app"
qq_applauncher_dir="$qq_app_dir/app_launcher"
qqntim_flag_file="$qq_applauncher_dir/qqntim-flag.txt"

if [ ! -f "$qqntim_flag_file" ]; then
    echo "QQNTim 未被安装。"
    exit -1
fi

read -p "是否要卸载 QQNTim (y/n)?" choice
case $choice in
  y) ;;
  *) exit -1 ;;
esac

read -p "是否需要同时移除所有数据 (y/n)?" choice
case $choice in
  y) rm -rf "$HOME/.local/share/QQNTim" ;;
  *) ;;
esac

if [ "$QQNTIM_UNINSTALLER_NO_KILL_QQ" != "1" ]; then
    echo "正在关闭 QQ……"
    killall -w qq linuxqq > /dev/null 2>&1
fi

echo "正在移除文件……"
[ -f "$qq_applauncher_dir/node_modules.zip.md5" ] && rm -f "$qq_applauncher_dir/node_modules.zip.md5"
rm -rf "$qq_applauncher_dir/qqntim.js" "$qq_applauncher_dir/qqntim-renderer.js" "$qq_applauncher_dir/node_modules" "$qq_applauncher_dir/builtins"

echo "正在还原 package.json……"
sed -i "s#\.\/app_launcher\/qqntim\.js#\.\/app_launcher\/index\.js#g" "$qq_app_dir/package.json"

rm -f "$qqntim_flag_file"

if [ "$QQNTIM_UNINSTALLER_NO_DELAYED_EXIT" != "1" ]; then
    echo "卸载成功。卸载程序将在 5 秒后自动退出。"
    sleep 5s
else
    echo "卸载成功。"
fi
exit 0


================================================
FILE: publish/uninstall_macos.sh
================================================
#!/usr/bin/env bash

pushd "$( dirname "${BASH_SOURCE[0]}" )/_" > /dev/null

# 判断是否拥有 root 权限
if [ ! "$(whoami)" == "root" ]; then
    echo "正在提升权限……"
    popd > /dev/null
    sudo QQNTIM_UNINSTALLER_NO_KILL_QQ="$QQNTIM_UNINSTALLER_NO_KILL_QQ" QQNTIM_UNINSTALLER_NO_DELAYED_EXIT="$QQNTIM_UNINSTALLER_NO_DELAYED_EXIT" "${BASH_SOURCE[0]}"
    exit 0
fi

# 获取 QQ 安装路径
qq_installation_dir="/Applications/QQ.app/Contents"

if [ ! -d "$qq_installation_dir" ]; then
    echo "未找到 QQNT 安装目录。"
fi

qq_app_dir="$qq_installation_dir/Resources/app"
qq_applauncher_dir="$qq_app_dir/app_launcher"
qqntim_flag_file="$qq_applauncher_dir/qqntim-flag.txt"

if [ ! -f "$qqntim_flag_file" ]; then
    echo "QQNTim 未被安装。"
    exit -1
fi

read -p "是否要卸载 QQNTim (y/n)?" choice
case $choice in
  y) ;;
  *) exit -1 ;;
esac

read -p "是否需要同时移除所有数据 (y/n)?" choice
case $choice in
  y) rm -rf "$HOME/.local/share/QQNTim" ;;
  *) ;;
esac

if [ "$QQNTIM_UNINSTALLER_NO_KILL_QQ" != "1" ]; then
    echo "正在关闭 QQ……"
    pkill QQ > /dev/null 2>&1
fi

echo "正在移除文件……"
[ -f "$qq_applauncher_dir/node_modules.zip.md5" ] && rm -f "$qq_applauncher_dir/node_modules.zip.md5"
rm -rf "$qq_applauncher_dir/qqntim.js" "$qq_applauncher_dir/qqntim-renderer.js" "$qq_applauncher_dir/node_modules" "$qq_applauncher_dir/builtins"

echo "正在还原 package.json……"
sed -i "" "s#\.\/app_launcher\/qqntim\.js#\.\/app_launcher\/index\.js#g" "$qq_app_dir/package.json"

rm -f "$qqntim_flag_file"

if [ "$QQNTIM_UNINSTALLER_NO_DELAYED_EXIT" != "1" ]; then
    echo "卸载成功。卸载程序将在 5 秒后自动退出。"
    sleep 5
else
    echo "卸载成功。"
fi
exit 0


================================================
FILE: rome.json
================================================
{
    "$schema": "https://docs.rome.tools/schemas/12.1.3/schema.json",
    "organizeImports": {
        "enabled": true
    },
    "files": {
        "ignore": [".pnp.cjs", ".pnp.loader.mjs", ".yarn/*", "dist/*", "src/typings/src/electron.d.ts"]
    },
    "formatter": {
        "indentSize": 4,
        "indentStyle": "space",
        "lineWidth": 300
    },
    "linter": {
        "enabled": true,
        "rules": {
            "recommended": true,
            "suspicious": { "noExplicitAny": "off", "noDoubleEquals": "off" },
            "style": { "noParameterAssign": "off", "noNonNullAssertion": "off" },
            "a11y": { "all": false }
        }
    }
}


================================================
FILE: scripts/pack.ps1
================================================
$ErrorActionPreference = "Stop"

Set-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + "\..")
$CD = (Get-Location).Path


$SourceDirPath = "$CD\dist\_\node_modules"
$DestinationZipPath = "$CD\dist\_\node_modules.zip"

# 设置特定时间戳,确保两次构建结果 Hash 不变
Get-ChildItem $SourceDirPath -Recurse | ForEach-Object { $_.LastWriteTimeUtc = "01/01/1970 08:00:00"; $_.LastAccessTimeUtc = "01/01/1970 08:00:00"; $_.CreationTimeUtc = "01/01/1970 08:00:00"; }

# 打包 node_modules
# 仅支持 .NET Framework 4.5 及以上
Add-Type -AssemblyName System.IO.Compression.Filesystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($SourceDirPath, $DestinationZipPath)
Remove-Item $SourceDirPath -Recurse -Force

# 生成 MD5 校验和
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllLines($DestinationZipPath, (Get-FileHash "$DestinationZipPath.md5" -Algorithm MD5).Hash, $Utf8NoBomEncoding)


================================================
FILE: scripts/pack.sh
================================================
#!/usr/bin/env bash

cd "$( dirname "${BASH_SOURCE[0]}" )/.."

pushd ./dist/_/node_modules > /dev/null

# 设置特定时间戳,确保两次构建结果 Hash 不变
find . -exec touch -d @0 {} +

# 打包 node_modules
zip -Xyqr9 ../node_modules.zip .

popd > /dev/null

rm -rf ./dist/_/node_modules

# 生成 MD5 校验和
(md5sum -b ./dist/_/node_modules.zip | cut -d" " -f1) > ./dist/_/node_modules.zip.md5

================================================
FILE: scripts/start.ps1
================================================
$ErrorActionPreference = "Stop"

Set-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + "\..")

# 从注册表获取 QQ 安装路径
foreach ($RegistryPath in @("HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*")) {
    try {
        foreach ($Item in (Get-ItemProperty $RegistryPath)) {
            if ($Item.PSChildName -eq "QQ") {
                $QQInstallDir = (Split-Path -Parent $Item.UninstallString)
                break
            }
        }
    }
    catch {}
}

if (($null -eq $QQInstallDir) -or ((Test-Path $QQInstallDir) -eq $false)) {
    throw "未找到 QQNT 安装目录。"
}

Start-Process "$QQInstallDir\QQ.exe" -Wait 

================================================
FILE: scripts/start.sh
================================================
#!/usr/bin/env bash

cd "$( dirname "${BASH_SOURCE[0]}" )/.."

( qq || linuxqq || flatpak run com.qq.QQ ) 2>&1 | sed -e '/NODE_TLS_REJECT_UNAUTHORIZED/d' -e '/Gtk-Message/d' -e '/to show where the warning was created/d' -e '/gbm_wrapper\.cc/d' -e '/node_bindings\.cc/d' -e '/UnhandledPromiseRejectionWarning/d' -e '/\[BuglyManager\.cpp\]/d' -e '/\[NativeCrashHandler\.cpp\]/d' -e '/\[BuglyService\.cpp\]/d' -e '/\[HotUpdater\]/d' -e '/ERROR:CONSOLE/d'


================================================
FILE: src/builtins/settings/package.json
================================================
{
    "name": "@flysoftbeta/qqntim-plugin-settings",
    "private": true,
    "devDependencies": {
        "@flysoftbeta/qqntim-typings": "workspace:*",
        "@types/node": "^20.6.2",
        "@types/react": "^18.2.21",
        "@types/react-dom": "^18.2.7",
        "@types/unzipper": "^0.10.7"
    },
    "dependencies": {
        "unzipper": "^0.10.14"
    }
}


================================================
FILE: src/builtins/settings/publish/qqntim.json
================================================
{
    "manifestVersion": "3.0",
    "id": "builtin-settings-ui",
    "name": "设置",
    "author": "Flysoft",
    "injections": [
        {
            "type": "renderer",
            "page": "settings",
            "stylesheet": "style.css",
            "script": "renderer.js"
        }
    ]
}


================================================
FILE: src/builtins/settings/publish/style.css
================================================
.q-switch {
    position: relative;
}

.q-switch > input {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    appearance: none !important;
    margin: 0;
    z-index: 10;
}

.q-button {
    margin: 0 !important;
}

.qqntim-settings-panel-open
    .setting-main
    .setting-main__content:not(.qqntim-settings-panel),
body:not(.qqntim-settings-panel-open)
    .setting-main
    .setting-main__content.qqntim-settings-panel {
    display: none !important;
}

.qqntim-settings-panel {
    padding: 20px 16px 70px !important;
}

.qqntim-settings-panel-section-header {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 8px;
}

.qqntim-settings-panel-section-header-title {
    font-size: min(var(--font_size_2), 18px) !important;
}

.qqntim-settings-panel-section-header-buttons {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 5px;
}

.qqntim-settings-panel-section-content {
    border-radius: 5px;
    padding: 0 16px;
    background-color: var(--fg_white);
}

.qqntim-settings-panel-settings-versions {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    gap: 5px;
    padding: 16px 0;
}

.qqntim-settings-panel-settings-versions-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    white-space: nowrap;
    flex: 10;
}

.qqntim-settings-panel-settings-versions-item > h3 {
    font-size: min(var(--font_size_3), 18px) !important;
}

.qqntim-settings-panel-settings-versions-item > div {
    font-size: min(var(--font_size_2), 16px) !important;
    color: var(--text_secondary_01);
}

.qqntim-settings-panel-box {
    display: flex;
    flex-direction: column;
}

.qqntim-settings-panel-box-item {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    min-height: 44px;
    padding: 8px 0;
}

.qqntim-settings-panel-box-item > span {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.qqntim-settings-panel-box-item > div {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 5px;
}

.qqntim-settings-panel-box-item-title {
    font-size: min(var(--font_size_3), 18px) !important;
}

.qqntim-settings-panel-box-item-description {
    font-size: min(var(--font_size_2), 16px) !important;
    color: var(--text_secondary_01);
}

.qqntim-settings-panel-box-item:not(.qqntim-settings-panel-box-item-last) {
    border-bottom: 1px solid var(--divider_standard);
}

.qqntim-settings-panel-save {
    position: fixed;
    right: 20px;
    bottom: 20px;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    z-index: 100;
}


================================================
FILE: src/builtins/settings/src/_renderer.tsx
================================================
import * as exports from "./exports";
import * as exportsComponents from "./exports/components";
import { Navigation, TabWithOtherTab } from "./nav";
import { Panel } from "./panel";
import { cl } from "./utils/consts";
import { defineModules, nt, utils } from "qqntim/renderer";
import { createRoot } from "react-dom/client";

export default class Entry implements QQNTim.Entry.Renderer {
    constructor() {
        defineModules({ "qqntim-settings": exports as typeof QQNTim.Settings, "qqntim-settings/components": exportsComponents as typeof QQNTim.SettingsComponents });

        Promise.all([nt.getAccountInfo(), utils.waitForElement<HTMLElement>(".nav-bar:not(.qqntim-settings-nav)"), utils.waitForElement<HTMLElement>(".setting-main"), utils.waitForElement<HTMLElement>(`.setting-main .setting-main__content:not(.${cl.panel.c})`)]).then(
            ([account, nav, panel, panelContent]) => {
                if (!account) throw new Error("获取当前账户信息时失败");

                const panelVueId = utils.getVueId(panelContent)!;
                const panelContainer = document.createElement("div");
                panelContainer.classList.add("setting-main__content", cl.panel.c);
                panelContainer.setAttribute(panelVueId, "");
                const panelRoot = createRoot(panelContainer);
                const renderPanel = (currentTab: TabWithOtherTab) => {
                    panelRoot.render(<Panel currentTab={currentTab} account={account} />);
                };
                panel.appendChild(panelContainer);

                const navVueId = utils.getVueId(nav.firstElementChild as HTMLElement)!;
                const navContainer = document.createElement("div");
                navContainer.classList.add(cl.nav.c);
                const navRoot = createRoot(navContainer);
                const renderNav = () => {
                    navRoot.render(<Navigation vueId={navVueId} onCurrentTabChange={renderPanel} />);
                };
                nav.appendChild(navContainer);
                exports.setRenderNavFunction(renderNav);
                renderNav();
            },
        );
    }
}


================================================
FILE: src/builtins/settings/src/exports/components.tsx
================================================
import { cl } from "../utils/consts";
import { Fragment, ReactNode, useState } from "react";

export function SettingsSection({ title, children, buttons }: { title: string; children: ReactNode; buttons?: ReactNode }) {
    return (
        <div className={cl.panel.section.c}>
            <span className={cl.panel.section.header.c}>
                <h2 className={cl.panel.section.header.title.c}>{title}</h2>
                {!!buttons && <div className={cl.panel.section.header.buttons.c}>{buttons}</div>}
            </span>
            <div className={cl.panel.section.content.c}>{children}</div>
        </div>
    );
}

export function SettingsBox({ children }: { children: ReactNode }) {
    return <div className={cl.panel.box.c}>{children}</div>;
}

export function SettingsBoxItem({ title, description, children, isLast = false }: { title: string; description?: string[]; children?: ReactNode; isLast?: boolean }) {
    return (
        <label className={`${cl.panel.box.item.c}${isLast ? ` ${cl.panel.box.item.last.c}` : ""}`}>
            <span>
                <span className={cl.panel.box.item.title.c}>{title}</span>
                {description ? (
                    <span className={cl.panel.box.item.description.c}>
                        {description.map((text, idx, array) => {
                            return (
                                // rome-ignore lint/suspicious/noArrayIndexKey: <explanation>
                                <Fragment key={idx}>
                                    <span>{text}</span>
                                    {idx != array.length - 1 && <br />}
                                </Fragment>
                            );
                        })}
                    </span>
                ) : null}
            </span>
            <div>{children}</div>
        </label>
    );
}

export function Switch({ checked, onToggle }: { checked: boolean; onToggle: (checked: boolean) => void }) {
    return (
        <div className={`q-switch${checked ? " is-active" : ""}`} onClick={() => onToggle(!checked)}>
            <input type="checkbox" checked={checked} onChange={(event) => onToggle(event.target.checked)} />
            <div className="q-switch__handle" />
        </div>
    );
}

export function Input({ value, onChange, width }: { value: string; onChange: (value: string) => void; width }) {
    const [focus, setFocus] = useState<boolean>(false);

    return (
        <div className="q-input" style={{ border: "1px solid var(--divider_dark)", height: "26px", width: width, background: "var(--bg_white)", boxSizing: "border-box", position: "relative" }}>
            <input
                type="text"
                className="q-input__inner"
                value={value}
                onChange={(event) => onChange(event.target.value)}
                onFocus={() => setFocus(true)}
                onBlur={() => setFocus(false)}
                spellCheck={false}
                style={{
                    fontSize: "12px",
                    height: "26px",
                    lineHeight: "26px",
                    padding: "0 32px 0 8px",
                    border: "1px solid transparent",
                    borderRadius: "4px",
                    boxSizing: "border-box",
                    ...(focus && {
                        border: " 1px solid var(--brand_standard)",
                        borderRadius: "4px",
                        caretColor: "var(--brand_standard)",
                    }),
                }}
            />
        </div>
    );
}

export function Dropdown<T>({ items, selected, onChange, width }: { items: [T, string][]; selected: T; onChange: (id: T) => void; width: string }) {
    const [open, setOpen] = useState<boolean>(false);
    const [selectedId, selectedContent] = items.find(([id]) => id == selected)!;

    return (
        <div className="q-pulldown-menu small-size" style={{ width: width }}>
            <div className="q-pulldown-menu-button" onClick={() => setOpen((prev) => !prev)}>
                <div className="content">{selectedContent}</div>
                <span className="icon">
                    <i
                        className="q-icon"
                        style={{
                            width: "16px",
                            height: "16px",
                            color: "inherit",
                            alignItems: "center",
                            display: "inline-flex",
                            justifyContent: "center",
                        }}
                    >
                        <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ width: "16px", height: "16px" }}>
                            <path d="M12 6.0001L8.00004 10L4 6" stroke="currentColor" strokeLinejoin="round" />
                        </svg>
                    </i>
                </span>
            </div>
            {open && (
                <div className="q-pulldown-menu-wrapper">
                    <ul className="q-pulldown-menu-list" style={{ maxHeight: "unset" }}>
                        {items.map(([id, content]) => {
                            const isSelected = id == selectedId;
                            return (
                                <li
                                    className={`q-pulldown-menu-list-item${isSelected ? " selected" : ""}`}
                                    tabIndex={0}
                                    onClick={() => {
                                        onChange(id);
                                        setOpen(false);
                                    }}
                                >
                                    <span className="content">{content}</span>
                                    {isSelected && (
                                        <span className="icon">
                                            <i
                                                className="q-icon"
                                                style={{
                                                    width: "1em",
                                                    height: "1em",
                                                    color: "inherit",
                                                    alignItems: "center",
                                                    display: "inline-flex",
                                                    justifyContent: "center",
                                                }}
                                            >
                                                <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ width: "1em", height: "1em" }}>
                                                    <path d="M2 7L6.00001 11L14 3" stroke="currentColor" strokeLinejoin="round" />
                                                </svg>
                                            </i>
                                        </span>
                                    )}
                                </li>
                            );
                        })}
                    </ul>
                </div>
            )}
        </div>
    );
}

export function Button({ onClick, primary, small, children }: { onClick: () => void; primary: boolean; small: boolean; children: ReactNode }) {
    return (
        <button className={`q-button q-button--default ${primary ? "q-button--primary" : "q-button--secondary"}${small ? " q-button--small" : ""}`} onClick={() => onClick()}>
            <span className="q-button__slot-warp">{children}</span>
        </button>
    );
}


================================================
FILE: src/builtins/settings/src/exports/index.ts
================================================
export const panels: [string, QQNTim.Settings.Panel, string | undefined][] = [];
let renderNav: Function = () => undefined;

export function defineSettingsPanels(...newSettingsPanels: [string, QQNTim.Settings.Panel, string | undefined][]) {
    panels.push(...newSettingsPanels);
    renderNav();
}

export function setRenderNavFunction(newFunction: Function) {
    renderNav = newFunction;
}


================================================
FILE: src/builtins/settings/src/installer.ts
================================================
import { s } from "./utils/sep";
import { randomUUID } from "crypto";
import * as path from "path";
import { allPlugins, app, dialog, env, modules } from "qqntim/renderer";
import { Extract } from "unzipper";
const { fs } = modules;

export async function installZipPluginsForAccount(uin: string, requiresRestart: boolean) {
    const result = await dialog.openDialog({ title: "选择插件压缩包", properties: ["openFile"], filters: [{ name: "ZIP 压缩文件", extensions: ["zip"] }] });
    if (result.canceled) return;
    const filePath = result.filePaths[0];
    if (!(await fs.exists(filePath)) || !(await fs.stat(filePath)).isFile()) return;
    const tmpDir = `${process.platform == "win32" ? process.env["TEMP"] : "/tmp"}${s}${randomUUID()}`;

    try {
        await fs.ensureDir(tmpDir);
        await new Promise<void>((resolve, reject) =>
            fs
                .createReadStream(result.filePaths[0])
                .pipe(Extract({ path: tmpDir }))
                .on("close", () => resolve())
                .on("error", (error) => reject(error)),
        );
    } catch (reason) {
        await dialog.alert("解压插件压缩包时出现错误:\n" + reason);
        return false;
    }

    return await installPluginsForAccount(uin, requiresRestart, tmpDir);
}

export async function installFolderPluginsForAccount(uin: string, requiresRestart: boolean) {
    const result = await dialog.openDialog({ title: "选择插件文件夹", properties: ["openDirectory"] });
    if (result.canceled) return;
    const filePath = result.filePaths[0];
    if (!(await fs.exists(filePath)) || !(await fs.stat(filePath)).isDirectory()) return false;

    return await installPluginsForAccount(uin, requiresRestart, filePath);
}

async function collectManifests(dir: string) {
    const getManifestFile = async (dir: string) => {
        const manifestFile = `${dir}${s}qqntim.json`;
        if ((await fs.exists(manifestFile)) && (await fs.stat(manifestFile)).isFile()) return manifestFile;
    };

    let manifestFiles: string[] = [];
    const manifestFile = await getManifestFile(dir);
    if (!manifestFile) {
        const folders = await fs.readdir(dir);
        manifestFiles = (
            await Promise.all(
                folders.map(async (folder) => {
                    const folderPath = `${dir}${s}${folder}`;
                    if ((await fs.exists(folderPath)) && (await fs.stat(folderPath)).isDirectory()) {
                        return await getManifestFile(folderPath);
                    }
                }),
            )
        ).filter(Boolean) as string[];
    } else manifestFiles = [manifestFile];

    return manifestFiles;
}

async function installPluginsForAccount(uin: string, requiresRestart: boolean, dir: string) {
    const manifestFiles = await collectManifests(dir);
    if (manifestFiles.length == 0) {
        await dialog.alert("未在目标文件夹或文件夹搜索到任何插件。\n请联系插件作者以获得更多信息。");
        return false;
    }

    let count = 0;
    for (const manifestFile of manifestFiles) {
        const manifest = fs.readJSONSync(manifestFile) as QQNTim.Manifest;
        const pluginDir = `${uin == "" ? env.path.pluginDir : `${env.path.pluginPerUserDir}${s}${uin}`}${s}${manifest.id}`;
        if (!(await dialog.confirm(`扫描到一个插件:\n\nID:${manifest.id}\n名称:${manifest.name}\n作者:${manifest.author || "未知"}\n说明:${manifest.description || "该插件没有提供说明。"}\n\n是否希望安装此插件?`))) continue;
        try {
            if (allPlugins[uin]?.[manifest.id]) await fs.rm(allPlugins[uin][manifest.id].dir);
            await fs.ensureDir(pluginDir);
            await fs.copy(path.dirname(manifestFile), pluginDir);
            count++;
        } catch (reason) {
            await dialog.alert("复制插件时出现错误:\n" + reason);
        }
    }

    await dialog.alert(`成功安装了 ${count} 个插件。${requiresRestart ? `\n\n点击 "确定" 将重启你的 QQ。` : ""}`);
    if (requiresRestart) app.relaunch();
    return true;
}

export async function uninstallPlugin(requiresRestart: boolean, pluginDir: string) {
    if (!(await dialog.confirm("是否要卸载此插件?"))) return false;
    try {
        await fs.remove(pluginDir);
        await dialog.alert(`成功卸载此插件。${requiresRestart ? `\n\n点击 "确定" 将重启你的 QQ。` : ""}`);
        if (requiresRestart) app.relaunch();
        return true;
    } catch (reason) {
        await dialog.alert(`卸载插件时出现错误:\n${reason}`);
        return false;
    }
}


================================================
FILE: src/builtins/settings/src/main.ts
================================================


================================================
FILE: src/builtins/settings/src/nav.tsx
================================================
import { panels } from "./exports";
import { cl } from "./utils/consts";
import { utils } from "qqntim/renderer";
import { Fragment, useEffect, useState } from "react";

interface OtherTab {
    key?: undefined;
    type?: undefined;
    title?: string;
    icon?: string;
}

interface PluginsManagerTab {
    key: string;
    type: "plugins-manager";
    title: string;
    icon: string;
}

interface SettingsTab {
    key: string;
    type: "settings";
    title: string;
    icon: string;
}

interface PluginTab {
    key: string;
    type: "plugin";
    title: string;
    icon: string | undefined;
    node: QQNTim.Settings.Panel;
}

export type Tab = PluginsManagerTab | SettingsTab | PluginTab;
export type TabWithOtherTab = Tab | OtherTab;

export function Navigation({ vueId, onCurrentTabChange }: { vueId: string; onCurrentTabChange: (tab: TabWithOtherTab) => void }) {
    const [currentTab, setCurrentTab] = useState<TabWithOtherTab>({});
    useEffect(() => {
        utils.waitForElement<HTMLElement>(".nav-bar").then((element) =>
            element.addEventListener("click", (event) => {
                const item = (event.target as HTMLElement).closest(".nav-item");
                if (!item) return;
                if (item.classList.contains(cl.nav.item.c)) return;
                item.classList.toggle("nav-item-active", true);

                const title = item.firstElementChild?.nextElementSibling as HTMLElement;
                if (title) setCurrentTab({ title: title.innerText });
            }),
        );
    }, []);
    useEffect(() => {
        if (currentTab.type) utils.waitForElement<HTMLElement>(`.nav-item.nav-item-active:not(.${cl.nav.item.c})`).then((element) => element.classList.remove("nav-item-active"));
        onCurrentTabChange(currentTab);
    }, [currentTab]);

    const tabs: Tab[] = [
        {
            key: "settings",
            type: "settings",
            title: "QQNTim 设置",
            icon: `<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 2.15771L13 5.07438L13 10.9256L8 13.8423L3 10.9256L3 5.07438L8 2.15771ZM7.49613 1.29394C7.80749 1.11231 8.19251 1.11231 8.50387 1.29394L13.5039 4.2106C13.8111 4.38981 14 4.71871 14 5.07438V10.9256C14 11.2813 13.8111 11.6102 13.5039 11.7894L8.50387 14.7061C8.19251 14.8877 7.80749 14.8877 7.49613 14.7061L2.49613 11.7894C2.18891 11.6102 2 11.2813 2 10.9256V5.07438C2 4.71871 2.18891 4.38981 2.49613 4.2106L7.49613 1.29394ZM10.2633 6.09507L5 9.13385L5.5 9.99988L10.7633 6.96109L10.2633 6.09507Z" fill="currentColor"></path></svg>`,
        },
        {
            key: "plugins-manager",
            type: "plugins-manager",
            title: "插件管理",
            icon: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3.75" y="3.75" width="6.5" height="6.5" rx="1.25" stroke="currentColor" stroke-width="1.5"></rect><rect x="12.4038" y="7" width="6.5" height="6.5" rx="1.25" transform="rotate(-45 12.4038 7)" stroke="currentColor" stroke-width="1.5"></rect><rect x="3.75" y="13.75" width="6.5" height="6.5" rx="1.25" stroke="currentColor" stroke-width="1.5"></rect><rect x="13.75" y="13.75" width="6.5" height="6.5" rx="1.25" stroke="currentColor" stroke-width="1.5"></rect></svg>`,
        },
        ...panels.map(([title, node, icon], idx): PluginTab => {
            return {
                key: `plugin-${idx}`,
                type: "plugin",
                title: title,
                icon: icon,
                node: node,
            };
        }),
    ];

    return (
        <Fragment>
            {tabs.map((item) => (
                <div key={item.key} className={`nav-item ${cl.nav.item.c}${currentTab.key == item.key ? " nav-item-active" : ""}`} onClick={() => setCurrentTab(item)} {...{ [vueId]: "" }}>
                    {!!item.icon && (
                        <i
                            className="q-icon icon"
                            /* rome-ignore lint/security/noDangerouslySetInnerHtml: <explanation> */
                            dangerouslySetInnerHTML={{ __html: item.icon }}
                            style={{
                                width: "16px",
                                height: "16px",
                                marginRight: "8px",
                                alignItems: "center",
                                color: "inherit",
                                display: "inline-flex",
                                justifyContent: "center",
                            }}
                        />
                    )}
                    <div className="name" {...{ [vueId]: "" }}>
                        {item.title}
                    </div>
                </div>
            ))}
        </Fragment>
    );
}


================================================
FILE: src/builtins/settings/src/panel.tsx
================================================
import { Button, SettingsBox, SettingsBoxItem, SettingsSection, Switch } from "./exports/components";
import { installFolderPluginsForAccount, installZipPluginsForAccount, uninstallPlugin } from "./installer";
import { TabWithOtherTab } from "./nav";
import { cl } from "./utils/consts";
import { enablePlugin, getPluginDescription, isInBlacklist, isInWhitelist, isPluginsExistent } from "./utils/utils";
import { shell } from "electron";
import { allPlugins, app, env, modules, utils } from "qqntim/renderer";
import { useEffect, useState } from "react";
const { fs } = modules;

interface PanelProps {
    account: QQNTim.API.Renderer.NT.LoginAccount;
    config: Required<QQNTim.Configuration>;
    setConfig: React.Dispatch<React.SetStateAction<Required<QQNTim.Configuration>>>;
}

export function Panel({ currentTab, account }: { currentTab: TabWithOtherTab; account: QQNTim.API.Renderer.NT.LoginAccount }) {
    const [config, setConfig] = useState<Required<QQNTim.Configuration>>(env.config);
    const [pluginsConfig, setPluginsConfig] = useState<Record<string, object>>(config.plugins.config || {});

    const saveConfigAndRestart = () => {
        fs.writeJSONSync(env.path.configFile, config);
        app.relaunch();
    };

    const resetConfigAndRestart = () => {
        fs.writeJSONSync(env.path.configFile, {});
        app.relaunch();
    };

    useEffect(
        () =>
            setConfig((prev) => {
                return { ...prev, plugins: { ...prev.plugins, config: pluginsConfig } };
            }),
        [pluginsConfig],
    );

    useEffect(() => {
        document.body.classList.toggle(cl.panel.open.c, !!currentTab.type);
        utils.waitForElement<HTMLElement>(".setting-title").then((element) => {
            if (element.__VUE__?.[0]?.props?.title && currentTab.title) element.__VUE__[0].props.title = currentTab.title;
        });
    }, [currentTab]);

    const panelProps: PanelProps = {
        account,
        config,
        setConfig,
    };

    return (
        <>
            {currentTab.type == "settings" ? <SettingsPanel {...panelProps} /> : currentTab.type == "plugins-manager" ? <PluginsManagerPanel {...panelProps} /> : currentTab.type == "plugin" ? <currentTab.node config={pluginsConfig} setConfig={setPluginsConfig} /> : null}
            <div className={cl.panel.save.c}>
                <Button onClick={() => resetConfigAndRestart()} small={false} primary={false}>
                    重置所有设置并重启
                </Button>
                <Button onClick={() => saveConfigAndRestart()} small={false} primary={true}>
                    保存并重启
                </Button>
            </div>
        </>
    );
}

function SettingsPanel({ config, setConfig }: PanelProps) {
    return (
        <>
            <SettingsSection title="版本信息">
                <div className={cl.panel.settings.versions.c}>
                    {[
                        ["QQNTim", process.versions.qqntim],
                        ["QQNT", process.versions.qqnt],
                        ["Electron", process.versions.electron],
                        ["Node.js", process.versions.node],
                        ["Chromium", process.versions.chrome],
                        ["V8", process.versions.v8],
                    ].map(([name, version]) => (
                        <div key={name} className={cl.panel.settings.versions.item.c}>
                            <h3>{name}</h3>
                            <div>{version}</div>
                        </div>
                    ))}
                </div>
            </SettingsSection>
            <SettingsSection title="选项">
                <SettingsBox>
                    {(
                        [
                            [
                                "显示详细日志输出",
                                "开启后,可以在控制台内查看到 IPC 通信、部分 Electron 对象的成员访问信息等。",
                                config.verboseLogging,
                                (state: boolean) =>
                                    setConfig((prev) => {
                                        return { ...prev, verboseLogging: state };
                                    }),
                            ],
                            [
                                "使用原版 DevTools",
                                "使用 Chromium DevTools 而不是 chii DevTools (Windows 版 9.8.5 及以上不可用)。",
                                config.useNativeDevTools,
                                (state) =>
                                    setConfig((prev) => {
                                        return { ...prev, useNativeDevTools: state };
                                    }),
                            ],
                            [
                                "禁用兼容性处理",
                                "禁用后,LiteLoader 可能将不能与 QQNTim 一起使用。",
                                config.disableCompatibilityProcessing,
                                (state) =>
                                    setConfig((prev) => {
                                        return { ...prev, disableCompatibilityProcessing: state };
                                    }),
                            ],
                        ] as [string, string, boolean, (state: boolean) => void][]
                    ).map(([title, description, value, setValue], idx, array) => (
                        // rome-ignore lint/suspicious/noArrayIndexKey: <explanation>
                        <SettingsBoxItem key={idx} title={title} description={[description]} isLast={idx == array.length - 1}>
                            <Switch checked={value} onToggle={setValue} />
                        </SettingsBoxItem>
                    ))}
                </SettingsBox>
            </SettingsSection>
        </>
    );
}

function PluginsManagerPanel({ account, config, setConfig }: PanelProps) {
    const [existentPlugins, setExistentPlugins] = useState<string[]>(isPluginsExistent());

    return Array.from(new Set([...Object.keys(allPlugins), account.uin]))
        .sort()
        .map((uin: string) => {
            const plugins = allPlugins[uin] || {};
            const requiresRestart = uin == account.uin || uin == "";
            const isEmpty = Object.keys(plugins).length == 0;
            if (uin != account.uin && isEmpty) return;
            return (
                <SettingsSection
                    key={uin}
                    title={uin == "" ? "对所有账号生效的插件" : `仅对账号 ${uin} 生效的插件`}
                    buttons={
                        <>
                            <Button onClick={() => installZipPluginsForAccount(uin, requiresRestart)} primary={false} small={true}>
                                安装插件压缩包 (.zip)
                            </Button>
                            <Button onClick={() => installFolderPluginsForAccount(uin, requiresRestart)} primary={false} small={true}>
                                安装插件文件夹
                            </Button>
                        </>
                    }
                >
                    <SettingsBox>
                        {!isEmpty ? (
                            Object.keys(plugins)
                                .sort()
                                .map((id, idx, array) => {
                                    const plugin = plugins[id];
                                    const inWhitelist = isInWhitelist(id, config.plugins.whitelist);
                                    const inBlacklist = isInBlacklist(id, config.plugins.blacklist);
                                    const description = getPluginDescription(plugin);

                                    if (!existentPlugins.includes(id)) return;
                                    return (
                                        <SettingsBoxItem key={id} title={plugin.manifest.name} description={description} isLast={idx == array.length - 1}>
                                            <Switch checked={!!(inWhitelist || (!inWhitelist && !inBlacklist))} onToggle={(state) => enablePlugin(setConfig, id, state, inWhitelist, inBlacklist)} />
                                            <Button onClick={() => shell.openPath(plugin.dir)} small={true} primary={false}>
                                                文件夹
                                            </Button>
                                            <Button onClick={() => uninstallPlugin(requiresRestart, plugin.dir).then((success) => success && setExistentPlugins((prev) => prev.filter((pluginId) => pluginId != id)))} small={true} primary={false}>
                                                删除
                                            </Button>
                                        </SettingsBoxItem>
                                    );
                                })
                        ) : (
                            <SettingsBoxItem title="此处还没有任何插件 :(" isLast={true} />
                        )}
                    </SettingsBox>
                </SettingsSection>
            );
        });
}


================================================
FILE: src/builtins/settings/src/qqntim-env.d.ts
================================================
/// <reference types="@flysoftbeta/qqntim-typings" />


================================================
FILE: src/builtins/settings/src/renderer.ts
================================================
import Entry from "./_renderer";
export default Entry;


================================================
FILE: src/builtins/settings/src/utils/consts.ts
================================================
export const cl = {
    nav: {
        c: "qqntim-settings-nav",
        item: {
            c: "qqntim-settings-nav-item",
        },
    },
    panel: {
        c: "qqntim-settings-panel",
        open: {
            c: "qqntim-settings-panel-open",
        },
        settings: {
            versions: {
                c: "qqntim-settings-panel-settings-versions",
                item: {
                    c: "qqntim-settings-panel-settings-versions-item",
                },
            },
        },
        section: {
            c: "qqntim-settings-panel-section",
            header: {
                c: "qqntim-settings-panel-section-header",
                title: {
                    c: "qqntim-settings-panel-section-header-title",
                },
                buttons: {
                    c: "qqntim-settings-panel-section-header-buttons",
                },
            },
            content: {
                c: "qqntim-settings-panel-section-content",
            },
        },
        box: {
            c: "qqntim-settings-panel-box",
            item: {
                c: "qqntim-settings-panel-box-item",
                last: {
                    c: "qqntim-settings-panel-box-item-last",
                },
                title: {
                    c: "qqntim-settings-panel-box-item-title",
                },
                description: {
                    c: "qqntim-settings-panel-box-item-description",
                },
            },
        },
        save: {
            c: "qqntim-settings-panel-save",
        },
    },
};


================================================
FILE: src/builtins/settings/src/utils/hooks.tsx
================================================
import { useEffect, useRef } from "react";

// Thanks https://learnersbucket.com/examples/interview/useprevious-hook-in-react/
export function usePrevious<T>(value: T) {
    const ref = useRef<T>();

    useEffect(() => {
        ref.current = value;
    }, [value]);

    return ref.current;
}


================================================
FILE: src/builtins/settings/src/utils/sep.ts
================================================
export { sep as s } from "path";


================================================
FILE: src/builtins/settings/src/utils/utils.ts
================================================
import { allPlugins, modules } from "qqntim/renderer";
const { fs } = modules;

export function isInWhitelist(id: string, whitelist?: string[]) {
    return !!(whitelist && !whitelist.includes(id));
}
export function isInBlacklist(id: string, blacklist?: string[]) {
    return !!blacklist?.includes(id);
}

function addItemToArray<T>(array: T[], item: T) {
    return [...array, item];
}
function removeItemFromArray<T>(array: T[], item: T) {
    return array.filter((value) => value != item);
}
export function enablePlugin(setConfig: React.Dispatch<React.SetStateAction<Required<QQNTim.Configuration>>>, id: string, enable: boolean, inWhitelist: boolean, inBlacklist: boolean) {
    setConfig((prev) => {
        let _config = prev;
        if (_config.plugins.whitelist && enable != inWhitelist)
            _config = {
                ..._config,
                plugins: {
                    ..._config.plugins,
                    whitelist: (enable ? addItemToArray : removeItemFromArray)(_config.plugins.whitelist!, id),
                },
            };
        else if (!_config.plugins.blacklist) _config.plugins.blacklist = [];
        if (_config.plugins.blacklist && enable == inBlacklist)
            _config = {
                ..._config,
                plugins: {
                    ..._config.plugins,
                    blacklist: (!enable ? addItemToArray : removeItemFromArray)(_config.plugins.blacklist!, id),
                },
            };
        return _config;
    });
}

export function isPluginsExistent() {
    const ids: string[] = [];
    Object.keys(allPlugins).forEach((uin) =>
        Object.keys(allPlugins[uin]).forEach((id) => {
            const plugin = allPlugins[uin][id];
            if (fs.existsSync(plugin.dir) && fs.statSync(plugin.dir).isDirectory()) ids.push(id);
        }),
    );
    return ids;
}

export function getPluginDescription(plugin: QQNTim.Plugin) {
    const versionText = [plugin.manifest.version, plugin.manifest.author].filter(Boolean).join(" - ");
    const warnText = [!plugin.meetRequirements && "当前环境不满足需求,未加载", plugin.manifest.manifestVersion != "3.0" && "插件使用了过时的插件标准,请提醒作者更新"].filter(Boolean).join("; ");
    const description = plugin.manifest.description || "该插件没有提供说明。";
    return [versionText, warnText && `警告: ${warnText}。`, description].filter(Boolean);
}


================================================
FILE: src/builtins/settings/tsconfig.json
================================================
{
    "compilerOptions": {
        "jsx": "react-jsx",
        "module": "CommonJS",
        "moduleResolution": "Node",
        "target": "ESNext",
        "resolveJsonModule": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "noEmit": true
    },
    "include": ["src"],
    "exclude": ["node_modules", "**/node_modules/*"]
}


================================================
FILE: src/common/global.ts
================================================
export const env = {} as QQNTim.Environment;
export const allPlugins = {} as QQNTim.Plugin.AllUsersPlugins;

export const setEnv = (value: QQNTim.Environment) => Object.assign(env, value);
export const setAllPlugins = (value: QQNTim.Plugin.AllUsersPlugins) => Object.assign(allPlugins, value);


================================================
FILE: src/common/ipc.ts
================================================
import { env } from "./global";
import { printObject } from "./utils/console";
import { isMainProcess } from "./utils/process";

const interruptIpcs: [QQNTim.IPC.InterruptFunction, QQNTim.IPC.InterruptIPCOptions | undefined][] = [];

function interruptIpc(args: QQNTim.IPC.Args<any>, direction: QQNTim.IPC.Direction, channel: string, sender?: Electron.WebContents) {
    for (const [func, options] of interruptIpcs) {
        if (options?.cmdName && (!args[1] || (args[1][0]?.cmdName != options?.cmdName && args[1][0] != options?.cmdName))) continue;
        if (options?.eventName && !args[0]?.eventName?.startsWith(`${options?.eventName}-`)) continue;
        if (options?.type && (!args[0] || args[0].type != options?.type)) continue;
        if (options?.direction && options?.direction != direction) continue;

        const ret = func(args, channel, sender);
        if (ret == false) return false;
    }

    return true;
}

export function handleIpc(args: QQNTim.IPC.Args<any>, direction: QQNTim.IPC.Direction, channel: string, sender?: Electron.WebContents) {
    if (args[0]?.eventName?.startsWith("ns-LoggerApi-")) return false;
    return interruptIpc(args, direction, channel, sender);
}

export function addInterruptIpc(func: QQNTim.IPC.InterruptFunction, options?: QQNTim.IPC.InterruptIPCOptions) {
    interruptIpcs.push([func, options]);
}

export function watchIpc() {
    if (env.config.verboseLogging && (env.config.useNativeDevTools || (!env.config.useNativeDevTools && isMainProcess))) {
        (["in", "out"] as QQNTim.IPC.Direction[]).forEach((type) => {
            addInterruptIpc((args, channel, sender) => console.debug(`[!Watch:IPC?${type == "in" ? "In" : "Out"}${sender ? `:${sender.id.toString()}` : ""}] ${channel}`, printObject(args)), { direction: type });
        });
    }
}


================================================
FILE: src/common/loader.ts
================================================
import { s } from "./sep";

const loadedPlugins: QQNTim.Plugin.LoadedPlugins = {};

function getUserPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin: string) {
    const userPlugins = allPlugins[uin];
    if (!userPlugins) {
        console.warn(`[!Loader] 账户 (${uin}) 没有插件,跳过加载`);
        return;
    }
    if (uin != "") console.log(`[!Loader] 正在为账户 (${uin}) 加载插件`);
    else console.log("[!Loader] 正在为所有账户加载插件");
    return userPlugins;
}

export function loadPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin: string, shouldInject: (injection: QQNTim.Plugin.Injection) => boolean, scripts: [QQNTim.Plugin, string][], stylesheets?: [QQNTim.Plugin, string][]) {
    const userPlugins = getUserPlugins(allPlugins, uin);
    if (!userPlugins) return false;

    for (const id in userPlugins) {
        if (loadedPlugins[id]) continue;
        const plugin = userPlugins[id];
        if (!plugin.loaded) continue;
        loadedPlugins[id] = plugin;
        console.log(`[!Loader] 正在加载插件:${id}`);

        plugin.injections.forEach((injection) => {
            const rendererInjection = injection as QQNTim.Plugin.InjectionRenderer;
            if (!shouldInject(injection)) return;
            stylesheets && rendererInjection.stylesheet && stylesheets.push([plugin, `${plugin.dir}${s}${rendererInjection.stylesheet}`]);
            injection.script && scripts.push([plugin, `${plugin.dir}${s}${injection.script}`]);
        });
    }

    return true;
}


================================================
FILE: src/common/patch.ts
================================================
const modules: Record<string, any> = {};

export function defineModules(newModules: Record<string, any>) {
    for (const name in newModules) {
        if (modules[name]) throw new Error(`模块名已经被使用:${name}`);
        modules[name] = newModules[name];
    }
}

export function getModule(name: string) {
    return modules[name];
}


================================================
FILE: src/common/paths.ts
================================================
import { s } from "./sep";

export const dataDir = process.env["QQNTIM_HOME"] || (process.platform == "win32" ? `${process.env["UserProfile"]}${s}.qqntim` : `${process.env["HOME"]}${s}.local${s}share${s}QQNTim`);
export const configFile = `${dataDir}${s}config.json`;
export const pluginDir = `${dataDir}${s}plugins`;
export const pluginPerUserDir = `${dataDir}${s}plugins-user`;


================================================
FILE: src/common/sep.ts
================================================
export { sep as s } from "path";


================================================
FILE: src/common/utils/console.ts
================================================
import { isMainProcess } from "./process";
import supportsColor from "supports-color";
import { inspect } from "util";

export const hasColorSupport = !!supportsColor.stdout;

export function printObject(object: any, enableColorSupport = isMainProcess && hasColorSupport) {
    return inspect(object, {
        compact: true,
        depth: null,
        showHidden: true,
        colors: enableColorSupport,
    });
}


================================================
FILE: src/common/utils/freePort.ts
================================================
import { AddressInfo, createServer } from "net";

export function findFreePort() {
    const server = createServer().listen(0);
    const { port } = server.address()! as AddressInfo;
    server.close();
    return port;
}


================================================
FILE: src/common/utils/ntVersion.ts
================================================
import { s } from "../sep";
import { readJSONSync } from "fs-extra";

export function getCurrentNTVersion() {
    let version: string;
    if (process.platform == "win32") {
        version = readJSONSync(`${__dirname}${s}..${s}versions${s}config.json`)?.curVersion;
    } else if (process.platform == "linux" || process.platform == "darwin") {
        version = readJSONSync(`${__dirname}${s}..${s}package.json`)?.version;
    } else throw new Error(`unsupported platform: ${process.platform}`);
    if (!version) throw new Error("cannot determine QQNT version");
    return version;
}


================================================
FILE: src/common/utils/process.ts
================================================
import { app } from "electron";

export const isMainProcess = !!app as boolean;


================================================
FILE: src/common/version.ts
================================================
import { version } from "../../package.json";
import { getCurrentNTVersion } from "./utils/ntVersion";

export function mountVersion() {
    const ntVersion = getCurrentNTVersion();
    Object.defineProperties(process.versions, {
        qqnt: { value: ntVersion, writable: false },
        qqntim: { value: version, writable: false },
    });
}


================================================
FILE: src/common/watch.ts
================================================
import { env } from "./global";
import { printObject } from "./utils/console";

type Constructor<T> = new (...args: any[]) => T;

export function getter<T, R extends keyof T>(scope: string | undefined, target: T, p: R) {
    if (p == "__qqntim_original_object") return target;
    if (typeof target[p] == "function")
        return (...argArray: any[]) => {
            const res = (target[p] as Function).apply(target, argArray);
            if (scope && env.config.verboseLogging) console.debug(`[!Watch:${scope}] 调用:${p as string}`, printObject(argArray), res != target ? printObject(res) : "[已隐藏]");
            return res;
        };
    else {
        const res = target[p];
        if (scope && env.config.verboseLogging) console.debug(`[!Watch:${scope}] 获取:${p as string}`);
        return res;
    }
}

export function setter<T, R extends keyof T>(scope: string | undefined, _: T, p: R, newValue: T[R]) {
    if (scope && env.config.verboseLogging) console.debug(`[!Watch:${scope}] 设置:${p as string}`, printObject(newValue));
    return true;
}

export function construct<F, T extends Constructor<F>>(scope: string | undefined, target: T, argArray: any[]) {
    if (scope && env.config.verboseLogging) console.debug(`[!Watch:${scope}] 构造新实例:`, printObject(argArray));
    return new target(...argArray);
}

export function apply<T extends Function>(target: T, thisArg: any, argArray: any[]) {
    return target.apply(thisArg, argArray);
}


================================================
FILE: src/electron/README.txt
================================================
Silence is golden.


================================================
FILE: src/electron/package.json
================================================
{
    "name": "electron",
    "private": true,
    "version": "25.2.0"
}


================================================
FILE: src/main/api.ts
================================================
import { env } from "../common/global";
import { addInterruptIpc } from "../common/ipc";
import { defineModules } from "../common/patch";
import { mountVersion } from "../common/version";
import { addInterruptWindowArgs, addInterruptWindowCreation } from "./patch";
import { plugins } from "./plugins";
import * as fs from "fs-extra";

export let api: typeof QQNTim.API.Main;

export function initAPI() {
    mountVersion();

    api = {
        allPlugins: plugins,
        env: env,
        interrupt: {
            ipc: addInterruptIpc,
            windowCreation: addInterruptWindowCreation,
            windowArgs: addInterruptWindowArgs,
        },
        defineModules: defineModules,
        modules: {
            fs: fs,
        },
    };

    defineModules({ "qqntim/main": api });
}


================================================
FILE: src/main/compatibility.ts
================================================
import { env } from "../common/global";
import { existsSync } from "fs-extra";
import { resolve } from "path";

export function loadCustomLoaders() {
    if (env.config.disableCompatibilityProcessing) return;
    console.log("[!Compatibility] 正在进行兼容性处理");
    env.config.pluginLoaders.map((loader: string) => {
        const path = resolve(__dirname, "..", loader);
        if (existsSync(path)) require(path);
    });
}


================================================
FILE: src/main/config.ts
================================================
import { configFile, dataDir, pluginDir, pluginPerUserDir } from "../common/paths";
import * as fs from "fs-extra";

function toBoolean(item: boolean | undefined, env: string, defaultValue: boolean) {
    const envValue = process.env[env];
    return envValue ? !!parseInt(envValue) : typeof item == "boolean" ? item : defaultValue;
}

function toStringArray<T extends string[], R extends T | undefined>(item: R, env: string, defaultValue: R) {
    const envValue = process.env[env];
    return envValue ? envValue.split(";") : item && item instanceof Array ? item : defaultValue;
}

// function toNumberArray(
//     item: number[] | undefined,
//     env: string,
//     defaultValue: number[] | undefined,
//     isFloat = false
// ) {
//     const envValue = process.env[env];
//     return envValue
//         ? envValue
//               .split(";")
//               .map((value) => (isFloat ? parseFloat(value) : parseInt(value)))
//         : item instanceof Array
//         ? item
//         : defaultValue;
// }

export function getEnvironment(config: QQNTim.Configuration): QQNTim.Environment {
    return {
        config: {
            plugins: {
                whitelist: toStringArray(config.plugins?.whitelist, "QQNTIM_PLUGINS_WHITELIST", undefined),
                blacklist: toStringArray(config.plugins?.blacklist, "QQNTIM_PLUGINS_BLACKLIST", undefined),
                config: config.plugins?.config || {},
            },
            pluginLoaders: toStringArray(config.pluginLoaders, "QQNTIM_PLUGIN_LOADER", ["LiteLoader", "LiteLoaderQQNT"]),
            verboseLogging: toBoolean(config.verboseLogging, "QQNTIM_VERBOSE_LOGGING", false),
            useNativeDevTools: toBoolean(config.useNativeDevTools, "QQNTIM_USE_NATIVE_DEVTOOLS", false),
            disableCompatibilityProcessing: toBoolean(config.disableCompatibilityProcessing, "QQNTIM_NO_COMPATIBILITY_PROCESSING", false),
        },
        path: {
            dataDir,
            configFile,
            pluginDir,
            pluginPerUserDir,
        },
    };
}

function prepareDataDir() {
    fs.ensureDirSync(dataDir);
    fs.ensureDirSync(pluginDir);
    fs.ensureDirSync(pluginPerUserDir);
    if (!fs.existsSync(configFile)) fs.writeJSONSync(configFile, {});
}

export function loadConfig() {
    prepareDataDir();
    const config = fs.readJSONSync(configFile) || {};
    return getEnvironment(config);
}


================================================
FILE: src/main/debugger.ts
================================================
import { env } from "../common/global";
import { findFreePort } from "../common/utils/freePort";
import axios from "axios";
import { start } from "chii/server";
import { BrowserWindow } from "electron";

export let debuggerHost = "";
export let debuggerPort = -1;
export let debuggerOrigin = "";

export async function initDebugger() {
    if (!env.config.useNativeDevTools) {
        debuggerPort = findFreePort();
        debuggerHost = "127.0.0.1";
        debuggerOrigin = `http://${debuggerHost}:${debuggerPort}`;

        console.log(`[!Debugger] 正在启动 chii 调试器:${debuggerOrigin}`);
        await start({
            host: debuggerHost,
            port: debuggerPort,
            useHttps: false,
        });
    }
}

async function listChiiTargets() {
    const res = await axios.get(`${debuggerOrigin}/targets`);
    return (res.data.targets as any[]).map((target) => [target.title, target.id]);
}

export async function createDebuggerWindow(debuggerId: string, win: BrowserWindow) {
    const targets = await listChiiTargets();
    for (const [id, target] of targets) {
        if (id == debuggerId) {
            const url = `${debuggerOrigin}/front_end/chii_app.html?ws=${debuggerHost}:${debuggerPort}/client/${(Math.random() * 6).toString()}?target=${target}`;

            console.log(`[!Debugger] 正在打开 chii 调试器窗口:${url}`);

            const debuggerWin = new BrowserWindow({
                width: 800,
                height: 600,
                show: true,
                webPreferences: {
                    webSecurity: false,
                    allowRunningInsecureContent: true,
                    devTools: false,
                    nodeIntegration: false,
                    nodeIntegrationInSubFrames: false,
                    contextIsolation: true,
                },
            });

            debuggerWin.webContents.loadURL(url);

            win.on("closed", () => debuggerWin.destroy());

            break;
        }
    }
}


================================================
FILE: src/main/loader.ts
================================================
import { loadPlugins } from "../common/loader";

let scripts: [QQNTim.Plugin, string][] = [];

function shouldInject(injection: QQNTim.Plugin.Injection) {
    return injection.type == "main";
}

export function applyPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin = "") {
    loadPlugins(allPlugins, uin, shouldInject, scripts);
    applyScripts();

    return true;
}

function applyScripts() {
    scripts = scripts.filter(([plugin, script]) => {
        try {
            const mod = require(script);
            if (mod) new ((mod.default || mod) as typeof QQNTim.Entry.Main)();
            return false;
        } catch (reason) {
            console.error(`[!Loader] 运行此插件脚本时出现意外错误:${script},请联系插件作者 (${plugin.manifest.author}) 解决`);
            console.error(reason);
        }
        return true;
    });
}


================================================
FILE: src/main/main.ts
================================================
/**
 * @license
 * Copyright (c) Flysoft.
 */

import { setAllPlugins, setEnv } from "../common/global";
import { watchIpc } from "../common/ipc";
import { initAPI } from "./api";
import { loadCustomLoaders } from "./compatibility";
import { loadConfig } from "./config";
import { initDebugger } from "./debugger";
import { applyPlugins } from "./loader";
import { patchModuleLoader } from "./patch";
import { collectPlugins, plugins } from "./plugins";

setEnv(loadConfig());
initDebugger();
patchModuleLoader();
watchIpc();
loadCustomLoaders();
collectPlugins();
setAllPlugins(plugins);
initAPI();
applyPlugins(plugins);
console.log("[!Main] QQNTim 加载成功");
require("./index.js");


================================================
FILE: src/main/patch.ts
================================================
import { env } from "../common/global";
import { handleIpc } from "../common/ipc";
import { defineModules, getModule } from "../common/patch";
import { s } from "../common/sep";
import { hasColorSupport } from "../common/utils/console";
import { apply, construct, getter, setter } from "../common/watch";
import { createDebuggerWindow, debuggerOrigin } from "./debugger";
import { applyPlugins } from "./loader";
import { plugins } from "./plugins";
import { enable, initialize } from "@electron/remote/main";
import { BrowserWindow, Menu, MenuItem, app, dialog, ipcMain } from "electron";
import { Module } from "module";

const interruptWindowArgs: QQNTim.WindowCreation.InterruptArgsFunction[] = [];
const interruptWindowCreation: QQNTim.WindowCreation.InterruptFunction[] = [];

ipcMain.on("___!boot", (event) => {
    if (!event.returnValue) event.returnValue = { enabled: false };
});

ipcMain.on("___!log", (event, level, ...args) => {
    console[{ 0: "debug", 1: "log", 2: "info", 3: "warn", 4: "error" }[level] || "log"](`[!Renderer:Log:${event.sender.id}]`, ...args);
});

ipcMain.handle("___!dialog", (event, method: string, options: object) => dialog[method](BrowserWindow.fromWebContents(event.sender), options));

function patchBrowserWindow() {
    const windowMenu: Electron.MenuItem[] = [
        new MenuItem({
            label: "刷新",
            role: "reload",
            accelerator: "F5",
        }),
        new MenuItem({
            label: "开发者工具",
            accelerator: "F12",
            ...(env.config.useNativeDevTools
                ? { role: "toggleDevTools" }
                : {
                      click: (_, win) => {
                          if (!win) return;
                          const debuggerId = win.webContents.id.toString();
                          createDebuggerWindow(debuggerId, win);
                      },
                  }),
        }),
    ];
    return new Proxy(BrowserWindow, {
        apply(target, thisArg, argArray) {
            return apply(target, thisArg, argArray);
        },
        get(target, p) {
            return getter(undefined, target, p as any);
        },
        set(target, p, newValue) {
            return setter(undefined, target, p as any, newValue);
        },
        construct(target, [options]: [Electron.BrowserWindowConstructorOptions]) {
            let patchedArgs: Electron.BrowserWindowConstructorOptions = {
                ...options,
                webPreferences: {
                    ...options.webPreferences,
                    preload: `${__dirname}${s}qqntim-renderer.js`,
                    webSecurity: false,
                    allowRunningInsecureContent: true,
                    nodeIntegration: true,
                    nodeIntegrationInSubFrames: true,
                    contextIsolation: false,
                    devTools: env.config.useNativeDevTools,
                    sandbox: false,
                },
            };
            interruptWindowArgs.forEach((func) => {
                patchedArgs = func(patchedArgs);
            });
            const win = construct("BrowserWindow", target, [patchedArgs]) as BrowserWindow;

            const webContentsId = win.webContents.id.toString();

            let thirdpartyPreloads: string[] = win.webContents.session.getPreloads();
            win.webContents.session.setPreloads([]);
            enable(win.webContents);

            const session = new Proxy(win.webContents.session, {
                get(target, p) {
                    const res = getter(undefined, target, p as any);
                    if (p == "setPreloads")
                        return (newPreloads: string[]) => {
                            thirdpartyPreloads = newPreloads;
                        };
                    return res;
                },
                set(target, p, newValue) {
                    return setter(undefined, target, p as any, newValue);
                },
            });
            const webContents = new Proxy(win.webContents, {
                get(target, p) {
                    const res = getter(undefined, target, p as any);
                    if (p == "session") return session;
                    return res;
                },
                set(target, p, newValue) {
                    return setter(undefined, target, p as any, newValue);
                },
            });

            const send = win.webContents.send;
            win.webContents.send = (channel: string, ...args: QQNTim.IPC.Args<any>) => {
                handleIpc(args, "out", channel);
                return send.call(win.webContents, channel, ...args);
            };
            win.webContents.on("ipc-message", (_, channel, ...args) => {
                if (!handleIpc(args as any, "in", channel, win.webContents)) throw new Error("QQNTim 已强行中断了一条 IPC 消息");
                if (channel == "___!apply_plugins") applyPlugins(plugins, args[0] as string);
            });
            win.webContents.on("ipc-message-sync", (event, channel, ...args) => {
                handleIpc(args as any, "in", channel, win.webContents);
                if (channel == "___!boot") {
                    event.returnValue = {
                        enabled: true,
                        preload: Array.from(new Set([...thirdpartyPreloads, options.webPreferences?.preload].filter(Boolean))),
                        debuggerOrigin: !env.config.useNativeDevTools && debuggerOrigin,
                        webContentsId: webContentsId,
                        plugins: plugins,
                        env: env,
                        hasColorSupport: hasColorSupport,
                    };
                } else if (channel == "___!browserwindow_api") {
                    event.returnValue = win[args[0][0]](...args[0][1]);
                } else if (channel == "___!app_api") {
                    event.returnValue = app[args[0][0]](...args[0][1]);
                }
            });

            const setMenu = win.setMenu;
            win.setMenu = (menu) => {
                const patchedMenu = Menu.buildFromTemplate([...(menu?.items || []), ...windowMenu]);
                return setMenu.call(win, patchedMenu);
            };
            win.setMenu(null);

            return new Proxy(win, {
                get(target, p) {
                    const res = getter(undefined, target, p as any);
                    if (p == "webContents") return webContents;
                    return res;
                },
                set(target, p, newValue) {
                    return setter(undefined, target, p as any, newValue);
                },
            });
        },
    });
}

export function addInterruptWindowCreation(func: QQNTim.WindowCreation.InterruptFunction) {
    interruptWindowCreation.push(func);
}

export function addInterruptWindowArgs(func: QQNTim.WindowCreation.InterruptArgsFunction) {
    interruptWindowArgs.push(func);
}

export function patchModuleLoader() {
    // 阻止 Electron 默认菜单生成
    Menu.setApplicationMenu(null);
    initialize();

    const patchedElectron: typeof Electron.CrossProcessExports = {
        ...require("electron"),
        BrowserWindow: patchBrowserWindow(),
    };

    defineModules({ electron: patchedElectron });

    const loadBackend = (Module as any)._load;
    (Module as any)._load = (request: string, parent: NodeModule, isMain: boolean) => {
        return getModule(request) || loadBackend(request, parent, isMain);
    };
}


================================================
FILE: src/main/plugins.ts
================================================
import { env } from "../common/global";
import { s } from "../common/sep";
import * as fs from "fs-extra";
import * as os from "os";
import * as semver from "semver";

const supportedManifestVersions: QQNTim.Manifest.ManifestVersion[] = ["3.0"];
export const plugins: QQNTim.Plugin.AllUsersPlugins = {};

function isPluginEnabled(manifest: QQNTim.Manifest) {
    if (env.config.plugins.whitelist) return env.config.plugins.whitelist.includes(manifest.id);
    else if (env.config.plugins.blacklist) return !env.config.plugins.blacklist.includes(manifest.id);
    else return true;
}

function isPluginRequirementsMet(manifest: QQNTim.Manifest) {
    if (manifest.requirements?.os) {
        let meetRequirements = false;
        const osRelease = os.release();
        for (const item of manifest.requirements.os) {
            if (item.platform != process.platform) continue;
            if (item.lte && !semver.lte(item.lte, osRelease)) continue;
            if (item.lt && !semver.lt(item.lt, osRelease)) continue;
            if (item.gte && !semver.gte(item.gte, osRelease)) continue;
            if (item.gt && !semver.gt(item.gt, osRelease)) continue;
            if (item.eq && !semver.eq(item.eq, osRelease)) continue;
            meetRequirements = true;
            break;
        }
        if (!meetRequirements) {
            return false;
        }
    }

    return true;
}

export function parsePlugin(dir: string) {
    try {
        const manifestFile = `${dir}${s}qqntim.json`;
        if (!fs.existsSync(manifestFile)) return null;
        const manifest = fs.readJSONSync(manifestFile) as QQNTim.Manifest;
        if (!manifest.manifestVersion) manifest.manifestVersion = supportedManifestVersions[0];
        else if (!supportedManifestVersions.includes(manifest.manifestVersion)) throw new TypeError(`此插件包含一个无效的清单版本:${manifest.manifestVersion},支持的版本有:${supportedManifestVersions.join(", ")}`);

        const meetRequirements = isPluginRequirementsMet(manifest);
        const enabled = isPluginEnabled(manifest);
        const loaded = meetRequirements && enabled;
        if (!meetRequirements) console.error(`[!Plugins] 跳过加载插件:${manifest.id}(当前环境不满足要求)`);
        else if (!enabled) console.error(`[!Plugins] 跳过加载插件:${manifest.id}(插件已被禁用)`);

        return {
            enabled: enabled,
            meetRequirements: meetRequirements,
            loaded: loaded,
            id: manifest.id,
            dir: dir,
            injections: manifest.injections.map((injection) => {
                return injection.type == "main"
                    ? { ...injection }
                    : {
                          ...injection,
                          pattern: injection.pattern && new RegExp(injection.pattern),
                      };
            }),
            manifest: manifest,
        } as QQNTim.Plugin;
    } catch (reason) {
        console.error("[!Plugins] 解析插件时出现意外错误:", dir);
        console.error(reason);
        return null;
    }
}

function collectPluginsFromDir(baseDir: string, uin = "") {
    const folders = fs.readdirSync(baseDir);
    if (!plugins[uin]) plugins[uin] = {};
    folders.forEach((folder) => {
        const folderPath = `${baseDir}${s}${folder}`;
        if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
            const plugin = parsePlugin(folderPath);
            if (!plugin) return;
            if (plugins[uin][plugin.id]) return;
            plugins[uin][plugin.id] = plugin;
        }
    });
}

export function collectPlugins() {
    collectPluginsFromDir(`${__dirname}${s}builtins`);
    collectPluginsFromDir(env.path.pluginDir);
    const folders = fs.readdirSync(env.path.pluginPerUserDir);
    folders.forEach((folder) => {
        const folderPath = `${env.path.pluginPerUserDir}${s}${folder}`;
        if (fs.statSync(folderPath).isDirectory()) {
            collectPluginsFromDir(folderPath, folder);
        }
    });
}


================================================
FILE: src/qqntim-env.d.ts
================================================
/// <reference types="@flysoftbeta/qqntim-typings" />


================================================
FILE: src/renderer/api/app.ts
================================================
import { ipcRenderer } from "electron";

class AppAPI implements QQNTim.API.Renderer.AppAPI {
    relaunch() {
        ipcRenderer.sendSync("___!app_api", ["relaunch", []]);
        this.quit();
    }

    quit() {
        ipcRenderer.sendSync("___!app_api", ["quit", []]);
    }

    exit() {
        ipcRenderer.sendSync("___!app_api", ["exit", []]);
    }
}

export const appApi = new AppAPI();


================================================
FILE: src/renderer/api/browserWindow.ts
================================================
import { ipcRenderer } from "electron";

class BrowserWindowAPI implements QQNTim.API.Renderer.BrowserWindowAPI {
    setSize(width: number, height: number) {
        ipcRenderer.sendSync(
            "___!browserwindow_api",
            {
                eventName: "QQNTIM_BROWSERWINDOW_API",
            },
            ["setSize", [width, height]],
        );
    }

    setMinimumSize(width: number, height: number) {
        ipcRenderer.sendSync(
            "___!browserwindow_api",
            {
                eventName: "QQNTIM_BROWSERWINDOW_API",
            },
            ["setMinimumSize", [width, height]],
        );
    }
}

export const browserWindowApi = new BrowserWindowAPI();


================================================
FILE: src/renderer/api/dialog.ts
================================================
import { ipcRenderer } from "electron";

class DialogAPI implements QQNTim.API.Renderer.DialogAPI {
    async confirm(message = "") {
        const res = await this.messageBox({ message, buttons: ["确定", "取消"], defaultId: 0, type: "question" });
        return res.response == 0;
    }

    async alert(message = "") {
        await this.messageBox({ message, buttons: ["确定"], defaultId: 0, type: "info" });
        return;
    }

    messageBox(options: Electron.MessageBoxOptions): Promise<Electron.MessageBoxReturnValue> {
        return ipcRenderer.invoke("___!dialog", "showMessageBox", options);
    }

    openDialog(options: Electron.OpenDialogOptions): Promise<Electron.OpenDialogReturnValue> {
        return ipcRenderer.invoke("___!dialog", "showOpenDialog", options);
    }

    saveDialog(options: Electron.SaveDialogOptions): Promise<Electron.SaveDialogReturnValue> {
        return ipcRenderer.invoke("___!dialog", "showSaveDialog", options);
    }
}

export const dialogApi = new DialogAPI();


================================================
FILE: src/renderer/api/getVueId.ts
================================================
export function getVueId(element: HTMLElement) {
    let vueId: string | undefined;

    for (const item in element.dataset) {
        if (item.startsWith("v"))
            vueId = `data-${item
                .split("")
                .map((item) => {
                    const low = item.toLocaleLowerCase();
                    if (low != item) return `-${low}`;
                    else return low;
                })
                .join("")}`;
    }

    return vueId;
}


================================================
FILE: src/renderer/api/index.ts
================================================
import { allPlugins, env } from "../../common/global";
import { addInterruptIpc } from "../../common/ipc";
import { defineModules } from "../../common/patch";
import { mountVersion } from "../../common/version";
import { appApi } from "./app";
import { browserWindowApi } from "./browserWindow";
import { dialogApi } from "./dialog";
import { getVueId } from "./getVueId";
import { nt } from "./nt";
import { ntCall } from "./nt/call";
import { waitForElement } from "./waitForElement";
import { windowLoadPromise } from "./windowLoadPromise";
import * as fs from "fs-extra";

export let api: typeof QQNTim.API.Renderer;

export function initAPI() {
    mountVersion();
    nt.init();

    api = {
        allPlugins: allPlugins,
        env: env,
        interrupt: {
            ipc: addInterruptIpc,
        },
        nt: nt,
        browserWindow: browserWindowApi,
        app: appApi,
        dialog: dialogApi,
        modules: {
            fs: fs,
        },
        defineModules: defineModules,
        utils: {
            waitForElement: waitForElement,
            getVueId: getVueId,
            ntCall: ntCall,
        },
        windowLoadPromise: windowLoadPromise,
    };

    defineModules({ "qqntim/renderer": api });
}


================================================
FILE: src/renderer/api/nt/call.ts
================================================
import { addInterruptIpc } from "../../../common/ipc";
import { webContentsId } from "../../main";
import { randomUUID } from "crypto";
import { ipcRenderer } from "electron";

class NTCallError extends Error {
    public code: number;
    public message: string;
    constructor(code: number, message: string) {
        super();
        this.code = code;
        this.message = message;
    }
}

const pendingCallbacks: Record<string, Function> = {};

addInterruptIpc(
    (args) => {
        const id = args[0].callbackId;
        if (pendingCallbacks[id]) {
            pendingCallbacks[id](args);
            delete pendingCallbacks[id];
            return false;
        }
    },
    {
        direction: "in",
    },
);

export function ntCall(eventName: string, cmdName: string, args: any[], isRegister = false) {
    return new Promise<any>((resolve, reject) => {
        const uuid = randomUUID();
        pendingCallbacks[uuid] = (args: QQNTim.IPC.Args<QQNTim.IPC.Response>) => {
            if (args[1] && args[1].result != undefined && args[1].result != 0) reject(new NTCallError(args[1].result, args[1].errMsg));
            else resolve(args[1]);
        };
        ipcRenderer.send(
            `IPC_UP_${webContentsId}`,
            {
                type: "request",
                callbackId: uuid,
                eventName: `${eventName}-${webContentsId}${isRegister ? "-register" : ""}`,
            },
            [cmdName, ...args],
        );
    });
}


================================================
FILE: src/renderer/api/nt/constructor.ts
================================================
import { ntMedia } from "./media";

export function constructTextElement(ele: any): QQNTim.API.Renderer.NT.MessageElementText {
    return {
        type: "text",
        content: ele.textElement.content,
        raw: ele,
    };
}

export function constructImageElement(ele: any, msg: any): QQNTim.API.Renderer.NT.MessageElementImage {
    return {
        type: "image",
        file: ele.picElement.sourcePath,
        downloadedPromise: ntMedia.downloadMedia(msg.msgId, ele.elementId, msg.peerUid, msg.chatType, ele.picElement.thumbPath.get(0), ele.picElement.sourcePath),
        raw: ele,
    };
}
export function constructFaceElement(ele: any): QQNTim.API.Renderer.NT.MessageElementFace {
    return {
        type: "face",
        faceIndex: ele.faceElement.faceIndex,
        faceType: ele.faceElement.faceType == 1 ? "normal" : ele.faceElement.faceType == 2 ? "normal-extended" : ele.faceElement.faceType == 3 ? "super" : ele.faceElement.faceType,
        faceSuperIndex: ele.faceElement.stickerId && parseInt(ele.faceElement.stickerId),
        raw: ele,
    };
}
export function constructRawElement(ele: any): QQNTim.API.Renderer.NT.MessageElementRaw {
    return {
        type: "raw",
        raw: ele,
    };
}
export function constructMessage(msg: any): QQNTim.API.Renderer.NT.Message {
    const downloadedPromises: Promise<void>[] = [];
    const elements = (msg.elements as any[]).map((ele): QQNTim.API.Renderer.NT.MessageElement => {
        if (ele.elementType == 1) return constructTextElement(ele);
        else if (ele.elementType == 2) {
            const element = constructImageElement(ele, msg);
            downloadedPromises.push(element.downloadedPromise);
            return element;
        } else if (ele.elementType == 6) return constructFaceElement(ele);
        else return constructRawElement(ele);
    });
    return {
        allDownloadedPromise: Promise.all(downloadedPromises),
        peer: {
            uid: msg.peerUid,
            name: msg.peerName,
            chatType: msg.chatType == 1 ? "friend" : msg.chatType == 2 ? "group" : "others",
        },
        sender: {
            uid: msg.senderUid,
            memberName: msg.sendMemberName || msg.sendNickName,
            nickName: msg.sendNickName,
        },
        elements: elements,
        raw: msg,
    };
}
export function constructUser(user: any): QQNTim.API.Renderer.NT.User {
    return {
        uid: user.uid,
        qid: user.qid,
        uin: user.uin,
        avatarUrl: user.avatarUrl,
        nickName: user.nick,
        bio: user.longNick,
        sex: { 1: "male", 2: "female", 255: "unset", 0: "unset" }[user.sex] || "others",
        raw: user,
    };
}
export function constructGroup(group: any): QQNTim.API.Renderer.NT.Group {
    return {
        uid: group.groupCode,
        avatarUrl: group.avatarUrl,
        name: group.groupName,
        role: { 4: "master", 3: "moderator", 2: "member" }[group.memberRole] || "others",
        maxMembers: group.maxMember,
        members: group.memberCount,
        raw: group,
    };
}


================================================
FILE: src/renderer/api/nt/destructor.ts
================================================
export function destructTextElement(element: QQNTim.API.Renderer.NT.MessageElementText) {
    return {
        elementType: 1,
        elementId: "",
        textElement: {
            content: element.content,
            atType: 0,
            atUid: "",
            atTinyId: "",
            atNtUid: "",
        },
    };
}

export function destructImageElement(element: QQNTim.API.Renderer.NT.MessageElementImage, picElement: any) {
    return {
        elementType: 2,
        elementId: "",
        picElement: picElement,
    };
}

export function destructFaceElement(element: QQNTim.API.Renderer.NT.MessageElementFace) {
    return {
        elementType: 6,
        elementId: "",
        faceElement: {
            faceIndex: element.faceIndex,
            faceType: element.faceType == "normal" ? 1 : element.faceType == "normal-extended" ? 2 : element.faceType == "super" ? 3 : element.faceType
Download .txt
gitextract_sv6t5qoj/

├── .gitattributes
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── .yarn/
│   └── sdks/
│       ├── integrations.yml
│       └── typescript/
│           ├── bin/
│           │   ├── tsc
│           │   └── tsserver
│           ├── lib/
│           │   ├── tsc.js
│           │   ├── tsserver.js
│           │   ├── tsserverlibrary.js
│           │   └── typescript.js
│           └── package.json
├── COPYING
├── COPYING.LESSER
├── DEVELOPMENT.md
├── MANUAL.md
├── README.md
├── build.ts
├── examples/
│   └── NT-API/
│       ├── consts.js
│       ├── qqntim.json
│       ├── renderer.js
│       └── settings.js
├── package.json
├── publish/
│   ├── _/
│   │   ├── install.ps1
│   │   └── uninstall.ps1
│   ├── install.cmd
│   ├── install.sh
│   ├── install_macos.sh
│   ├── uninstall.cmd
│   ├── uninstall.sh
│   └── uninstall_macos.sh
├── rome.json
├── scripts/
│   ├── pack.ps1
│   ├── pack.sh
│   ├── start.ps1
│   └── start.sh
├── src/
│   ├── builtins/
│   │   └── settings/
│   │       ├── package.json
│   │       ├── publish/
│   │       │   ├── qqntim.json
│   │       │   └── style.css
│   │       ├── src/
│   │       │   ├── _renderer.tsx
│   │       │   ├── exports/
│   │       │   │   ├── components.tsx
│   │       │   │   └── index.ts
│   │       │   ├── installer.ts
│   │       │   ├── main.ts
│   │       │   ├── nav.tsx
│   │       │   ├── panel.tsx
│   │       │   ├── qqntim-env.d.ts
│   │       │   ├── renderer.ts
│   │       │   └── utils/
│   │       │       ├── consts.ts
│   │       │       ├── hooks.tsx
│   │       │       ├── sep.ts
│   │       │       └── utils.ts
│   │       └── tsconfig.json
│   ├── common/
│   │   ├── global.ts
│   │   ├── ipc.ts
│   │   ├── loader.ts
│   │   ├── patch.ts
│   │   ├── paths.ts
│   │   ├── sep.ts
│   │   ├── utils/
│   │   │   ├── console.ts
│   │   │   ├── freePort.ts
│   │   │   ├── ntVersion.ts
│   │   │   └── process.ts
│   │   ├── version.ts
│   │   └── watch.ts
│   ├── electron/
│   │   ├── README.txt
│   │   └── package.json
│   ├── main/
│   │   ├── api.ts
│   │   ├── compatibility.ts
│   │   ├── config.ts
│   │   ├── debugger.ts
│   │   ├── loader.ts
│   │   ├── main.ts
│   │   ├── patch.ts
│   │   └── plugins.ts
│   ├── qqntim-env.d.ts
│   ├── renderer/
│   │   ├── api/
│   │   │   ├── app.ts
│   │   │   ├── browserWindow.ts
│   │   │   ├── dialog.ts
│   │   │   ├── getVueId.ts
│   │   │   ├── index.ts
│   │   │   ├── nt/
│   │   │   │   ├── call.ts
│   │   │   │   ├── constructor.ts
│   │   │   │   ├── destructor.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── media.ts
│   │   │   │   └── watcher.ts
│   │   │   ├── waitForElement.ts
│   │   │   └── windowLoadPromise.ts
│   │   ├── debugger.ts
│   │   ├── loader.ts
│   │   ├── main.ts
│   │   ├── patch.ts
│   │   └── vueHelper.ts
│   └── typings/
│       ├── COPYING
│       ├── COPYING.LESSER
│       ├── electron.d.ts
│       ├── index.d.ts
│       ├── package.json
│       └── tsconfig.json
└── tsconfig.json
Download .txt
SYMBOL INDEX (1646 symbols across 46 files)

FILE: .yarn/sdks/typescript/lib/tsserver.js
  function toEditorPath (line 32) | function toEditorPath(str) {
  function fromEditorPath (line 120) | function fromEditorPath(str) {
  method onMessage (line 168) | onMessage(/** @type {string | object} */ message) {
  method send (line 207) | send(/** @type {any} */ msg) {

FILE: .yarn/sdks/typescript/lib/tsserverlibrary.js
  function toEditorPath (line 32) | function toEditorPath(str) {
  function fromEditorPath (line 120) | function fromEditorPath(str) {
  method onMessage (line 168) | onMessage(/** @type {string | object} */ message) {
  method send (line 207) | send(/** @type {any} */ msg) {

FILE: build.ts
  type Package (line 6) | type Package = {
  type Packages (line 10) | type Packages = Record<string, Record<string, Package>>;
  function buildBundles (line 54) | async function buildBundles() {
  function buildBuiltinPlugins (line 73) | async function buildBuiltinPlugins() {
  function prepareDistDir (line 93) | async function prepareDistDir() {
  function collectDeps (line 99) | function collectDeps() {
  function unpackPackage (line 108) | async function unpackPackage(packages: Packages, rootDir: string, name: ...

FILE: examples/NT-API/renderer.js
  method constructor (line 6) | constructor() {

FILE: examples/NT-API/settings.js
  function SettingsPanel (line 6) | function SettingsPanel({ config, setConfig }) {
  method constructor (line 114) | constructor() {

FILE: src/builtins/settings/src/_renderer.tsx
  class Entry (line 9) | class Entry implements QQNTim.Entry.Renderer {
    method constructor (line 10) | constructor() {

FILE: src/builtins/settings/src/exports/components.tsx
  function SettingsSection (line 4) | function SettingsSection({ title, children, buttons }: { title: string; ...
  function SettingsBox (line 16) | function SettingsBox({ children }: { children: ReactNode }) {
  function SettingsBoxItem (line 20) | function SettingsBoxItem({ title, description, children, isLast = false ...
  function Switch (line 44) | function Switch({ checked, onToggle }: { checked: boolean; onToggle: (ch...
  function Input (line 53) | function Input({ value, onChange, width }: { value: string; onChange: (v...
  function Dropdown (line 85) | function Dropdown<T>({ items, selected, onChange, width }: { items: [T, ...
  function Button (line 155) | function Button({ onClick, primary, small, children }: { onClick: () => ...

FILE: src/builtins/settings/src/exports/index.ts
  function defineSettingsPanels (line 4) | function defineSettingsPanels(...newSettingsPanels: [string, QQNTim.Sett...
  function setRenderNavFunction (line 9) | function setRenderNavFunction(newFunction: Function) {

FILE: src/builtins/settings/src/installer.ts
  function installZipPluginsForAccount (line 8) | async function installZipPluginsForAccount(uin: string, requiresRestart:...
  function installFolderPluginsForAccount (line 32) | async function installFolderPluginsForAccount(uin: string, requiresResta...
  function collectManifests (line 41) | async function collectManifests(dir: string) {
  function installPluginsForAccount (line 66) | async function installPluginsForAccount(uin: string, requiresRestart: bo...
  function uninstallPlugin (line 93) | async function uninstallPlugin(requiresRestart: boolean, pluginDir: stri...

FILE: src/builtins/settings/src/nav.tsx
  type OtherTab (line 6) | interface OtherTab {
  type PluginsManagerTab (line 13) | interface PluginsManagerTab {
  type SettingsTab (line 20) | interface SettingsTab {
  type PluginTab (line 27) | interface PluginTab {
  type Tab (line 35) | type Tab = PluginsManagerTab | SettingsTab | PluginTab;
  type TabWithOtherTab (line 36) | type TabWithOtherTab = Tab | OtherTab;
  function Navigation (line 38) | function Navigation({ vueId, onCurrentTabChange }: { vueId: string; onCu...

FILE: src/builtins/settings/src/panel.tsx
  type PanelProps (line 11) | interface PanelProps {
  function Panel (line 17) | function Panel({ currentTab, account }: { currentTab: TabWithOtherTab; a...
  function SettingsPanel (line 67) | function SettingsPanel({ config, setConfig }: PanelProps) {
  function PluginsManagerPanel (line 131) | function PluginsManagerPanel({ account, config, setConfig }: PanelProps) {

FILE: src/builtins/settings/src/utils/hooks.tsx
  function usePrevious (line 4) | function usePrevious<T>(value: T) {

FILE: src/builtins/settings/src/utils/utils.ts
  function isInWhitelist (line 4) | function isInWhitelist(id: string, whitelist?: string[]) {
  function isInBlacklist (line 7) | function isInBlacklist(id: string, blacklist?: string[]) {
  function addItemToArray (line 11) | function addItemToArray<T>(array: T[], item: T) {
  function removeItemFromArray (line 14) | function removeItemFromArray<T>(array: T[], item: T) {
  function enablePlugin (line 17) | function enablePlugin(setConfig: React.Dispatch<React.SetStateAction<Req...
  function isPluginsExistent (line 41) | function isPluginsExistent() {
  function getPluginDescription (line 52) | function getPluginDescription(plugin: QQNTim.Plugin) {

FILE: src/common/ipc.ts
  function interruptIpc (line 7) | function interruptIpc(args: QQNTim.IPC.Args<any>, direction: QQNTim.IPC....
  function handleIpc (line 21) | function handleIpc(args: QQNTim.IPC.Args<any>, direction: QQNTim.IPC.Dir...
  function addInterruptIpc (line 26) | function addInterruptIpc(func: QQNTim.IPC.InterruptFunction, options?: Q...
  function watchIpc (line 30) | function watchIpc() {

FILE: src/common/loader.ts
  function getUserPlugins (line 5) | function getUserPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin: ...
  function loadPlugins (line 16) | function loadPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin: str...

FILE: src/common/patch.ts
  function defineModules (line 3) | function defineModules(newModules: Record<string, any>) {
  function getModule (line 10) | function getModule(name: string) {

FILE: src/common/utils/console.ts
  function printObject (line 7) | function printObject(object: any, enableColorSupport = isMainProcess && ...

FILE: src/common/utils/freePort.ts
  function findFreePort (line 3) | function findFreePort() {

FILE: src/common/utils/ntVersion.ts
  function getCurrentNTVersion (line 4) | function getCurrentNTVersion() {

FILE: src/common/version.ts
  function mountVersion (line 4) | function mountVersion() {

FILE: src/common/watch.ts
  type Constructor (line 4) | type Constructor<T> = new (...args: any[]) => T;
  function getter (line 6) | function getter<T, R extends keyof T>(scope: string | undefined, target:...
  function setter (line 21) | function setter<T, R extends keyof T>(scope: string | undefined, _: T, p...
  function construct (line 26) | function construct<F, T extends Constructor<F>>(scope: string | undefine...
  function apply (line 31) | function apply<T extends Function>(target: T, thisArg: any, argArray: an...

FILE: src/main/api.ts
  function initAPI (line 11) | function initAPI() {

FILE: src/main/compatibility.ts
  function loadCustomLoaders (line 5) | function loadCustomLoaders() {

FILE: src/main/config.ts
  function toBoolean (line 4) | function toBoolean(item: boolean | undefined, env: string, defaultValue:...
  function toStringArray (line 9) | function toStringArray<T extends string[], R extends T | undefined>(item...
  function getEnvironment (line 30) | function getEnvironment(config: QQNTim.Configuration): QQNTim.Environment {
  function prepareDataDir (line 52) | function prepareDataDir() {
  function loadConfig (line 59) | function loadConfig() {

FILE: src/main/debugger.ts
  function initDebugger (line 11) | async function initDebugger() {
  function listChiiTargets (line 26) | async function listChiiTargets() {
  function createDebuggerWindow (line 31) | async function createDebuggerWindow(debuggerId: string, win: BrowserWind...

FILE: src/main/loader.ts
  function shouldInject (line 5) | function shouldInject(injection: QQNTim.Plugin.Injection) {
  function applyPlugins (line 9) | function applyPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin = "...
  function applyScripts (line 16) | function applyScripts() {

FILE: src/main/patch.ts
  function patchBrowserWindow (line 27) | function patchBrowserWindow() {
  function addInterruptWindowCreation (line 157) | function addInterruptWindowCreation(func: QQNTim.WindowCreation.Interrup...
  function addInterruptWindowArgs (line 161) | function addInterruptWindowArgs(func: QQNTim.WindowCreation.InterruptArg...
  function patchModuleLoader (line 165) | function patchModuleLoader() {

FILE: src/main/plugins.ts
  function isPluginEnabled (line 10) | function isPluginEnabled(manifest: QQNTim.Manifest) {
  function isPluginRequirementsMet (line 16) | function isPluginRequirementsMet(manifest: QQNTim.Manifest) {
  function parsePlugin (line 38) | function parsePlugin(dir: string) {
  function collectPluginsFromDir (line 75) | function collectPluginsFromDir(baseDir: string, uin = "") {
  function collectPlugins (line 89) | function collectPlugins() {

FILE: src/renderer/api/app.ts
  class AppAPI (line 3) | class AppAPI implements QQNTim.API.Renderer.AppAPI {
    method relaunch (line 4) | relaunch() {
    method quit (line 9) | quit() {
    method exit (line 13) | exit() {

FILE: src/renderer/api/browserWindow.ts
  class BrowserWindowAPI (line 3) | class BrowserWindowAPI implements QQNTim.API.Renderer.BrowserWindowAPI {
    method setSize (line 4) | setSize(width: number, height: number) {
    method setMinimumSize (line 14) | setMinimumSize(width: number, height: number) {

FILE: src/renderer/api/dialog.ts
  class DialogAPI (line 3) | class DialogAPI implements QQNTim.API.Renderer.DialogAPI {
    method confirm (line 4) | async confirm(message = "") {
    method alert (line 9) | async alert(message = "") {
    method messageBox (line 14) | messageBox(options: Electron.MessageBoxOptions): Promise<Electron.Mess...
    method openDialog (line 18) | openDialog(options: Electron.OpenDialogOptions): Promise<Electron.Open...
    method saveDialog (line 22) | saveDialog(options: Electron.SaveDialogOptions): Promise<Electron.Save...

FILE: src/renderer/api/getVueId.ts
  function getVueId (line 1) | function getVueId(element: HTMLElement) {

FILE: src/renderer/api/index.ts
  function initAPI (line 17) | function initAPI() {

FILE: src/renderer/api/nt/call.ts
  class NTCallError (line 6) | class NTCallError extends Error {
    method constructor (line 9) | constructor(code: number, message: string) {
  function ntCall (line 32) | function ntCall(eventName: string, cmdName: string, args: any[], isRegis...

FILE: src/renderer/api/nt/constructor.ts
  function constructTextElement (line 3) | function constructTextElement(ele: any): QQNTim.API.Renderer.NT.MessageE...
  function constructImageElement (line 11) | function constructImageElement(ele: any, msg: any): QQNTim.API.Renderer....
  function constructFaceElement (line 19) | function constructFaceElement(ele: any): QQNTim.API.Renderer.NT.MessageE...
  function constructRawElement (line 28) | function constructRawElement(ele: any): QQNTim.API.Renderer.NT.MessageEl...
  function constructMessage (line 34) | function constructMessage(msg: any): QQNTim.API.Renderer.NT.Message {
  function constructUser (line 61) | function constructUser(user: any): QQNTim.API.Renderer.NT.User {
  function constructGroup (line 73) | function constructGroup(group: any): QQNTim.API.Renderer.NT.Group {

FILE: src/renderer/api/nt/destructor.ts
  function destructTextElement (line 1) | function destructTextElement(element: QQNTim.API.Renderer.NT.MessageElem...
  function destructImageElement (line 15) | function destructImageElement(element: QQNTim.API.Renderer.NT.MessageEle...
  function destructFaceElement (line 23) | function destructFaceElement(element: QQNTim.API.Renderer.NT.MessageElem...
  function destructRawElement (line 43) | function destructRawElement(element: QQNTim.API.Renderer.NT.MessageEleme...
  function destructPeer (line 47) | function destructPeer(peer: QQNTim.API.Renderer.NT.Peer) {

FILE: src/renderer/api/nt/index.ts
  class NT (line 10) | class NT extends NTEventEmitter implements QQNTim.API.Renderer.NT {
    method init (line 16) | public init() {
    method listenNewMessages (line 24) | private listenNewMessages() {
    method listenContactListChange (line 34) | private listenContactListChange() {
    method getAccountInfo (line 52) | async getAccountInfo(): Promise<QQNTim.API.Renderer.NT.LoginAccount | ...
    method getUserInfo (line 59) | async getUserInfo(uid: string): Promise<QQNTim.API.Renderer.NT.User> {
    method revokeMessage (line 64) | async revokeMessage(peer: QQNTim.API.Renderer.NT.Peer, message: string) {
    method sendMessage (line 73) | async sendMessage(peer: QQNTim.API.Renderer.NT.Peer, elements: QQNTim....
    method getFriendsList (line 93) | async getFriendsList(forced: boolean) {
    method getGroupsList (line 100) | async getGroupsList(forced: boolean) {
    method getPreviousMessages (line 107) | async getPreviousMessages(peer: QQNTim.API.Renderer.NT.Peer, count = 2...

FILE: src/renderer/api/nt/media.ts
  class NTMedia (line 5) | class NTMedia {
    method init (line 8) | public init() {
    method prepareImageElement (line 12) | public async prepareImageElement(file: string) {
    method downloadMedia (line 46) | public async downloadMedia(msgId: string, elementId: string, peerUid: ...

FILE: src/renderer/api/nt/watcher.ts
  class NTWatcher (line 3) | class NTWatcher<T extends string | number> {
    method constructor (line 5) | constructor(getId: (args: QQNTim.IPC.Args<any>) => T, eventName: strin...
    method wait (line 18) | wait(id: T) {

FILE: src/renderer/api/waitForElement.ts
  function refreshStatus (line 12) | function refreshStatus() {
  function waitForElement (line 20) | function waitForElement<T extends Element>(selector: string) {

FILE: src/renderer/debugger.ts
  function attachDebugger (line 4) | function attachDebugger() {

FILE: src/renderer/loader.ts
  function detectCurrentPage (line 9) | function detectCurrentPage(): QQNTim.Manifest.PageWithAbout {
  function shouldInject (line 23) | function shouldInject(injection: QQNTim.Plugin.Injection, page: QQNTim.M...
  function applyPlugins (line 27) | function applyPlugins(allPlugins: QQNTim.Plugin.AllUsersPlugins, uin = "...
  function applyStylesheets (line 41) | function applyStylesheets() {
  function applyScripts (line 53) | function applyScripts() {

FILE: src/renderer/patch.ts
  function patchIpcRenderer (line 14) | function patchIpcRenderer() {
  function patchContextBridge (line 39) | function patchContextBridge() {
  function patchModuleLoader (line 54) | function patchModuleLoader() {
  function patchLogger (line 71) | function patchLogger() {

FILE: src/renderer/vueHelper.ts
  type Component (line 1) | interface Component {
  type VueElement (line 10) | interface VueElement extends HTMLElement {
  function watchComponentUnmount (line 20) | function watchComponentUnmount(component: Component) {
  function watchComponentMount (line 34) | function watchComponentMount(component: Component) {
  function recordComponent (line 47) | function recordComponent(component: Component) {
  function hookVue3 (line 66) | function hookVue3() {

FILE: src/typings/electron.d.ts
  type DOMEvent (line 8) | type DOMEvent = Event;
  type GlobalResponse (line 9) | type GlobalResponse = Response;
  type GlobalRequest (line 10) | type GlobalRequest = Request;
  type Accelerator (line 15) | type Accelerator = string;
  type Event (line 16) | type Event<Params extends object = {}> = {
  type App (line 21) | interface App extends NodeJS.EventEmitter {
  type AutoUpdater (line 1687) | interface AutoUpdater extends NodeJS.EventEmitter {
  type BluetoothDevice (line 1774) | interface BluetoothDevice {
  class BrowserView (line 1781) | class BrowserView {
  class BrowserWindow (line 1843) | class BrowserWindow extends NodeEventEmitter {
  type Certificate (line 3430) | interface Certificate {
  type CertificatePrincipal (line 3475) | interface CertificatePrincipal {
  class ClientRequest (line 3504) | class ClientRequest extends NodeEventEmitter {
  type Clipboard (line 3724) | interface Clipboard {
  class CommandLine (line 3841) | class CommandLine {
  type ContentTracing (line 3882) | interface ContentTracing {
  type ContextBridge (line 3939) | interface ContextBridge {
  type Cookie (line 3946) | interface Cookie {
  class Cookies (line 3996) | class Cookies extends NodeEventEmitter {
  type CPUUsage (line 4102) | interface CPUUsage {
  type CrashReport (line 4116) | interface CrashReport {
  type CrashReporter (line 4123) | interface CrashReporter {
  type CustomScheme (line 4211) | interface CustomScheme {
  class Debugger (line 4221) | class Debugger extends NodeEventEmitter {
  type DesktopCapturer (line 4373) | interface DesktopCapturer {
  type DesktopCapturerSource (line 4388) | interface DesktopCapturerSource {
  type Dialog (line 4426) | interface Dialog {
  type Display (line 4678) | interface Display {
  class Dock (line 4742) | class Dock {
  class DownloadItem (line 4823) | class DownloadItem extends NodeEventEmitter {
  type Extension (line 5042) | interface Extension {
  type ExtensionInfo (line 5062) | interface ExtensionInfo {
  type FileFilter (line 5069) | interface FileFilter {
  type FilePathWithHeaders (line 5076) | interface FilePathWithHeaders {
  type GlobalShortcut (line 5089) | interface GlobalShortcut {
  type GPUFeatureStatus (line 5147) | interface GPUFeatureStatus {
  type HIDDevice (line 5204) | interface HIDDevice {
  type InAppPurchase (line 5234) | interface InAppPurchase extends NodeJS.EventEmitter {
  class IncomingMessage (line 5282) | class IncomingMessage extends NodeEventEmitter {
  type InputEvent (line 5400) | interface InputEvent {
  type IOCounters (line 5465) | interface IOCounters {
  type IpcMain (line 5494) | interface IpcMain extends NodeJS.EventEmitter {
  type IpcMainEvent (line 5544) | interface IpcMainEvent extends Event {
  type IpcMainInvokeEvent (line 5581) | interface IpcMainInvokeEvent extends Event {
  type IpcRenderer (line 5603) | interface IpcRenderer extends NodeJS.EventEmitter {
  type IpcRendererEvent (line 5731) | interface IpcRendererEvent extends Event {
  type JumpListCategory (line 5752) | interface JumpListCategory {
  type JumpListItem (line 5770) | interface JumpListItem {
  type KeyboardEvent (line 5820) | interface KeyboardEvent {
  type KeyboardInputEvent (line 5846) | interface KeyboardInputEvent extends InputEvent {
  type MemoryInfo (line 5860) | interface MemoryInfo {
  type MemoryUsageDetails (line 5880) | interface MemoryUsageDetails {
  class Menu (line 5888) | class Menu extends NodeEventEmitter {
  class MenuItem (line 5985) | class MenuItem {
  class MessageChannelMain (line 6152) | class MessageChannelMain extends NodeEventEmitter {
  class MessagePortMain (line 6165) | class MessagePortMain extends NodeEventEmitter {
  type MimeTypedBuffer (line 6198) | interface MimeTypedBuffer {
  type MouseInputEvent (line 6215) | interface MouseInputEvent extends InputEvent {
  type MouseWheelInputEvent (line 6236) | interface MouseWheelInputEvent extends MouseInputEvent {
  class NativeImage (line 6253) | class NativeImage {
  type NativeTheme (line 6413) | interface NativeTheme extends NodeJS.EventEmitter {
  type Net (line 6495) | interface Net {
  type NetLog (line 6561) | interface NetLog {
  class Notification (line 6585) | class Notification extends NodeEventEmitter {
  type NotificationAction (line 6833) | interface NotificationAction {
  type NotificationResponse (line 6846) | interface NotificationResponse {
  type ParentPort (line 6871) | interface ParentPort extends NodeJS.EventEmitter {
  type PaymentDiscount (line 6888) | interface PaymentDiscount {
  type Point (line 6915) | interface Point {
  type PostBody (line 6922) | interface PostBody {
  type PowerMonitor (line 6942) | interface PowerMonitor extends NodeJS.EventEmitter {
  type PowerSaveBlocker (line 7160) | interface PowerSaveBlocker {
  type PrinterInfo (line 7189) | interface PrinterInfo {
  type ProcessMemoryInfo (line 7218) | interface ProcessMemoryInfo {
  type ProcessMetric (line 7239) | interface ProcessMetric {
  type Product (line 7288) | interface Product {
  type ProductDiscount (line 7356) | interface ProductDiscount {
  type ProductSubscriptionPeriod (line 7391) | interface ProductSubscriptionPeriod {
  type Protocol (line 7405) | interface Protocol {
  type ProtocolRequest (line 7611) | interface ProtocolRequest {
  type ProtocolResponse (line 7621) | interface ProtocolResponse {
  type ProtocolResponseUploadData (line 7686) | interface ProtocolResponseUploadData {
  type PushNotifications (line 7699) | interface PushNotifications extends NodeJS.EventEmitter {
  type Rectangle (line 7829) | interface Rectangle {
  type Referrer (line 7850) | interface Referrer {
  type ResolvedEndpoint (line 7865) | interface ResolvedEndpoint {
  type ResolvedHost (line 7875) | interface ResolvedHost {
  type SafeStorage (line 7884) | interface SafeStorage extends NodeJS.EventEmitter {
  type Screen (line 7910) | interface Screen extends NodeJS.EventEmitter {
  type ScrubberItem (line 7990) | interface ScrubberItem {
  type SegmentedControlSegment (line 8003) | interface SegmentedControlSegment {
  type SerialPort (line 8020) | interface SerialPort {
  type ServiceWorkerInfo (line 8061) | interface ServiceWorkerInfo {
  class ServiceWorkers (line 8080) | class ServiceWorkers extends NodeEventEmitter {
  class Session (line 8185) | class Session extends NodeEventEmitter {
  type SharedWorkerInfo (line 9115) | interface SharedWorkerInfo {
  class ShareMenu (line 9128) | class ShareMenu extends NodeEventEmitter {
  type SharingItem (line 9145) | interface SharingItem {
  type Shell (line 9162) | interface Shell {
  type ShortcutDetails (line 9219) | interface ShortcutDetails {
  type Size (line 9259) | interface Size {
  type SystemPreferences (line 9266) | interface SystemPreferences extends NodeJS.EventEmitter {
  type Task (line 9818) | interface Task {
  type ThumbarButton (line 9856) | interface ThumbarButton {
  class TouchBar (line 9875) | class TouchBar {
  class TouchBarButton (line 9932) | class TouchBarButton {
  class TouchBarColorPicker (line 9969) | class TouchBarColorPicker extends NodeEventEmitter {
  class TouchBarGroup (line 9988) | class TouchBarGroup extends NodeEventEmitter {
  class TouchBarLabel (line 9997) | class TouchBarLabel extends NodeEventEmitter {
  class TouchBarOtherItemsProxy (line 10021) | class TouchBarOtherItemsProxy extends NodeEventEmitter {
  class TouchBarPopover (line 10030) | class TouchBarPopover extends NodeEventEmitter {
  class TouchBarScrubber (line 10049) | class TouchBarScrubber extends NodeEventEmitter {
  class TouchBarSegmentedControl (line 10104) | class TouchBarSegmentedControl extends NodeEventEmitter {
  class TouchBarSlider (line 10135) | class TouchBarSlider extends NodeEventEmitter {
  class TouchBarSpacer (line 10164) | class TouchBarSpacer extends NodeEventEmitter {
  type TraceCategoriesAndOptions (line 10178) | interface TraceCategoriesAndOptions {
  type TraceConfig (line 10204) | interface TraceConfig {
  type Transaction (line 10255) | interface Transaction {
  class Tray (line 10286) | class Tray extends NodeEventEmitter {
  type UploadData (line 10925) | interface UploadData {
  type UploadFile (line 10942) | interface UploadFile {
  type UploadRawData (line 10968) | interface UploadRawData {
  type USBDevice (line 10981) | interface USBDevice {
  type UserDefaultTypes (line 11046) | interface UserDefaultTypes {
  class UtilityProcess (line 11059) | class UtilityProcess extends NodeEventEmitter {
  class WebContents (line 11157) | class WebContents extends NodeEventEmitter {
  type WebFrame (line 13622) | interface WebFrame {
  class WebFrameMain (line 13815) | class WebFrameMain extends NodeEventEmitter {
  class WebRequest (line 13973) | class WebRequest {
  type WebRequestFilter (line 14082) | interface WebRequestFilter {
  type WebSource (line 14099) | interface WebSource {
  type WebviewTag (line 14106) | interface WebviewTag extends HTMLElement {
  type AboutPanelOptionsOptions (line 14752) | interface AboutPanelOptionsOptions {
  type AddRepresentationOptions (line 14798) | interface AddRepresentationOptions {
  type AdjustSelectionOptions (line 14821) | interface AdjustSelectionOptions {
  type AnimationSettings (line 14832) | interface AnimationSettings {
  type AppDetailsOptions (line 14850) | interface AppDetailsOptions {
  type ApplicationInfoForProtocolReturnValue (line 14875) | interface ApplicationInfoForProtocolReturnValue {
  type AuthenticationResponseDetails (line 14890) | interface AuthenticationResponseDetails {
  type AuthInfo (line 14894) | interface AuthInfo {
  type AutoResizeOptions (line 14902) | interface AutoResizeOptions {
  type BeforeSendResponse (line 14925) | interface BeforeSendResponse {
  type BitmapOptions (line 14933) | interface BitmapOptions {
  type BlinkMemoryInfo (line 14940) | interface BlinkMemoryInfo {
  type BluetoothPairingHandlerHandlerDetails (line 14951) | interface BluetoothPairingHandlerHandlerDetails {
  type BrowserViewConstructorOptions (line 14964) | interface BrowserViewConstructorOptions {
  type BrowserWindowConstructorOptions (line 14971) | interface BrowserWindowConstructorOptions {
  type CallbackResponse (line 15274) | interface CallbackResponse {
  type CertificateTrustDialogOptions (line 15283) | interface CertificateTrustDialogOptions {
  type ClearCodeCachesOptions (line 15294) | interface ClearCodeCachesOptions {
  type ClearStorageDataOptions (line 15303) | interface ClearStorageDataOptions {
  type ClientRequestConstructorOptions (line 15321) | interface ClientRequestConstructorOptions {
  type CloseOpts (line 15404) | interface CloseOpts {
  type Config (line 15413) | interface Config {
  type ConfigureHostResolverOptions (line 15434) | interface ConfigureHostResolverOptions {
  type ConsoleMessageEvent (line 15467) | interface ConsoleMessageEvent extends DOMEvent {
  type ContextMenuEvent (line 15484) | interface ContextMenuEvent extends DOMEvent {
  type ContextMenuParams (line 15488) | interface ContextMenuParams {
  type ContinueActivityDetails (line 15604) | interface ContinueActivityDetails {
  type CookiesGetFilter (line 15612) | interface CookiesGetFilter {
  type CookiesSetDetails (line 15644) | interface CookiesSetDetails {
  type CrashReporterStartOptions (line 15689) | interface CrashReporterStartOptions {
  type CreateFromBitmapOptions (line 15746) | interface CreateFromBitmapOptions {
  type CreateFromBufferOptions (line 15755) | interface CreateFromBufferOptions {
  type CreateInterruptedDownloadOptions (line 15770) | interface CreateInterruptedDownloadOptions {
  type Data (line 15802) | interface Data {
  type Details (line 15813) | interface Details {
  type DevicePermissionHandlerHandlerDetails (line 15838) | interface DevicePermissionHandlerHandlerDetails {
  type DevtoolsOpenUrlEvent (line 15854) | interface DevtoolsOpenUrlEvent extends DOMEvent {
  type DidChangeThemeColorEvent (line 15861) | interface DidChangeThemeColorEvent extends DOMEvent {
  type DidCreateWindowDetails (line 15865) | interface DidCreateWindowDetails {
  type DidFailLoadEvent (line 15899) | interface DidFailLoadEvent extends DOMEvent {
  type DidFrameFinishLoadEvent (line 15906) | interface DidFrameFinishLoadEvent extends DOMEvent {
  type DidFrameNavigateEvent (line 15910) | interface DidFrameNavigateEvent extends DOMEvent {
  type DidNavigateEvent (line 15925) | interface DidNavigateEvent extends DOMEvent {
  type DidNavigateInPageEvent (line 15929) | interface DidNavigateInPageEvent extends DOMEvent {
  type DidRedirectNavigationEvent (line 15934) | interface DidRedirectNavigationEvent extends DOMEvent {
  type DidStartNavigationEvent (line 15942) | interface DidStartNavigationEvent extends DOMEvent {
  type DisplayBalloonOptions (line 15950) | interface DisplayBalloonOptions {
  type DisplayMediaRequestHandlerHandlerRequest (line 15977) | interface DisplayMediaRequestHandlerHandlerRequest {
  type EnableNetworkEmulationOptions (line 16000) | interface EnableNetworkEmulationOptions {
  type FeedURLOptions (line 16019) | interface FeedURLOptions {
  type FileIconOptions (line 16035) | interface FileIconOptions {
  type FindInPageOptions (line 16039) | interface FindInPageOptions {
  type FocusOptions (line 16055) | interface FocusOptions {
  type ForkOptions (line 16064) | interface ForkOptions {
  type FoundInPageEvent (line 16105) | interface FoundInPageEvent extends DOMEvent {
  type FrameCreatedDetails (line 16109) | interface FrameCreatedDetails {
  type FromPartitionOptions (line 16113) | interface FromPartitionOptions {
  type FromPathOptions (line 16120) | interface FromPathOptions {
  type HandlerDetails (line 16127) | interface HandlerDetails {
  type HeadersReceivedResponse (line 16160) | interface HeadersReceivedResponse {
  type HeapStatistics (line 16173) | interface HeapStatistics {
  type HidDeviceAddedDetails (line 16185) | interface HidDeviceAddedDetails {
  type HidDeviceRemovedDetails (line 16190) | interface HidDeviceRemovedDetails {
  type HidDeviceRevokedDetails (line 16195) | interface HidDeviceRevokedDetails {
  type IgnoreMouseEventsOptions (line 16203) | interface IgnoreMouseEventsOptions {
  type ImportCertificateOptions (line 16214) | interface ImportCertificateOptions {
  type Info (line 16225) | interface Info {
  type Input (line 16240) | interface Input {
  type InsertCSSOptions (line 16287) | interface InsertCSSOptions {
  type IpcMessageEvent (line 16295) | interface IpcMessageEvent extends DOMEvent {
  type Item (line 16304) | interface Item {
  type JumpListSettings (line 16319) | interface JumpListSettings {
  type LoadCommitEvent (line 16335) | interface LoadCommitEvent extends DOMEvent {
  type LoadExtensionOptions (line 16340) | interface LoadExtensionOptions {
  type LoadFileOptions (line 16349) | interface LoadFileOptions {
  type LoadURLOptions (line 16364) | interface LoadURLOptions {
  type LoginItemSettings (line 16386) | interface LoginItemSettings {
  type LoginItemSettingsOptions (line 16434) | interface LoginItemSettingsOptions {
  type MenuItemConstructorOptions (line 16449) | interface MenuItemConstructorOptions {
  type MessageBoxOptions (line 16599) | interface MessageBoxOptions {
  type MessageBoxReturnValue (line 16676) | interface MessageBoxReturnValue {
  type MessageBoxSyncOptions (line 16687) | interface MessageBoxSyncOptions {
  type MessageDetails (line 16749) | interface MessageDetails {
  type MessageEvent (line 16779) | interface MessageEvent {
  type MoveToApplicationsFolderOptions (line 16784) | interface MoveToApplicationsFolderOptions {
  type NotificationConstructorOptions (line 16791) | interface NotificationConstructorOptions {
  type OnBeforeRedirectListenerDetails (line 16870) | interface OnBeforeRedirectListenerDetails {
  type OnBeforeRequestListenerDetails (line 16895) | interface OnBeforeRequestListenerDetails {
  type OnBeforeSendHeadersListenerDetails (line 16912) | interface OnBeforeSendHeadersListenerDetails {
  type OnCompletedListenerDetails (line 16930) | interface OnCompletedListenerDetails {
  type OnErrorOccurredListenerDetails (line 16951) | interface OnErrorOccurredListenerDetails {
  type OnHeadersReceivedListenerDetails (line 16972) | interface OnHeadersReceivedListenerDetails {
  type OnResponseStartedListenerDetails (line 16991) | interface OnResponseStartedListenerDetails {
  type OnSendHeadersListenerDetails (line 17014) | interface OnSendHeadersListenerDetails {
  type OpenDevToolsOptions (line 17031) | interface OpenDevToolsOptions {
  type OpenDialogOptions (line 17045) | interface OpenDialogOptions {
  type OpenDialogReturnValue (line 17073) | interface OpenDialogReturnValue {
  type OpenDialogSyncOptions (line 17093) | interface OpenDialogSyncOptions {
  type OpenExternalOptions (line 17121) | interface OpenExternalOptions {
  type Options (line 17143) | type Options = {};
  type Opts (line 17145) | interface Opts {
  type PageFaviconUpdatedEvent (line 17156) | interface PageFaviconUpdatedEvent extends DOMEvent {
  type PageTitleUpdatedEvent (line 17163) | interface PageTitleUpdatedEvent extends DOMEvent {
  type Parameters (line 17168) | interface Parameters {
  type Payment (line 17198) | interface Payment {
  type PermissionCheckHandlerHandlerDetails (line 17217) | interface PermissionCheckHandlerHandlerDetails {
  type PermissionRequestHandlerHandlerDetails (line 17242) | interface PermissionRequestHandlerHandlerDetails {
  type PluginCrashedEvent (line 17265) | interface PluginCrashedEvent extends DOMEvent {
  type PopupOptions (line 17270) | interface PopupOptions {
  type PreconnectOptions (line 17298) | interface PreconnectOptions {
  type PrintToPDFOptions (line 17309) | interface PrintToPDFOptions {
  type Privileges (line 17358) | interface Privileges {
  type ProgressBarOptions (line 17389) | interface ProgressBarOptions {
  type Provider (line 17399) | interface Provider {
  type PurchaseProductOpts (line 17403) | interface PurchaseProductOpts {
  type ReadBookmark (line 17415) | interface ReadBookmark {
  type RegistrationCompletedDetails (line 17420) | interface RegistrationCompletedDetails {
  type RelaunchOptions (line 17427) | interface RelaunchOptions {
  type RenderProcessGoneDetails (line 17432) | interface RenderProcessGoneDetails {
  type Request (line 17444) | interface Request {
  type ResizeOptions (line 17465) | interface ResizeOptions {
  type ResolveHostOptions (line 17484) | interface ResolveHostOptions {
  type ResourceUsage (line 17510) | interface ResourceUsage {
  type Response (line 17519) | interface Response {
  type Result (line 17534) | interface Result {
  type SaveDialogOptions (line 17551) | interface SaveDialogOptions {
  type SaveDialogReturnValue (line 17595) | interface SaveDialogReturnValue {
  type SaveDialogSyncOptions (line 17614) | interface SaveDialogSyncOptions {
  type SelectHidDeviceDetails (line 17658) | interface SelectHidDeviceDetails {
  type SelectUsbDeviceDetails (line 17663) | interface SelectUsbDeviceDetails {
  type SerialPortRevokedDetails (line 17668) | interface SerialPortRevokedDetails {
  type Settings (line 17677) | interface Settings {
  type SourcesOptions (line 17721) | interface SourcesOptions {
  type SSLConfigConfig (line 17742) | interface SSLConfigConfig {
  type StartLoggingOptions (line 17765) | interface StartLoggingOptions {
  type Streams (line 17780) | interface Streams {
  type SystemMemoryInfo (line 17797) | interface SystemMemoryInfo {
  type TitleBarOverlayOptions (line 17820) | interface TitleBarOverlayOptions {
  type TitleOptions (line 17841) | interface TitleOptions {
  type ToBitmapOptions (line 17850) | interface ToBitmapOptions {
  type ToDataURLOptions (line 17857) | interface ToDataURLOptions {
  type ToPNGOptions (line 17864) | interface ToPNGOptions {
  type TouchBarButtonConstructorOptions (line 17871) | interface TouchBarButtonConstructorOptions {
  type TouchBarColorPickerConstructorOptions (line 17902) | interface TouchBarColorPickerConstructorOptions {
  type TouchBarConstructorOptions (line 17917) | interface TouchBarConstructorOptions {
  type TouchBarGroupConstructorOptions (line 17922) | interface TouchBarGroupConstructorOptions {
  type TouchBarLabelConstructorOptions (line 17929) | interface TouchBarLabelConstructorOptions {
  type TouchBarPopoverConstructorOptions (line 17944) | interface TouchBarPopoverConstructorOptions {
  type TouchBarScrubberConstructorOptions (line 17964) | interface TouchBarScrubberConstructorOptions {
  type TouchBarSegmentedControlConstructorOptions (line 18002) | interface TouchBarSegmentedControlConstructorOptions {
  type TouchBarSliderConstructorOptions (line 18026) | interface TouchBarSliderConstructorOptions {
  type TouchBarSpacerConstructorOptions (line 18049) | interface TouchBarSpacerConstructorOptions {
  type TraceBufferUsageReturnValue (line 18056) | interface TraceBufferUsageReturnValue {
  type UpdateTargetUrlEvent (line 18061) | interface UpdateTargetUrlEvent extends DOMEvent {
  type UploadProgress (line 18065) | interface UploadProgress {
  type UsbDeviceRevokedDetails (line 18086) | interface UsbDeviceRevokedDetails {
  type USBProtectedClassesHandlerHandlerDetails (line 18094) | interface USBProtectedClassesHandlerHandlerDetails {
  type VisibleOnAllWorkspacesOptions (line 18101) | interface VisibleOnAllWorkspacesOptions {
  type WebContentsAudioStateChangedEventParams (line 18120) | interface WebContentsAudioStateChangedEventParams {
  type WebContentsDidRedirectNavigationEventParams (line 18127) | interface WebContentsDidRedirectNavigationEventParams {
  type WebContentsDidStartNavigationEventParams (line 18155) | interface WebContentsDidStartNavigationEventParams {
  type WebContentsPrintOptions (line 18183) | interface WebContentsPrintOptions {
  type WebContentsWillFrameNavigateEventParams (line 18249) | interface WebContentsWillFrameNavigateEventParams {
  type WebContentsWillNavigateEventParams (line 18271) | interface WebContentsWillNavigateEventParams {
  type WebContentsWillRedirectEventParams (line 18299) | interface WebContentsWillRedirectEventParams {
  type WebviewTagPrintOptions (line 18327) | interface WebviewTagPrintOptions {
  type WillFrameNavigateEvent (line 18392) | interface WillFrameNavigateEvent extends DOMEvent {
  type WillNavigateEvent (line 18399) | interface WillNavigateEvent extends DOMEvent {
  type WillResizeDetails (line 18403) | interface WillResizeDetails {
  type EditFlags (line 18411) | interface EditFlags {
  type Env (line 18446) | type Env = {};
  type FoundInPageResult (line 18448) | interface FoundInPageResult {
  type LaunchItems (line 18465) | interface LaunchItems {
  type Margins (line 18500) | interface Margins {
  type MediaFlags (line 18524) | interface MediaFlags {
  type PageRanges (line 18579) | interface PageRanges {
  type Params (line 18590) | interface Params {
  type TitleBarOverlay (line 18702) | interface TitleBarOverlay {
  type Video (line 18726) | interface Video {
  type WebPreferences (line 18739) | interface WebPreferences {
  type DefaultFontFamily (line 18971) | interface DefaultFontFamily {
  type RemoteMainInterface (line 18998) | interface RemoteMainInterface {
  type Event (line 19037) | type Event<Params extends object = {}> = Electron.Event<Params>;
  type Clipboard (line 19039) | type Clipboard = Electron.Clipboard;
  type CrashReporter (line 19041) | type CrashReporter = Electron.CrashReporter;
  type NativeImage (line 19043) | type NativeImage = Electron.NativeImage;
  type Shell (line 19045) | type Shell = Electron.Shell;
  type AboutPanelOptionsOptions (line 19046) | type AboutPanelOptionsOptions = Electron.AboutPanelOptionsOptions;
  type AddRepresentationOptions (line 19047) | type AddRepresentationOptions = Electron.AddRepresentationOptions;
  type AdjustSelectionOptions (line 19048) | type AdjustSelectionOptions = Electron.AdjustSelectionOptions;
  type AnimationSettings (line 19049) | type AnimationSettings = Electron.AnimationSettings;
  type AppDetailsOptions (line 19050) | type AppDetailsOptions = Electron.AppDetailsOptions;
  type ApplicationInfoForProtocolReturnValue (line 19051) | type ApplicationInfoForProtocolReturnValue = Electron.ApplicationInfoFor...
  type AuthenticationResponseDetails (line 19052) | type AuthenticationResponseDetails = Electron.AuthenticationResponseDeta...
  type AuthInfo (line 19053) | type AuthInfo = Electron.AuthInfo;
  type AutoResizeOptions (line 19054) | type AutoResizeOptions = Electron.AutoResizeOptions;
  type BeforeSendResponse (line 19055) | type BeforeSendResponse = Electron.BeforeSendResponse;
  type BitmapOptions (line 19056) | type BitmapOptions = Electron.BitmapOptions;
  type BlinkMemoryInfo (line 19057) | type BlinkMemoryInfo = Electron.BlinkMemoryInfo;
  type BluetoothPairingHandlerHandlerDetails (line 19058) | type BluetoothPairingHandlerHandlerDetails = Electron.BluetoothPairingHa...
  type BrowserViewConstructorOptions (line 19059) | type BrowserViewConstructorOptions = Electron.BrowserViewConstructorOpti...
  type BrowserWindowConstructorOptions (line 19060) | type BrowserWindowConstructorOptions = Electron.BrowserWindowConstructor...
  type CallbackResponse (line 19061) | type CallbackResponse = Electron.CallbackResponse;
  type CertificateTrustDialogOptions (line 19062) | type CertificateTrustDialogOptions = Electron.CertificateTrustDialogOpti...
  type ClearCodeCachesOptions (line 19063) | type ClearCodeCachesOptions = Electron.ClearCodeCachesOptions;
  type ClearStorageDataOptions (line 19064) | type ClearStorageDataOptions = Electron.ClearStorageDataOptions;
  type ClientRequestConstructorOptions (line 19065) | type ClientRequestConstructorOptions = Electron.ClientRequestConstructor...
  type CloseOpts (line 19066) | type CloseOpts = Electron.CloseOpts;
  type Config (line 19067) | type Config = Electron.Config;
  type ConfigureHostResolverOptions (line 19068) | type ConfigureHostResolverOptions = Electron.ConfigureHostResolverOptions;
  type ConsoleMessageEvent (line 19069) | type ConsoleMessageEvent = Electron.ConsoleMessageEvent;
  type ContextMenuEvent (line 19070) | type ContextMenuEvent = Electron.ContextMenuEvent;
  type ContextMenuParams (line 19071) | type ContextMenuParams = Electron.ContextMenuParams;
  type ContinueActivityDetails (line 19072) | type ContinueActivityDetails = Electron.ContinueActivityDetails;
  type CookiesGetFilter (line 19073) | type CookiesGetFilter = Electron.CookiesGetFilter;
  type CookiesSetDetails (line 19074) | type CookiesSetDetails = Electron.CookiesSetDetails;
  type CrashReporterStartOptions (line 19075) | type CrashReporterStartOptions = Electron.CrashReporterStartOptions;
  type CreateFromBitmapOptions (line 19076) | type CreateFromBitmapOptions = Electron.CreateFromBitmapOptions;
  type CreateFromBufferOptions (line 19077) | type CreateFromBufferOptions = Electron.CreateFromBufferOptions;
  type CreateInterruptedDownloadOptions (line 19078) | type CreateInterruptedDownloadOptions = Electron.CreateInterruptedDownlo...
  type Data (line 19079) | type Data = Electron.Data;
  type Details (line 19080) | type Details = Electron.Details;
  type DevicePermissionHandlerHandlerDetails (line 19081) | type DevicePermissionHandlerHandlerDetails = Electron.DevicePermissionHa...
  type DevtoolsOpenUrlEvent (line 19082) | type DevtoolsOpenUrlEvent = Electron.DevtoolsOpenUrlEvent;
  type DidChangeThemeColorEvent (line 19083) | type DidChangeThemeColorEvent = Electron.DidChangeThemeColorEvent;
  type DidCreateWindowDetails (line 19084) | type DidCreateWindowDetails = Electron.DidCreateWindowDetails;
  type DidFailLoadEvent (line 19085) | type DidFailLoadEvent = Electron.DidFailLoadEvent;
  type DidFrameFinishLoadEvent (line 19086) | type DidFrameFinishLoadEvent = Electron.DidFrameFinishLoadEvent;
  type DidFrameNavigateEvent (line 19087) | type DidFrameNavigateEvent = Electron.DidFrameNavigateEvent;
  type DidNavigateEvent (line 19088) | type DidNavigateEvent = Electron.DidNavigateEvent;
  type DidNavigateInPageEvent (line 19089) | type DidNavigateInPageEvent = Electron.DidNavigateInPageEvent;
  type DidRedirectNavigationEvent (line 19090) | type DidRedirectNavigationEvent = Electron.DidRedirectNavigationEvent;
  type DidStartNavigationEvent (line 19091) | type DidStartNavigationEvent = Electron.DidStartNavigationEvent;
  type DisplayBalloonOptions (line 19092) | type DisplayBalloonOptions = Electron.DisplayBalloonOptions;
  type DisplayMediaRequestHandlerHandlerRequest (line 19093) | type DisplayMediaRequestHandlerHandlerRequest = Electron.DisplayMediaReq...
  type EnableNetworkEmulationOptions (line 19094) | type EnableNetworkEmulationOptions = Electron.EnableNetworkEmulationOpti...
  type FeedURLOptions (line 19095) | type FeedURLOptions = Electron.FeedURLOptions;
  type FileIconOptions (line 19096) | type FileIconOptions = Electron.FileIconOptions;
  type FindInPageOptions (line 19097) | type FindInPageOptions = Electron.FindInPageOptions;
  type FocusOptions (line 19098) | type FocusOptions = Electron.FocusOptions;
  type ForkOptions (line 19099) | type ForkOptions = Electron.ForkOptions;
  type FoundInPageEvent (line 19100) | type FoundInPageEvent = Electron.FoundInPageEvent;
  type FrameCreatedDetails (line 19101) | type FrameCreatedDetails = Electron.FrameCreatedDetails;
  type FromPartitionOptions (line 19102) | type FromPartitionOptions = Electron.FromPartitionOptions;
  type FromPathOptions (line 19103) | type FromPathOptions = Electron.FromPathOptions;
  type HandlerDetails (line 19104) | type HandlerDetails = Electron.HandlerDetails;
  type HeadersReceivedResponse (line 19105) | type HeadersReceivedResponse = Electron.HeadersReceivedResponse;
  type HeapStatistics (line 19106) | type HeapStatistics = Electron.HeapStatistics;
  type HidDeviceAddedDetails (line 19107) | type HidDeviceAddedDetails = Electron.HidDeviceAddedDetails;
  type HidDeviceRemovedDetails (line 19108) | type HidDeviceRemovedDetails = Electron.HidDeviceRemovedDetails;
  type HidDeviceRevokedDetails (line 19109) | type HidDeviceRevokedDetails = Electron.HidDeviceRevokedDetails;
  type IgnoreMouseEventsOptions (line 19110) | type IgnoreMouseEventsOptions = Electron.IgnoreMouseEventsOptions;
  type ImportCertificateOptions (line 19111) | type ImportCertificateOptions = Electron.ImportCertificateOptions;
  type Info (line 19112) | type Info = Electron.Info;
  type Input (line 19113) | type Input = Electron.Input;
  type InsertCSSOptions (line 19114) | type InsertCSSOptions = Electron.InsertCSSOptions;
  type IpcMessageEvent (line 19115) | type IpcMessageEvent = Electron.IpcMessageEvent;
  type Item (line 19116) | type Item = Electron.Item;
  type JumpListSettings (line 19117) | type JumpListSettings = Electron.JumpListSettings;
  type LoadCommitEvent (line 19118) | type LoadCommitEvent = Electron.LoadCommitEvent;
  type LoadExtensionOptions (line 19119) | type LoadExtensionOptions = Electron.LoadExtensionOptions;
  type LoadFileOptions (line 19120) | type LoadFileOptions = Electron.LoadFileOptions;
  type LoadURLOptions (line 19121) | type LoadURLOptions = Electron.LoadURLOptions;
  type LoginItemSettings (line 19122) | type LoginItemSettings = Electron.LoginItemSettings;
  type LoginItemSettingsOptions (line 19123) | type LoginItemSettingsOptions = Electron.LoginItemSettingsOptions;
  type MenuItemConstructorOptions (line 19124) | type MenuItemConstructorOptions = Electron.MenuItemConstructorOptions;
  type MessageBoxOptions (line 19125) | type MessageBoxOptions = Electron.MessageBoxOptions;
  type MessageBoxReturnValue (line 19126) | type MessageBoxReturnValue = Electron.MessageBoxReturnValue;
  type MessageBoxSyncOptions (line 19127) | type MessageBoxSyncOptions = Electron.MessageBoxSyncOptions;
  type MessageDetails (line 19128) | type MessageDetails = Electron.MessageDetails;
  type MessageEvent (line 19129) | type MessageEvent = Electron.MessageEvent;
  type MoveToApplicationsFolderOptions (line 19130) | type MoveToApplicationsFolderOptions = Electron.MoveToApplicationsFolder...
  type NotificationConstructorOptions (line 19131) | type NotificationConstructorOptions = Electron.NotificationConstructorOp...
  type OnBeforeRedirectListenerDetails (line 19132) | type OnBeforeRedirectListenerDetails = Electron.OnBeforeRedirectListener...
  type OnBeforeRequestListenerDetails (line 19133) | type OnBeforeRequestListenerDetails = Electron.OnBeforeRequestListenerDe...
  type OnBeforeSendHeadersListenerDetails (line 19134) | type OnBeforeSendHeadersListenerDetails = Electron.OnBeforeSendHeadersLi...
  type OnCompletedListenerDetails (line 19135) | type OnCompletedListenerDetails = Electron.OnCompletedListenerDetails;
  type OnErrorOccurredListenerDetails (line 19136) | type OnErrorOccurredListenerDetails = Electron.OnErrorOccurredListenerDe...
  type OnHeadersReceivedListenerDetails (line 19137) | type OnHeadersReceivedListenerDetails = Electron.OnHeadersReceivedListen...
  type OnResponseStartedListenerDetails (line 19138) | type OnResponseStartedListenerDetails = Electron.OnResponseStartedListen...
  type OnSendHeadersListenerDetails (line 19139) | type OnSendHeadersListenerDetails = Electron.OnSendHeadersListenerDetails;
  type OpenDevToolsOptions (line 19140) | type OpenDevToolsOptions = Electron.OpenDevToolsOptions;
  type OpenDialogOptions (line 19141) | type OpenDialogOptions = Electron.OpenDialogOptions;
  type OpenDialogReturnValue (line 19142) | type OpenDialogReturnValue = Electron.OpenDialogReturnValue;
  type OpenDialogSyncOptions (line 19143) | type OpenDialogSyncOptions = Electron.OpenDialogSyncOptions;
  type OpenExternalOptions (line 19144) | type OpenExternalOptions = Electron.OpenExternalOptions;
  type Options (line 19145) | type Options = Electron.Options;
  type Opts (line 19146) | type Opts = Electron.Opts;
  type PageFaviconUpdatedEvent (line 19147) | type PageFaviconUpdatedEvent = Electron.PageFaviconUpdatedEvent;
  type PageTitleUpdatedEvent (line 19148) | type PageTitleUpdatedEvent = Electron.PageTitleUpdatedEvent;
  type Parameters (line 19149) | type Parameters = Electron.Parameters;
  type Payment (line 19150) | type Payment = Electron.Payment;
  type PermissionCheckHandlerHandlerDetails (line 19151) | type PermissionCheckHandlerHandlerDetails = Electron.PermissionCheckHand...
  type PermissionRequestHandlerHandlerDetails (line 19152) | type PermissionRequestHandlerHandlerDetails = Electron.PermissionRequest...
  type PluginCrashedEvent (line 19153) | type PluginCrashedEvent = Electron.PluginCrashedEvent;
  type PopupOptions (line 19154) | type PopupOptions = Electron.PopupOptions;
  type PreconnectOptions (line 19155) | type PreconnectOptions = Electron.PreconnectOptions;
  type PrintToPDFOptions (line 19156) | type PrintToPDFOptions = Electron.PrintToPDFOptions;
  type Privileges (line 19157) | type Privileges = Electron.Privileges;
  type ProgressBarOptions (line 19158) | type ProgressBarOptions = Electron.ProgressBarOptions;
  type Provider (line 19159) | type Provider = Electron.Provider;
  type PurchaseProductOpts (line 19160) | type PurchaseProductOpts = Electron.PurchaseProductOpts;
  type ReadBookmark (line 19161) | type ReadBookmark = Electron.ReadBookmark;
  type RegistrationCompletedDetails (line 19162) | type RegistrationCompletedDetails = Electron.RegistrationCompletedDetails;
  type RelaunchOptions (line 19163) | type RelaunchOptions = Electron.RelaunchOptions;
  type RenderProcessGoneDetails (line 19164) | type RenderProcessGoneDetails = Electron.RenderProcessGoneDetails;
  type Request (line 19165) | type Request = Electron.Request;
  type ResizeOptions (line 19166) | type ResizeOptions = Electron.ResizeOptions;
  type ResolveHostOptions (line 19167) | type ResolveHostOptions = Electron.ResolveHostOptions;
  type ResourceUsage (line 19168) | type ResourceUsage = Electron.ResourceUsage;
  type Response (line 19169) | type Response = Electron.Response;
  type Result (line 19170) | type Result = Electron.Result;
  type SaveDialogOptions (line 19171) | type SaveDialogOptions = Electron.SaveDialogOptions;
  type SaveDialogReturnValue (line 19172) | type SaveDialogReturnValue = Electron.SaveDialogReturnValue;
  type SaveDialogSyncOptions (line 19173) | type SaveDialogSyncOptions = Electron.SaveDialogSyncOptions;
  type SelectHidDeviceDetails (line 19174) | type SelectHidDeviceDetails = Electron.SelectHidDeviceDetails;
  type SelectUsbDeviceDetails (line 19175) | type SelectUsbDeviceDetails = Electron.SelectUsbDeviceDetails;
  type SerialPortRevokedDetails (line 19176) | type SerialPortRevokedDetails = Electron.SerialPortRevokedDetails;
  type Settings (line 19177) | type Settings = Electron.Settings;
  type SourcesOptions (line 19178) | type SourcesOptions = Electron.SourcesOptions;
  type SSLConfigConfig (line 19179) | type SSLConfigConfig = Electron.SSLConfigConfig;
  type StartLoggingOptions (line 19180) | type StartLoggingOptions = Electron.StartLoggingOptions;
  type Streams (line 19181) | type Streams = Electron.Streams;
  type SystemMemoryInfo (line 19182) | type SystemMemoryInfo = Electron.SystemMemoryInfo;
  type TitleBarOverlayOptions (line 19183) | type TitleBarOverlayOptions = Electron.TitleBarOverlayOptions;
  type TitleOptions (line 19184) | type TitleOptions = Electron.TitleOptions;
  type ToBitmapOptions (line 19185) | type ToBitmapOptions = Electron.ToBitmapOptions;
  type ToDataURLOptions (line 19186) | type ToDataURLOptions = Electron.ToDataURLOptions;
  type ToPNGOptions (line 19187) | type ToPNGOptions = Electron.ToPNGOptions;
  type TouchBarButtonConstructorOptions (line 19188) | type TouchBarButtonConstructorOptions = Electron.TouchBarButtonConstruct...
  type TouchBarColorPickerConstructorOptions (line 19189) | type TouchBarColorPickerConstructorOptions = Electron.TouchBarColorPicke...
  type TouchBarConstructorOptions (line 19190) | type TouchBarConstructorOptions = Electron.TouchBarConstructorOptions;
  type TouchBarGroupConstructorOptions (line 19191) | type TouchBarGroupConstructorOptions = Electron.TouchBarGroupConstructor...
  type TouchBarLabelConstructorOptions (line 19192) | type TouchBarLabelConstructorOptions = Electron.TouchBarLabelConstructor...
  type TouchBarPopoverConstructorOptions (line 19193) | type TouchBarPopoverConstructorOptions = Electron.TouchBarPopoverConstru...
  type TouchBarScrubberConstructorOptions (line 19194) | type TouchBarScrubberConstructorOptions = Electron.TouchBarScrubberConst...
  type TouchBarSegmentedControlConstructorOptions (line 19195) | type TouchBarSegmentedControlConstructorOptions = Electron.TouchBarSegme...
  type TouchBarSliderConstructorOptions (line 19196) | type TouchBarSliderConstructorOptions = Electron.TouchBarSliderConstruct...
  type TouchBarSpacerConstructorOptions (line 19197) | type TouchBarSpacerConstructorOptions = Electron.TouchBarSpacerConstruct...
  type TraceBufferUsageReturnValue (line 19198) | type TraceBufferUsageReturnValue = Electron.TraceBufferUsageReturnValue;
  type UpdateTargetUrlEvent (line 19199) | type UpdateTargetUrlEvent = Electron.UpdateTargetUrlEvent;
  type UploadProgress (line 19200) | type UploadProgress = Electron.UploadProgress;
  type UsbDeviceRevokedDetails (line 19201) | type UsbDeviceRevokedDetails = Electron.UsbDeviceRevokedDetails;
  type USBProtectedClassesHandlerHandlerDetails (line 19202) | type USBProtectedClassesHandlerHandlerDetails = Electron.USBProtectedCla...
  type VisibleOnAllWorkspacesOptions (line 19203) | type VisibleOnAllWorkspacesOptions = Electron.VisibleOnAllWorkspacesOpti...
  type WebContentsAudioStateChangedEventParams (line 19204) | type WebContentsAudioStateChangedEventParams = Electron.WebContentsAudio...
  type WebContentsDidRedirectNavigationEventParams (line 19205) | type WebContentsDidRedirectNavigationEventParams = Electron.WebContentsD...
  type WebContentsDidStartNavigationEventParams (line 19206) | type WebContentsDidStartNavigationEventParams = Electron.WebContentsDidS...
  type WebContentsPrintOptions (line 19207) | type WebContentsPrintOptions = Electron.WebContentsPrintOptions;
  type WebContentsWillFrameNavigateEventParams (line 19208) | type WebContentsWillFrameNavigateEventParams = Electron.WebContentsWillF...
  type WebContentsWillNavigateEventParams (line 19209) | type WebContentsWillNavigateEventParams = Electron.WebContentsWillNaviga...
  type WebContentsWillRedirectEventParams (line 19210) | type WebContentsWillRedirectEventParams = Electron.WebContentsWillRedire...
  type WebviewTagPrintOptions (line 19211) | type WebviewTagPrintOptions = Electron.WebviewTagPrintOptions;
  type WillFrameNavigateEvent (line 19212) | type WillFrameNavigateEvent = Electron.WillFrameNavigateEvent;
  type WillNavigateEvent (line 19213) | type WillNavigateEvent = Electron.WillNavigateEvent;
  type WillResizeDetails (line 19214) | type WillResizeDetails = Electron.WillResizeDetails;
  type EditFlags (line 19215) | type EditFlags = Electron.EditFlags;
  type Env (line 19216) | type Env = Electron.Env;
  type FoundInPageResult (line 19217) | type FoundInPageResult = Electron.FoundInPageResult;
  type LaunchItems (line 19218) | type LaunchItems = Electron.LaunchItems;
  type Margins (line 19219) | type Margins = Electron.Margins;
  type MediaFlags (line 19220) | type MediaFlags = Electron.MediaFlags;
  type PageRanges (line 19221) | type PageRanges = Electron.PageRanges;
  type Params (line 19222) | type Params = Electron.Params;
  type TitleBarOverlay (line 19223) | type TitleBarOverlay = Electron.TitleBarOverlay;
  type Video (line 19224) | type Video = Electron.Video;
  type WebPreferences (line 19225) | type WebPreferences = Electron.WebPreferences;
  type DefaultFontFamily (line 19226) | type DefaultFontFamily = Electron.DefaultFontFamily;
  type BluetoothDevice (line 19227) | type BluetoothDevice = Electron.BluetoothDevice;
  type Certificate (line 19228) | type Certificate = Electron.Certificate;
  type CertificatePrincipal (line 19229) | type CertificatePrincipal = Electron.CertificatePrincipal;
  type Cookie (line 19230) | type Cookie = Electron.Cookie;
  type CPUUsage (line 19231) | type CPUUsage = Electron.CPUUsage;
  type CrashReport (line 19232) | type CrashReport = Electron.CrashReport;
  type CustomScheme (line 19233) | type CustomScheme = Electron.CustomScheme;
  type DesktopCapturerSource (line 19234) | type DesktopCapturerSource = Electron.DesktopCapturerSource;
  type Display (line 19235) | type Display = Electron.Display;
  type Extension (line 19236) | type Extension = Electron.Extension;
  type ExtensionInfo (line 19237) | type ExtensionInfo = Electron.ExtensionInfo;
  type FileFilter (line 19238) | type FileFilter = Electron.FileFilter;
  type FilePathWithHeaders (line 19239) | type FilePathWithHeaders = Electron.FilePathWithHeaders;
  type GPUFeatureStatus (line 19240) | type GPUFeatureStatus = Electron.GPUFeatureStatus;
  type HIDDevice (line 19241) | type HIDDevice = Electron.HIDDevice;
  type InputEvent (line 19242) | type InputEvent = Electron.InputEvent;
  type IOCounters (line 19243) | type IOCounters = Electron.IOCounters;
  type IpcMainEvent (line 19244) | type IpcMainEvent = Electron.IpcMainEvent;
  type IpcMainInvokeEvent (line 19245) | type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
  type IpcRendererEvent (line 19246) | type IpcRendererEvent = Electron.IpcRendererEvent;
  type JumpListCategory (line 19247) | type JumpListCategory = Electron.JumpListCategory;
  type JumpListItem (line 19248) | type JumpListItem = Electron.JumpListItem;
  type KeyboardEvent (line 19249) | type KeyboardEvent = Electron.KeyboardEvent;
  type KeyboardInputEvent (line 19250) | type KeyboardInputEvent = Electron.KeyboardInputEvent;
  type MemoryInfo (line 19251) | type MemoryInfo = Electron.MemoryInfo;
  type MemoryUsageDetails (line 19252) | type MemoryUsageDetails = Electron.MemoryUsageDetails;
  type MimeTypedBuffer (line 19253) | type MimeTypedBuffer = Electron.MimeTypedBuffer;
  type MouseInputEvent (line 19254) | type MouseInputEvent = Electron.MouseInputEvent;
  type MouseWheelInputEvent (line 19255) | type MouseWheelInputEvent = Electron.MouseWheelInputEvent;
  type NotificationAction (line 19256) | type NotificationAction = Electron.NotificationAction;
  type NotificationResponse (line 19257) | type NotificationResponse = Electron.NotificationResponse;
  type PaymentDiscount (line 19258) | type PaymentDiscount = Electron.PaymentDiscount;
  type Point (line 19259) | type Point = Electron.Point;
  type PostBody (line 19260) | type PostBody = Electron.PostBody;
  type PrinterInfo (line 19261) | type PrinterInfo = Electron.PrinterInfo;
  type ProcessMemoryInfo (line 19262) | type ProcessMemoryInfo = Electron.ProcessMemoryInfo;
  type ProcessMetric (line 19263) | type ProcessMetric = Electron.ProcessMetric;
  type Product (line 19264) | type Product = Electron.Product;
  type ProductDiscount (line 19265) | type ProductDiscount = Electron.ProductDiscount;
  type ProductSubscriptionPeriod (line 19266) | type ProductSubscriptionPeriod = Electron.ProductSubscriptionPeriod;
  type ProtocolRequest (line 19267) | type ProtocolRequest = Electron.ProtocolRequest;
  type ProtocolResponse (line 19268) | type ProtocolResponse = Electron.ProtocolResponse;
  type ProtocolResponseUploadData (line 19269) | type ProtocolResponseUploadData = Electron.ProtocolResponseUploadData;
  type Rectangle (line 19270) | type Rectangle = Electron.Rectangle;
  type Referrer (line 19271) | type Referrer = Electron.Referrer;
  type ResolvedEndpoint (line 19272) | type ResolvedEndpoint = Electron.ResolvedEndpoint;
  type ResolvedHost (line 19273) | type ResolvedHost = Electron.ResolvedHost;
  type ScrubberItem (line 19274) | type ScrubberItem = Electron.ScrubberItem;
  type SegmentedControlSegment (line 19275) | type SegmentedControlSegment = Electron.SegmentedControlSegment;
  type SerialPort (line 19276) | type SerialPort = Electron.SerialPort;
  type ServiceWorkerInfo (line 19277) | type ServiceWorkerInfo = Electron.ServiceWorkerInfo;
  type SharedWorkerInfo (line 19278) | type SharedWorkerInfo = Electron.SharedWorkerInfo;
  type SharingItem (line 19279) | type SharingItem = Electron.SharingItem;
  type ShortcutDetails (line 19280) | type ShortcutDetails = Electron.ShortcutDetails;
  type Size (line 19281) | type Size = Electron.Size;
  type Task (line 19282) | type Task = Electron.Task;
  type ThumbarButton (line 19283) | type ThumbarButton = Electron.ThumbarButton;
  type TraceCategoriesAndOptions (line 19284) | type TraceCategoriesAndOptions = Electron.TraceCategoriesAndOptions;
  type TraceConfig (line 19285) | type TraceConfig = Electron.TraceConfig;
  type Transaction (line 19286) | type Transaction = Electron.Transaction;
  type UploadData (line 19287) | type UploadData = Electron.UploadData;
  type UploadFile (line 19288) | type UploadFile = Electron.UploadFile;
  type UploadRawData (line 19289) | type UploadRawData = Electron.UploadRawData;
  type USBDevice (line 19290) | type USBDevice = Electron.USBDevice;
  type UserDefaultTypes (line 19291) | type UserDefaultTypes = Electron.UserDefaultTypes;
  type WebRequestFilter (line 19292) | type WebRequestFilter = Electron.WebRequestFilter;
  type WebSource (line 19293) | type WebSource = Electron.WebSource;
  type Event (line 19297) | type Event<Params extends object = {}> = Electron.Event<Params>;
  type App (line 19299) | type App = Electron.App;
  type AutoUpdater (line 19301) | type AutoUpdater = Electron.AutoUpdater;
  class BrowserView (line 19302) | class BrowserView extends Electron.BrowserView {}
  class BrowserWindow (line 19303) | class BrowserWindow extends Electron.BrowserWindow {}
  type ClientRequest (line 19304) | type ClientRequest = Electron.ClientRequest;
  type CommandLine (line 19305) | type CommandLine = Electron.CommandLine;
  type ContentTracing (line 19307) | type ContentTracing = Electron.ContentTracing;
  type Cookies (line 19308) | type Cookies = Electron.Cookies;
  type Debugger (line 19309) | type Debugger = Electron.Debugger;
  type DesktopCapturer (line 19311) | type DesktopCapturer = Electron.DesktopCapturer;
  type Dialog (line 19313) | type Dialog = Electron.Dialog;
  type Dock (line 19314) | type Dock = Electron.Dock;
  type DownloadItem (line 19315) | type DownloadItem = Electron.DownloadItem;
  type GlobalShortcut (line 19317) | type GlobalShortcut = Electron.GlobalShortcut;
  type InAppPurchase (line 19319) | type InAppPurchase = Electron.InAppPurchase;
  type IncomingMessage (line 19320) | type IncomingMessage = Electron.IncomingMessage;
  type IpcMain (line 19322) | type IpcMain = Electron.IpcMain;
  class Menu (line 19323) | class Menu extends Electron.Menu {}
  class MenuItem (line 19324) | class MenuItem extends Electron.MenuItem {}
  class MessageChannelMain (line 19325) | class MessageChannelMain extends Electron.MessageChannelMain {}
  type MessagePortMain (line 19326) | type MessagePortMain = Electron.MessagePortMain;
  type NativeTheme (line 19328) | type NativeTheme = Electron.NativeTheme;
  type Net (line 19330) | type Net = Electron.Net;
  type NetLog (line 19332) | type NetLog = Electron.NetLog;
  class Notification (line 19333) | class Notification extends Electron.Notification {}
  type PowerMonitor (line 19335) | type PowerMonitor = Electron.PowerMonitor;
  type PowerSaveBlocker (line 19337) | type PowerSaveBlocker = Electron.PowerSaveBlocker;
  type Protocol (line 19339) | type Protocol = Electron.Protocol;
  type PushNotifications (line 19341) | type PushNotifications = Electron.PushNotifications;
  type SafeStorage (line 19343) | type SafeStorage = Electron.SafeStorage;
  type Screen (line 19345) | type Screen = Electron.Screen;
  type ServiceWorkers (line 19346) | type ServiceWorkers = Electron.ServiceWorkers;
  type Session (line 19348) | type Session = Electron.Session;
  class ShareMenu (line 19349) | class ShareMenu extends Electron.ShareMenu {}
  type SystemPreferences (line 19351) | type SystemPreferences = Electron.SystemPreferences;
  class TouchBar (line 19352) | class TouchBar extends Electron.TouchBar {}
  type TouchBarButton (line 19353) | type TouchBarButton = Electron.TouchBarButton;
  type TouchBarColorPicker (line 19354) | type TouchBarColorPicker = Electron.TouchBarColorPicker;
  type TouchBarGroup (line 19355) | type TouchBarGroup = Electron.TouchBarGroup;
  type TouchBarLabel (line 19356) | type TouchBarLabel = Electron.TouchBarLabel;
  type TouchBarOtherItemsProxy (line 19357) | type TouchBarOtherItemsProxy = Electron.TouchBarOtherItemsProxy;
  type TouchBarPopover (line 19358) | type TouchBarPopover = Electron.TouchBarPopover;
  type TouchBarScrubber (line 19359) | type TouchBarScrubber = Electron.TouchBarScrubber;
  type TouchBarSegmentedControl (line 19360) | type TouchBarSegmentedControl = Electron.TouchBarSegmentedControl;
  type TouchBarSlider (line 19361) | type TouchBarSlider = Electron.TouchBarSlider;
  type TouchBarSpacer (line 19362) | type TouchBarSpacer = Electron.TouchBarSpacer;
  class Tray (line 19363) | class Tray extends Electron.Tray {}
  type UtilityProcess (line 19365) | type UtilityProcess = Electron.UtilityProcess;
  type WebContents (line 19367) | type WebContents = Electron.WebContents;
  type WebFrameMain (line 19369) | type WebFrameMain = Electron.WebFrameMain;
  type WebRequest (line 19370) | type WebRequest = Electron.WebRequest;
  type AboutPanelOptionsOptions (line 19371) | type AboutPanelOptionsOptions = Electron.AboutPanelOptionsOptions;
  type AddRepresentationOptions (line 19372) | type AddRepresentationOptions = Electron.AddRepresentationOptions;
  type AdjustSelectionOptions (line 19373) | type AdjustSelectionOptions = Electron.AdjustSelectionOptions;
  type AnimationSettings (line 19374) | type AnimationSettings = Electron.AnimationSettings;
  type AppDetailsOptions (line 19375) | type AppDetailsOptions = Electron.AppDetailsOptions;
  type ApplicationInfoForProtocolReturnValue (line 19376) | type ApplicationInfoForProtocolReturnValue = Electron.ApplicationInfoFor...
  type AuthenticationResponseDetails (line 19377) | type AuthenticationResponseDetails = Electron.AuthenticationResponseDeta...
  type AuthInfo (line 19378) | type AuthInfo = Electron.AuthInfo;
  type AutoResizeOptions (line 19379) | type AutoResizeOptions = Electron.AutoResizeOptions;
  type BeforeSendResponse (line 19380) | type BeforeSendResponse = Electron.BeforeSendResponse;
  type BitmapOptions (line 19381) | type BitmapOptions = Electron.BitmapOptions;
  type BlinkMemoryInfo (line 19382) | type BlinkMemoryInfo = Electron.BlinkMemoryInfo;
  type BluetoothPairingHandlerHandlerDetails (line 19383) | type BluetoothPairingHandlerHandlerDetails = Electron.BluetoothPairingHa...
  type BrowserViewConstructorOptions (line 19384) | type BrowserViewConstructorOptions = Electron.BrowserViewConstructorOpti...
  type BrowserWindowConstructorOptions (line 19385) | type BrowserWindowConstructorOptions = Electron.BrowserWindowConstructor...
  type CallbackResponse (line 19386) | type CallbackResponse = Electron.CallbackResponse;
  type CertificateTrustDialogOptions (line 19387) | type CertificateTrustDialogOptions = Electron.CertificateTrustDialogOpti...
  type ClearCodeCachesOptions (line 19388) | type ClearCodeCachesOptions = Electron.ClearCodeCachesOptions;
  type ClearStorageDataOptions (line 19389) | type ClearStorageDataOptions = Electron.ClearStorageDataOptions;
  type ClientRequestConstructorOptions (line 19390) | type ClientRequestConstructorOptions = Electron.ClientRequestConstructor...
  type CloseOpts (line 19391) | type CloseOpts = Electron.CloseOpts;
  type Config (line 19392) | type Config = Electron.Config;
  type ConfigureHostResolverOptions (line 19393) | type ConfigureHostResolverOptions = Electron.ConfigureHostResolverOptions;
  type ConsoleMessageEvent (line 19394) | type ConsoleMessageEvent = Electron.ConsoleMessageEvent;
  type ContextMenuEvent (line 19395) | type ContextMenuEvent = Electron.ContextMenuEvent;
  type ContextMenuParams (line 19396) | type ContextMenuParams = Electron.ContextMenuParams;
  type ContinueActivityDetails (line 19397) | type ContinueActivityDetails = Electron.ContinueActivityDetails;
  type CookiesGetFilter (line 19398) | type CookiesGetFilter = Electron.CookiesGetFilter;
  type CookiesSetDetails (line 19399) | type CookiesSetDetails = Electron.CookiesSetDetails;
  type CrashReporterStartOptions (line 19400) | type CrashReporterStartOptions = Electron.CrashReporterStartOptions;
  type CreateFromBitmapOptions (line 19401) | type CreateFromBitmapOptions = Electron.CreateFromBitmapOptions;
  type CreateFromBufferOptions (line 19402) | type CreateFromBufferOptions = Electron.CreateFromBufferOptions;
  type CreateInterruptedDownloadOptions (line 19403) | type CreateInterruptedDownloadOptions = Electron.CreateInterruptedDownlo...
  type Data (line 19404) | type Data = Electron.Data;
  type Details (line 19405) | type Details = Electron.Details;
  type DevicePermissionHandlerHandlerDetails (line 19406) | type DevicePermissionHandlerHandlerDetails = Electron.DevicePermissionHa...
  type DevtoolsOpenUrlEvent (line 19407) | type DevtoolsOpenUrlEvent = Electron.DevtoolsOpenUrlEvent;
  type DidChangeThemeColorEvent (line 19408) | type DidChangeThemeColorEvent = Electron.DidChangeThemeColorEvent;
  type DidCreateWindowDetails (line 19409) | type DidCreateWindowDetails = Electron.DidCreateWindowDetails;
  type DidFailLoadEvent (line 19410) | type DidFailLoadEvent = Electron.DidFailLoadEvent;
  type DidFrameFinishLoadEvent (line 19411) | type DidFrameFinishLoadEvent = Electron.DidFrameFinishLoadEvent;
  type DidFrameNavigateEvent (line 19412) | type DidFrameNavigateEvent = Electron.DidFrameNavigateEvent;
  type DidNavigateEvent (line 19413) | type DidNavigateEvent = Electron.DidNavigateEvent;
  type DidNavigateInPageEvent (line 19414) | type DidNavigateInPageEvent = Electron.DidNavigateInPageEvent;
  type DidRedirectNavigationEvent (line 19415) | type DidRedirectNavigationEvent = Electron.DidRedirectNavigationEvent;
  type DidStartNavigationEvent (line 19416) | type DidStartNavigationEvent = Electron.DidStartNavigationEvent;
  type DisplayBalloonOptions (line 19417) | type DisplayBalloonOptions = Electron.DisplayBalloonOptions;
  type DisplayMediaRequestHandlerHandlerRequest (line 19418) | type DisplayMediaRequestHandlerHandlerRequest = Electron.DisplayMediaReq...
  type EnableNetworkEmulationOptions (line 19419) | type EnableNetworkEmulationOptions = Electron.EnableNetworkEmulationOpti...
  type FeedURLOptions (line 19420) | type FeedURLOptions = Electron.FeedURLOptions;
  type FileIconOptions (line 19421) | type FileIconOptions = Electron.FileIconOptions;
  type FindInPageOptions (line 19422) | type FindInPageOptions = Electron.FindInPageOptions;
  type FocusOptions (line 19423) | type FocusOptions = Electron.FocusOptions;
  type ForkOptions (line 19424) | type ForkOptions = Electron.ForkOptions;
  type FoundInPageEvent (line 19425) | type FoundInPageEvent = Electron.FoundInPageEvent;
  type FrameCreatedDetails (line 19426) | type FrameCreatedDetails = Electron.FrameCreatedDetails;
  type FromPartitionOptions (line 19427) | type FromPartitionOptions = Electron.FromPartitionOptions;
  type FromPathOptions (line 19428) | type FromPathOptions = Electron.FromPathOptions;
  type HandlerDetails (line 19429) | type HandlerDetails = Electron.HandlerDetails;
  type HeadersReceivedResponse (line 19430) | type HeadersReceivedResponse = Electron.HeadersReceivedResponse;
  type HeapStatistics (line 19431) | type HeapStatistics = Electron.HeapStatistics;
  type HidDeviceAddedDetails (line 19432) | type HidDeviceAddedDetails = Electron.HidDeviceAddedDetails;
  type HidDeviceRemovedDetails (line 19433) | type HidDeviceRemovedDetails = Electron.HidDeviceRemovedDetails;
  type HidDeviceRevokedDetails (line 19434) | type HidDeviceRevokedDetails = Electron.HidDeviceRevokedDetails;
  type IgnoreMouseEventsOptions (line 19435) | type IgnoreMouseEventsOptions = Electron.IgnoreMouseEventsOptions;
  type ImportCertificateOptions (line 19436) | type ImportCertificateOptions = Electron.ImportCertificateOptions;
  type Info (line 19437) | type Info = Electron.Info;
  type Input (line 19438) | type Input = Electron.Input;
  type InsertCSSOptions (line 19439) | type InsertCSSOptions = Electron.InsertCSSOptions;
  type IpcMessageEvent (line 19440) | type IpcMessageEvent = Electron.IpcMessageEvent;
  type Item (line 19441) | type Item = Electron.Item;
  type JumpListSettings (line 19442) | type JumpListSettings = Electron.JumpListSettings;
  type LoadCommitEvent (line 19443) | type LoadCommitEvent = Electron.LoadCommitEvent;
  type LoadExtensionOptions (line 19444) | type LoadExtensionOptions = Electron.LoadExtensionOptions;
  type LoadFileOptions (line 19445) | type LoadFileOptions = Electron.LoadFileOptions;
  type LoadURLOptions (line 19446) | type LoadURLOptions = Electron.LoadURLOptions;
  type LoginItemSettings (line 19447) | type LoginItemSettings = Electron.LoginItemSettings;
  type LoginItemSettingsOptions (line 19448) | type LoginItemSettingsOptions = Electron.LoginItemSettingsOptions;
  type MenuItemConstructorOptions (line 19449) | type MenuItemConstructorOptions = Electron.MenuItemConstructorOptions;
  type MessageBoxOptions (line 19450) | type MessageBoxOptions = Electron.MessageBoxOptions;
  type MessageBoxReturnValue (line 19451) | type MessageBoxReturnValue = Electron.MessageBoxReturnValue;
  type MessageBoxSyncOptions (line 19452) | type MessageBoxSyncOptions = Electron.MessageBoxSyncOptions;
  type MessageDetails (line 19453) | type MessageDetails = Electron.MessageDetails;
  type MessageEvent (line 19454) | type MessageEvent = Electron.MessageEvent;
  type MoveToApplicationsFolderOptions (line 19455) | type MoveToApplicationsFolderOptions = Electron.MoveToApplicationsFolder...
  type NotificationConstructorOptions (line 19456) | type NotificationConstructorOptions = Electron.NotificationConstructorOp...
  type OnBeforeRedirectListenerDetails (line 19457) | type OnBeforeRedirectListenerDetails = Electron.OnBeforeRedirectListener...
  type OnBeforeRequestListenerDetails (line 19458) | type OnBeforeRequestListenerDetails = Electron.OnBeforeRequestListenerDe...
  type OnBeforeSendHeadersListenerDetails (line 19459) | type OnBeforeSendHeadersListenerDetails = Electron.OnBeforeSendHeadersLi...
  type OnCompletedListenerDetails (line 19460) | type OnCompletedListenerDetails = Electron.OnCompletedListenerDetails;
  type OnErrorOccurredListenerDetails (line 19461) | type OnErrorOccurredListenerDetails = Electron.OnErrorOccurredListenerDe...
  type OnHeadersReceivedListenerDetails (line 19462) | type OnHeadersReceivedListenerDetails = Electron.OnHeadersReceivedListen...
  type OnResponseStartedListenerDetails (line 19463) | type OnResponseStartedListenerDetails = Electron.OnResponseStartedListen...
  type OnSendHeadersListenerDetails (line 19464) | type OnSendHeadersListenerDetails = Electron.OnSendHeadersListenerDetails;
  type OpenDevToolsOptions (line 19465) | type OpenDevToolsOptions = Electron.OpenDevToolsOptions;
  type OpenDialogOptions (line 19466) | type OpenDialogOptions = Electron.OpenDialogOptions;
  type OpenDialogReturnValue (line 19467) | type OpenDialogReturnValue = Electron.OpenDialogReturnValue;
  type OpenDialogSyncOptions (line 19468) | type OpenDialogSyncOptions = Electron.OpenDialogSyncOptions;
  type OpenExternalOptions (line 19469) | type OpenExternalOptions = Electron.OpenExternalOptions;
  type Options (line 19470) | type Options = Electron.Options;
  type Opts (line 19471) | type Opts = Electron.Opts;
  type PageFaviconUpdatedEvent (line 19472) | type PageFaviconUpdatedEvent = Electron.PageFaviconUpdatedEvent;
  type PageTitleUpdatedEvent (line 19473) | type PageTitleUpdatedEvent = Electron.PageTitleUpdatedEvent;
  type Parameters (line 19474) | type Parameters = Electron.Parameters;
  type Payment (line 19475) | type Payment = Electron.Payment;
  type PermissionCheckHandlerHandlerDetails (line 19476) | type PermissionCheckHandlerHandlerDetails = Electron.PermissionCheckHand...
  type PermissionRequestHandlerHandlerDetails (line 19477) | type PermissionRequestHandlerHandlerDetails = Electron.PermissionRequest...
  type PluginCrashedEvent (line 19478) | type PluginCrashedEvent = Electron.PluginCrashedEvent;
  type PopupOptions (line 19479) | type PopupOptions = Electron.PopupOptions;
  type PreconnectOptions (line 19480) | type PreconnectOptions = Electron.PreconnectOptions;
  type PrintToPDFOptions (line 19481) | type PrintToPDFOptions = Electron.PrintToPDFOptions;
  type Privileges (line 19482) | type Privileges = Electron.Privileges;
  type ProgressBarOptions (line 19483) | type ProgressBarOptions = Electron.ProgressBarOptions;
  type Provider (line 19484) | type Provider = Electron.Provider;
  type PurchaseProductOpts (line 19485) | type PurchaseProductOpts = Electron.PurchaseProductOpts;
  type ReadBookmark (line 19486) | type ReadBookmark = Electron.ReadBookmark;
  type RegistrationCompletedDetails (line 19487) | type RegistrationCompletedDetails = Electron.RegistrationCompletedDetails;
  type RelaunchOptions (line 19488) | type RelaunchOptions = Electron.RelaunchOptions;
  type RenderProcessGoneDetails (line 19489) | type RenderProcessGoneDetails = Electron.RenderProcessGoneDetails;
  type Request (line 19490) | type Request = Electron.Request;
  type ResizeOptions (line 19491) | type ResizeOptions = Electron.ResizeOptions;
  type ResolveHostOptions (line 19492) | type ResolveHostOptions = Electron.ResolveHostOptions;
  type ResourceUsage (line 19493) | type ResourceUsage = Electron.ResourceUsage;
  type Response (line 19494) | type Response = Electron.Response;
  type Result (line 19495) | type Result = Electron.Result;
  type SaveDialogOptions (line 19496) | type SaveDialogOptions = Electron.SaveDialogOptions;
  type SaveDialogReturnValue (line 19497) | type SaveDialogReturnValue = Electron.SaveDialogReturnValue;
  type SaveDialogSyncOptions (line 19498) | type SaveDialogSyncOptions = Electron.SaveDialogSyncOptions;
  type SelectHidDeviceDetails (line 19499) | type SelectHidDeviceDetails = Electron.SelectHidDeviceDetails;
  type SelectUsbDeviceDetails (line 19500) | type SelectUsbDeviceDetails = Electron.SelectUsbDeviceDetails;
  type SerialPortRevokedDetails (line 19501) | type SerialPortRevokedDetails = Electron.SerialPortRevokedDetails;
  type Settings (line 19502) | type Settings = Electron.Settings;
  type SourcesOptions (line 19503) | type SourcesOptions = Electron.SourcesOptions;
  type SSLConfigConfig (line 19504) | type SSLConfigConfig = Electron.SSLConfigConfig;
  type StartLoggingOptions (line 19505) | type StartLoggingOptions = Electron.StartLoggingOptions;
  type Streams (line 19506) | type Streams = Electron.Streams;
  type SystemMemoryInfo (line 19507) | type SystemMemoryInfo = Electron.SystemMemoryInfo;
  type TitleBarOverlayOptions (line 19508) | type TitleBarOverlayOptions = Electron.TitleBarOverlayOptions;
  type TitleOptions (line 19509) | type TitleOptions = Electron.TitleOptions;
  type ToBitmapOptions (line 19510) | type ToBitmapOptions = Electron.ToBitmapOptions;
  type ToDataURLOptions (line 19511) | type ToDataURLOptions = Electron.ToDataURLOptions;
  type ToPNGOptions (line 19512) | type ToPNGOptions = Electron.ToPNGOptions;
  type TouchBarButtonConstructorOptions (line 19513) | type TouchBarButtonConstructorOptions = Electron.TouchBarButtonConstruct...
  type TouchBarColorPickerConstructorOptions (line 19514) | type TouchBarColorPickerConstructorOptions = Electron.TouchBarColorPicke...
  type TouchBarConstructorOptions (line 19515) | type TouchBarConstructorOptions = Electron.TouchBarConstructorOptions;
  type TouchBarGroupConstructorOptions (line 19516) | type TouchBarGroupConstructorOptions = Electron.TouchBarGroupConstructor...
  type TouchBarLabelConstructorOptions (line 19517) | type TouchBarLabelConstructorOptions = Electron.TouchBarLabelConstructor...
  type TouchBarPopoverConstructorOptions (line 19518) | type TouchBarPopoverConstructorOptions = Electron.TouchBarPopoverConstru...
  type TouchBarScrubberConstructorOptions (line 19519) | type TouchBarScrubberConstructorOptions = Electron.TouchBarScrubberConst...
  type TouchBarSegmentedControlConstructorOptions (line 19520) | type TouchBarSegmentedControlConstructorOptions = Electron.TouchBarSegme...
  type TouchBarSliderConstructorOptions (line 19521) | type TouchBarSliderConstructorOptions = Electron.TouchBarSliderConstruct...
  type TouchBarSpacerConstructorOptions (line 19522) | type TouchBarSpacerConstructorOptions = Electron.TouchBarSpacerConstruct...
  type TraceBufferUsageReturnValue (line 19523) | type TraceBufferUsageReturnValue = Electron.TraceBufferUsageReturnValue;
  type UpdateTargetUrlEvent (line 19524) | type UpdateTargetUrlEvent = Electron.UpdateTargetUrlEvent;
  type UploadProgress (line 19525) | type UploadProgress = Electron.UploadProgress;
  type UsbDeviceRevokedDetails (line 19526) | type UsbDeviceRevokedDetails = Electron.UsbDeviceRevokedDetails;
  type USBProtectedClassesHandlerHandlerDetails (line 19527) | type USBProtectedClassesHandlerHandlerDetails = Electron.USBProtectedCla...
  type VisibleOnAllWorkspacesOptions (line 19528) | type VisibleOnAllWorkspacesOptions = Electron.VisibleOnAllWorkspacesOpti...
  type WebContentsAudioStateChangedEventParams (line 19529) | type WebContentsAudioStateChangedEventParams = Electron.WebContentsAudio...
  type WebContentsDidRedirectNavigationEventParams (line 19530) | type WebContentsDidRedirectNavigationEventParams = Electron.WebContentsD...
  type WebContentsDidStartNavigationEventParams (line 19531) | type WebContentsDidStartNavigationEventParams = Electron.WebContentsDidS...
  type WebContentsPrintOptions (line 19532) | type WebContentsPrintOptions = Electron.WebContentsPrintOptions;
  type WebContentsWillFrameNavigateEventParams (line 19533) | type WebContentsWillFrameNavigateEventParams = Electron.WebContentsWillF...
  type WebContentsWillNavigateEventParams (line 19534) | type WebContentsWillNavigateEventParams = Electron.WebContentsWillNaviga...
  type WebContentsWillRedirectEventParams (line 19535) | type WebContentsWillRedirectEventParams = Electron.WebContentsWillRedire...
  type WebviewTagPrintOptions (line 19536) | type WebviewTagPrintOptions = Electron.WebviewTagPrintOptions;
  type WillFrameNavigateEvent (line 19537) | type WillFrameNavigateEvent = Electron.WillFrameNavigateEvent;
  type WillNavigateEvent (line 19538) | type WillNavigateEvent = Electron.WillNavigateEvent;
  type WillResizeDetails (line 19539) | type WillResizeDetails = Electron.WillResizeDetails;
  type EditFlags (line 19540) | type EditFlags = Electron.EditFlags;
  type Env (line 19541) | type Env = Electron.Env;
  type FoundInPageResult (line 19542) | type FoundInPageResult = Electron.FoundInPageResult;
  type LaunchItems (line 19543) | type LaunchItems = Electron.LaunchItems;
  type Margins (line 19544) | type Margins = Electron.Margins;
  type MediaFlags (line 19545) | type MediaFlags = Electron.MediaFlags;
  type PageRanges (line 19546) | type PageRanges = Electron.PageRanges;
  type Params (line 19547) | type Params = Electron.Params;
  type TitleBarOverlay (line 19548) | type TitleBarOverlay = Electron.TitleBarOverlay;
  type Video (line 19549) | type Video = Electron.Video;
  type WebPreferences (line 19550) | type WebPreferences = Electron.WebPreferences;
  type DefaultFontFamily (line 19551) | type DefaultFontFamily = Electron.DefaultFontFamily;
  type BluetoothDevice (line 19552) | type BluetoothDevice = Electron.BluetoothDevice;
  type Certificate (line 19553) | type Certificate = Electron.Certificate;
  type CertificatePrincipal (line 19554) | type CertificatePrincipal = Electron.CertificatePrincipal;
  type Cookie (line 19555) | type Cookie = Electron.Cookie;
  type CPUUsage (line 19556) | type CPUUsage = Electron.CPUUsage;
  type CrashReport (line 19557) | type CrashReport = Electron.CrashReport;
  type CustomScheme (line 19558) | type CustomScheme = Electron.CustomScheme;
  type DesktopCapturerSource (line 19559) | type DesktopCapturerSource = Electron.DesktopCapturerSource;
  type Display (line 19560) | type Display = Electron.Display;
  type Extension (line 19561) | type Extension = Electron.Extension;
  type ExtensionInfo (line 19562) | type ExtensionInfo = Electron.ExtensionInfo;
  type FileFilter (line 19563) | type FileFilter = Electron.FileFilter;
  type FilePathWithHeaders (line 19564) | type FilePathWithHeaders = Electron.FilePathWithHeaders;
  type GPUFeatureStatus (line 19565) | type GPUFeatureStatus = Electron.GPUFeatureStatus;
  type HIDDevice (line 19566) | type HIDDevice = Electron.HIDDevice;
  type InputEvent (line 19567) | type InputEvent = Electron.InputEvent;
  type IOCounters (line 19568) | type IOCounters = Electron.IOCounters;
  type IpcMainEvent (line 19569) | type IpcMainEvent = Electron.IpcMainEvent;
  type IpcMainInvokeEvent (line 19570) | type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
  type IpcRendererEvent (line 19571) | type IpcRendererEvent = Electron.IpcRendererEvent;
  type JumpListCategory (line 19572) | type JumpListCategory = Electron.JumpListCategory;
  type JumpListItem (line 19573) | type JumpListItem = Electron.JumpListItem;
  type KeyboardEvent (line 19574) | type KeyboardEvent = Electron.KeyboardEvent;
  type KeyboardInputEvent (line 19575) | type KeyboardInputEvent = Electron.KeyboardInputEvent;
  type MemoryInfo (line 19576) | type MemoryInfo = Electron.MemoryInfo;
  type MemoryUsageDetails (line 19577) | type MemoryUsageDetails = Electron.MemoryUsageDetails;
  type MimeTypedBuffer (line 19578) | type MimeTypedBuffer = Electron.MimeTypedBuffer;
  type MouseInputEvent (line 19579) | type MouseInputEvent = Electron.MouseInputEvent;
  type MouseWheelInputEvent (line 19580) | type MouseWheelInputEvent = Electron.MouseWheelInputEvent;
  type NotificationAction (line 19581) | type NotificationAction = Electron.NotificationAction;
  type NotificationResponse (line 19582) | type NotificationResponse = Electron.NotificationResponse;
  type PaymentDiscount (line 19583) | type PaymentDiscount = Electron.PaymentDiscount;
  type Point (line 19584) | type Point = Electron.Point;
  type PostBody (line 19585) | type PostBody = Electron.PostBody;
  type PrinterInfo (line 19586) | type PrinterInfo = Electron.PrinterInfo;
  type ProcessMemoryInfo (line 19587) | type ProcessMemoryInfo = Electron.ProcessMemoryInfo;
  type ProcessMetric (line 19588) | type ProcessMetric = Electron.ProcessMetric;
  type Product (line 19589) | type Product = Electron.Product;
  type ProductDiscount (line 19590) | type ProductDiscount = Electron.ProductDiscount;
  type ProductSubscriptionPeriod (line 19591) | type ProductSubscriptionPeriod = Electron.ProductSubscriptionPeriod;
  type ProtocolRequest (line 19592) | type ProtocolRequest = Electron.ProtocolRequest;
  type ProtocolResponse (line 19593) | type ProtocolResponse = Electron.ProtocolResponse;
  type ProtocolResponseUploadData (line 19594) | type ProtocolResponseUploadData = Electron.ProtocolResponseUploadData;
  type Rectangle (line 19595) | type Rectangle = Electron.Rectangle;
  type Referrer (line 19596) | type Referrer = Electron.Referrer;
  type ResolvedEndpoint (line 19597) | type ResolvedEndpoint = Electron.ResolvedEndpoint;
  type ResolvedHost (line 19598) | type ResolvedHost = Electron.ResolvedHost;
  type ScrubberItem (line 19599) | type ScrubberItem = Electron.ScrubberItem;
  type SegmentedControlSegment (line 19600) | type SegmentedControlSegment = Electron.SegmentedControlSegment;
  type SerialPort (line 19601) | type SerialPort = Electron.SerialPort;
  type ServiceWorkerInfo (line 19602) | type ServiceWorkerInfo = Electron.ServiceWorkerInfo;
  type SharedWorkerInfo (line 19603) | type SharedWorkerInfo = Electron.SharedWorkerInfo;
  type SharingItem (line 19604) | type SharingItem = Electron.SharingItem;
  type ShortcutDetails (line 19605) | type ShortcutDetails = Electron.ShortcutDetails;
  type Size (line 19606) | type Size = Electron.Size;
  type Task (line 19607) | type Task = Electron.Task;
  type ThumbarButton (line 19608) | type ThumbarButton = Electron.ThumbarButton;
  type TraceCategoriesAndOptions (line 19609) | type TraceCategoriesAndOptions = Electron.TraceCategoriesAndOptions;
  type TraceConfig (line 19610) | type TraceConfig = Electron.TraceConfig;
  type Transaction (line 19611) | type Transaction = Electron.Transaction;
  type UploadData (line 19612) | type UploadData = Electron.UploadData;
  type UploadFile (line 19613) | type UploadFile = Electron.UploadFile;
  type UploadRawData (line 19614) | type UploadRawData = Electron.UploadRawData;
  type USBDevice (line 19615) | type USBDevice = Electron.USBDevice;
  type UserDefaultTypes (line 19616) | type UserDefaultTypes = Electron.UserDefaultTypes;
  type WebRequestFilter (line 19617) | type WebRequestFilter = Electron.WebRequestFilter;
  type WebSource (line 19618) | type WebSource = Electron.WebSource;
  type Event (line 19622) | type Event<Params extends object = {}> = Electron.Event<Params>;
  type ContextBridge (line 19624) | type ContextBridge = Electron.ContextBridge;
  type IpcRenderer (line 19626) | type IpcRenderer = Electron.IpcRenderer;
  type WebFrame (line 19628) | type WebFrame = Electron.WebFrame;
  type WebviewTag (line 19629) | type WebviewTag = Electron.WebviewTag;
  type AboutPanelOptionsOptions (line 19630) | type AboutPanelOptionsOptions = Electron.AboutPanelOptionsOptions;
  type AddRepresentationOptions (line 19631) | type AddRepresentationOptions = Electron.AddRepresentationOptions;
  type AdjustSelectionOptions (line 19632) | type AdjustSelectionOptions = Electron.AdjustSelectionOptions;
  type AnimationSettings (line 19633) | type AnimationSettings = Electron.AnimationSettings;
  type AppDetailsOptions (line 19634) | type AppDetailsOptions = Electron.AppDetailsOptions;
  type ApplicationInfoForProtocolReturnValue (line 19635) | type ApplicationInfoForProtocolReturnValue = Electron.ApplicationInfoFor...
  type AuthenticationResponseDetails (line 19636) | type AuthenticationResponseDetails = Electron.AuthenticationResponseDeta...
  type AuthInfo (line 19637) | type AuthInfo = Electron.AuthInfo;
  type AutoResizeOptions (line 19638) | type AutoResizeOptions = Electron.AutoResizeOptions;
  type BeforeSendResponse (line 19639) | type BeforeSendResponse = Electron.BeforeSendResponse;
  type BitmapOptions (line 19640) | type BitmapOptions = Electron.BitmapOptions;
  type BlinkMemoryInfo (line 19641) | type BlinkMemoryInfo = Electron.BlinkMemoryInfo;
  type BluetoothPairingHandlerHandlerDetails (line 19642) | type BluetoothPairingHandlerHandlerDetails = Electron.BluetoothPairingHa...
  type BrowserViewConstructorOptions (line 19643) | type BrowserViewConstructorOptions = Electron.BrowserViewConstructorOpti...
  type BrowserWindowConstructorOptions (line 19644) | type BrowserWindowConstructorOptions = Electron.BrowserWindowConstructor...
  type CallbackResponse (line 19645) | type CallbackResponse = Electron.CallbackResponse;
  type CertificateTrustDialogOptions (line 19646) | type CertificateTrustDialogOptions = Electron.CertificateTrustDialogOpti...
  type ClearCodeCachesOptions (line 19647) | type ClearCodeCachesOptions = Electron.ClearCodeCachesOptions;
  type ClearStorageDataOptions (line 19648) | type ClearStorageDataOptions = Electron.ClearStorageDataOptions;
  type ClientRequestConstructorOptions (line 19649) | type ClientRequestConstructorOptions = Electron.ClientRequestConstructor...
  type CloseOpts (line 19650) | type CloseOpts = Electron.CloseOpts;
  type Config (line 19651) | type Config = Electron.Config;
  type ConfigureHostResolverOptions (line 19652) | type ConfigureHostResolverOptions = Electron.ConfigureHostResolverOptions;
  type ConsoleMessageEvent (line 19653) | type ConsoleMessageEvent = Electron.ConsoleMessageEvent;
  type ContextMenuEvent (line 19654) | type ContextMenuEvent = Electron.ContextMenuEvent;
  type ContextMenuParams (line 19655) | type ContextMenuParams = Electron.ContextMenuParams;
  type ContinueActivityDetails (line 19656) | type ContinueActivityDetails = Electron.ContinueActivityDetails;
  type CookiesGetFilter (line 19657) | type CookiesGetFilter = Electron.CookiesGetFilter;
  type CookiesSetDetails (line 19658) | type CookiesSetDetails = Electron.CookiesSetDetails;
  type CrashReporterStartOptions (line 19659) | type CrashReporterStartOptions = Electron.CrashReporterStartOptions;
  type CreateFromBitmapOptions (line 19660) | type CreateFromBitmapOptions = Electron.CreateFromBitmapOptions;
  type CreateFromBufferOptions (line 19661) | type CreateFromBufferOptions = Electron.CreateFromBufferOptions;
  type CreateInterruptedDownloadOptions (line 19662) | type CreateInterruptedDownloadOptions = Electron.CreateInterruptedDownlo...
  type Data (line 19663) | type Data = Electron.Data;
  type Details (line 19664) | type Details = Electron.Details;
  type DevicePermissionHandlerHandlerDetails (line 19665) | type DevicePermissionHandlerHandlerDetails = Electron.DevicePermissionHa...
  type DevtoolsOpenUrlEvent (line 19666) | type DevtoolsOpenUrlEvent = Electron.DevtoolsOpenUrlEvent;
  type DidChangeThemeColorEvent (line 19667) | type DidChangeThemeColorEvent = Electron.DidChangeThemeColorEvent;
  type DidCreateWindowDetails (line 19668) | type DidCreateWindowDetails = Electron.DidCreateWindowDetails;
  type DidFailLoadEvent (line 19669) | type DidFailLoadEvent = Electron.DidFailLoadEvent;
  type DidFrameFinishLoadEvent (line 19670) | type DidFrameFinishLoadEvent = Electron.DidFrameFinishLoadEvent;
  type DidFrameNavigateEvent (line 19671) | type DidFrameNavigateEvent = Electron.DidFrameNavigateEvent;
  type DidNavigateEvent (line 19672) | type DidNavigateEvent = Electron.DidNavigateEvent;
  type DidNavigateInPageEvent (line 19673) | type DidNavigateInPageEvent = Electron.DidNavigateInPageEvent;
  type DidRedirectNavigationEvent (line 19674) | type DidRedirectNavigationEvent = Electron.DidRedirectNavigationEvent;
  type DidStartNavigationEvent (line 19675) | type DidStartNavigationEvent = Electron.DidStartNavigationEvent;
  type DisplayBalloonOptions (line 19676) | type DisplayBalloonOptions = Electron.DisplayBalloonOptions;
  type DisplayMediaRequestHandlerHandlerRequest (line 19677) | type DisplayMediaRequestHandlerHandlerRequest = Electron.DisplayMediaReq...
  type EnableNetworkEmulationOptions (line 19678) | type EnableNetworkEmulationOptions = Electron.EnableNetworkEmulationOpti...
  type FeedURLOptions (line 19679) | type FeedURLOptions = Electron.FeedURLOptions;
  type FileIconOptions (line 19680) | type FileIconOptions = Electron.FileIconOptions;
  type FindInPageOptions (line 19681) | type FindInPageOptions = Electron.FindInPageOptions;
  type FocusOptions (line 19682) | type FocusOptions = Electron.FocusOptions;
  type ForkOptions (line 19683) | type ForkOptions = Electron.ForkOptions;
  type FoundInPageEvent (line 19684) | type FoundInPageEvent = Electron.FoundInPageEvent;
  type FrameCreatedDetails (line 19685) | type FrameCreatedDetails = Electron.FrameCreatedDetails;
  type FromPartitionOptions (line 19686) | type FromPartitionOptions = Electron.FromPartitionOptions;
  type FromPathOptions (line 19687) | type FromPathOptions = Electron.FromPathOptions;
  type HandlerDetails (line 19688) | type HandlerDetails = Electron.HandlerDetails;
  type HeadersReceivedResponse (line 19689) | type HeadersReceivedResponse = Electron.HeadersReceivedResponse;
  type HeapStatistics (line 19690) | type HeapStatistics = Electron.HeapStatistics;
  type HidDeviceAddedDetails (line 19691) | type HidDeviceAddedDetails = Electron.HidDeviceAddedDetails;
  type HidDeviceRemovedDetails (line 19692) | type HidDeviceRemovedDetails = Electron.HidDeviceRemovedDetails;
  type HidDeviceRevokedDetails (line 19693) | type HidDeviceRevokedDetails = Electron.HidDeviceRevokedDetails;
  type IgnoreMouseEventsOptions (line 19694) | type IgnoreMouseEventsOptions = Electron.IgnoreMouseEventsOptions;
  type ImportCertificateOptions (line 19695) | type ImportCertificateOptions = Electron.ImportCertificateOptions;
  type Info (line 19696) | type Info = Electron.Info;
  type Input (line 19697) | type Input = Electron.Input;
  type InsertCSSOptions (line 19698) | type InsertCSSOptions = Electron.InsertCSSOptions;
  type IpcMessageEvent (line 19699) | type IpcMessageEvent = Electron.IpcMessageEvent;
  type Item (line 19700) | type Item = Electron.Item;
  type JumpListSettings (line 19701) | type JumpListSettings = Electron.JumpListSettings;
  type LoadCommitEvent (line 19702) | type LoadCommitEvent = Electron.LoadCommitEvent;
  type LoadExtensionOptions (line 19703) | type LoadExtensionOptions = Electron.LoadExtensionOptions;
  type LoadFileOptions (line 19704) | type LoadFileOptions = Electron.LoadFileOptions;
  type LoadURLOptions (line 19705) | type LoadURLOptions = Electron.LoadURLOptions;
  type LoginItemSettings (line 19706) | type LoginItemSettings = Electron.LoginItemSettings;
  type LoginItemSettingsOptions (line 19707) | type LoginItemSettingsOptions = Electron.LoginItemSettingsOptions;
  type MenuItemConstructorOptions (line 19708) | type MenuItemConstructorOptions = Electron.MenuItemConstructorOptions;
  type MessageBoxOptions (line 19709) | type MessageBoxOptions = Electron.MessageBoxOptions;
  type MessageBoxReturnValue (line 19710) | type MessageBoxReturnValue = Electron.MessageBoxReturnValue;
  type MessageBoxSyncOptions (line 19711) | type MessageBoxSyncOptions = Electron.MessageBoxSyncOptions;
  type MessageDetails (line 19712) | type MessageDetails = Electron.MessageDetails;
  type MessageEvent (line 19713) | type MessageEvent = Electron.MessageEvent;
  type MoveToApplicationsFolderOptions (line 19714) | type MoveToApplicationsFolderOptions = Electron.MoveToApplicationsFolder...
  type NotificationConstructorOptions (line 19715) | type NotificationConstructorOptions = Electron.NotificationConstructorOp...
  type OnBeforeRedirectListenerDetails (line 19716) | type OnBeforeRedirectListenerDetails = Electron.OnBeforeRedirectListener...
  type OnBeforeRequestListenerDetails (line 19717) | type OnBeforeRequestListenerDetails = Electron.OnBeforeRequestListenerDe...
  type OnBeforeSendHeadersListenerDetails (line 19718) | type OnBeforeSendHeadersListenerDetails = Electron.OnBeforeSendHeadersLi...
  type OnCompletedListenerDetails (line 19719) | type OnCompletedListenerDetails = Electron.OnCompletedListenerDetails;
  type OnErrorOccurredListenerDetails (line 19720) | type OnErrorOccurredListenerDetails = Electron.OnErrorOccurredListenerDe...
  type OnHeadersReceivedListenerDetails (line 19721) | type OnHeadersReceivedListenerDetails = Electron.OnHeadersReceivedListen...
  type OnResponseStartedListenerDetails (line 19722) | type OnResponseStartedListenerDetails = Electron.OnResponseStartedListen...
  type OnSendHeadersListenerDetails (line 19723) | type OnSendHeadersListenerDetails = Electron.OnSendHeadersListenerDetails;
  type OpenDevToolsOptions (line 19724) | type OpenDevToolsOptions = Electron.OpenDevToolsOptions;
  type OpenDialogOptions (line 19725) | type OpenDialogOptions = Electron.OpenDialogOptions;
  type OpenDialogReturnValue (line 19726) | type OpenDialogReturnValue = Electron.OpenDialogReturnValue;
  type OpenDialogSyncOptions (line 19727) | type OpenDialogSyncOptions = Electron.OpenDialogSyncOptions;
  type OpenExternalOptions (line 19728) | type OpenExternalOptions = Electron.OpenExternalOptions;
  type Options (line 19729) | type Options = Electron.Options;
  type Opts (line 19730) | type Opts = Electron.Opts;
  type PageFaviconUpdatedEvent (line 19731) | type PageFaviconUpdatedEvent = Electron.PageFaviconUpdatedEvent;
  type PageTitleUpdatedEvent (line 19732) | type PageTitleUpdatedEvent = Electron.PageTitleUpdatedEvent;
  type Parameters (line 19733) | type Parameters = Electron.Parameters;
  type Payment (line 19734) | type Payment = Electron.Payment;
  type PermissionCheckHandlerHandlerDetails (line 19735) | type PermissionCheckHandlerHandlerDetails = Electron.PermissionCheckHand...
  type PermissionRequestHandlerHandlerDetails (line 19736) | type PermissionRequestHandlerHandlerDetails = Electron.PermissionRequest...
  type PluginCrashedEvent (line 19737) | type PluginCrashedEvent = Electron.PluginCrashedEvent;
  type PopupOptions (line 19738) | type PopupOptions = Electron.PopupOptions;
  type PreconnectOptions (line 19739) | type PreconnectOptions = Electron.PreconnectOptions;
  type PrintToPDFOptions (line 19740) | type PrintToPDFOptions = Electron.PrintToPDFOptions;
  type Privileges (line 19741) | type Privileges = Electron.Privileges;
  type ProgressBarOptions (line 19742) | type ProgressBarOptions = Electron.ProgressBarOptions;
  type Provider (line 19743) | type Provider = Electron.Provider;
  type PurchaseProductOpts (line 19744) | type PurchaseProductOpts = Electron.PurchaseProductOpts;
  type ReadBookmark (line 19745) | type ReadBookmark = Electron.ReadBookmark;
  type RegistrationCompletedDetails (line 19746) | type RegistrationCompletedDetails = Electron.RegistrationCompletedDetails;
  type RelaunchOptions (line 19747) | type RelaunchOptions = Electron.RelaunchOptions;
  type RenderProcessGoneDetails (line 19748) | type RenderProcessGoneDetails = Electron.RenderProcessGoneDetails;
  type Request (line 19749) | type Request = Electron.Request;
  type ResizeOptions (line 19750) | type ResizeOptions = Electron.ResizeOptions;
  type ResolveHostOptions (line 19751) | type ResolveHostOptions = Electron.ResolveHostOptions;
  type ResourceUsage (line 19752) | type ResourceUsage = Electron.ResourceUsage;
  type Response (line 19753) | type Response = Electron.Response;
  type Result (line 19754) | type Result = Electron.Result;
  type SaveDialogOptions (line 19755) | type SaveDialogOptions = Electron.SaveDialogOptions;
  type SaveDialogReturnValue (line 19756) | type SaveDialogReturnValue = Electron.SaveDialogReturnValue;
  type SaveDialogSyncOptions (line 19757) | type SaveDialogSyncOptions = Electron.SaveDialogSyncOptions;
  type SelectHidDeviceDetails (line 19758) | type SelectHidDeviceDetails = Electron.SelectHidDeviceDetails;
  type SelectUsbDeviceDetails (line 19759) | type SelectUsbDeviceDetails = Electron.SelectUsbDeviceDetails;
  type SerialPortRevokedDetails (line 19760) | type SerialPortRevokedDetails = Electron.SerialPortRevokedDetails;
  type Settings (line 19761) | type Settings = Electron.Settings;
  type SourcesOptions (line 19762) | type SourcesOptions = Electron.SourcesOptions;
  type SSLConfigConfig (line 19763) | type SSLConfigConfig = Electron.SSLConfigConfig;
  type StartLoggingOptions (line 19764) | type StartLoggingOptions = Electron.StartLoggingOptions;
  type Streams (line 19765) | type Streams = Electron.Streams;
  type SystemMemoryInfo (line 19766) | type SystemMemoryInfo = Electron.SystemMemoryInfo;
  type TitleBarOverlayOptions (line 19767) | type TitleBarOverlayOptions = Electron.TitleBarOverlayOptions;
  type TitleOptions (line 19768) | type TitleOptions = Electron.TitleOptions;
  type ToBitmapOptions (line 19769) | type ToBitmapOptions = Electron.ToBitmapOptions;
  type ToDataURLOptions (line 19770) | type ToDataURLOptions = Electron.ToDataURLOptions;
  type ToPNGOptions (line 19771) | type ToPNGOptions = Electron.ToPNGOptions;
  type TouchBarButtonConstructorOptions (line 19772) | type TouchBarButtonConstructorOptions = Electron.TouchBarButtonConstruct...
  type TouchBarColorPickerConstructorOptions (line 19773) | type TouchBarColorPickerConstructorOptions = Electron.TouchBarColorPicke...
  type TouchBarConstructorOptions (line 19774) | type TouchBarConstructorOptions = Electron.TouchBarConstructorOptions;
  type TouchBarGroupConstructorOptions (line 19775) | type TouchBarGroupConstructorOptions = Electron.TouchBarGroupConstructor...
  type TouchBarLabelConstructorOptions (line 19776) | type TouchBarLabelConstructorOptions = Electron.TouchBarLabelConstructor...
  type TouchBarPopoverConstructorOptions (line 19777) | type TouchBarPopoverConstructorOptions = Electron.TouchBarPopoverConstru...
  type TouchBarScrubberConstructorOptions (line 19778) | type TouchBarScrubberConstructorOptions = Electron.TouchBarScrubberConst...
  type TouchBarSegmentedControlConstructorOptions (line 19779) | type TouchBarSegmentedControlConstructorOptions = Electron.TouchBarSegme...
  type TouchBarSliderConstructorOptions (line 19780) | type TouchBarSliderConstructorOptions = Electron.TouchBarSliderConstruct...
  type TouchBarSpacerConstructorOptions (line 19781) | type TouchBarSpacerConstructorOptions = Electron.TouchBarSpacerConstruct...
  type TraceBufferUsageReturnValue (line 19782) | type TraceBufferUsageReturnValue = Electron.TraceBufferUsageReturnValue;
  type UpdateTargetUrlEvent (line 19783) | type UpdateTargetUrlEvent = Electron.UpdateTargetUrlEvent;
  type UploadProgress (line 19784) | type UploadProgress = Electron.UploadProgress;
  type UsbDeviceRevokedDetails (line 19785) | type UsbDeviceRevokedDetails = Electron.UsbDeviceRevokedDetails;
  type USBProtectedClassesHandlerHandlerDetails (line 19786) | type USBProtectedClassesHandlerHandlerDetails = Electron.USBProtectedCla...
  type VisibleOnAllWorkspacesOptions (line 19787) | type VisibleOnAllWorkspacesOptions = Electron.VisibleOnAllWorkspacesOpti...
  type WebContentsAudioStateChangedEventParams (line 19788) | type WebContentsAudioStateChangedEventParams = Electron.WebContentsAudio...
  type WebContentsDidRedirectNavigationEventParams (line 19789) | type WebContentsDidRedirectNavigationEventParams = Electron.WebContentsD...
  type WebContentsDidStartNavigationEventParams (line 19790) | type WebContentsDidStartNavigationEventParams = Electron.WebContentsDidS...
  type WebContentsPrintOptions (line 19791) | type WebContentsPrintOptions = Electron.WebContentsPrintOptions;
  type WebContentsWillFrameNavigateEventParams (line 19792) | type WebContentsWillFrameNavigateEventParams = Electron.WebContentsWillF...
  type WebContentsWillNavigateEventParams (line 19793) | type WebContentsWillNavigateEventParams = Electron.WebContentsWillNaviga...
  type WebContentsWillRedirectEventParams (line 19794) | type WebContentsWillRedirectEventParams = Electron.WebContentsWillRedire...
  type WebviewTagPrintOptions (line 19795) | type WebviewTagPrintOptions = Electron.WebviewTagPrintOptions;
  type WillFrameNavigateEvent (line 19796) | type WillFrameNavigateEvent = Electron.WillFrameNavigateEvent;
  type WillNavigateEvent (line 19797) | type WillNavigateEvent = Electron.WillNavigateEvent;
  type WillResizeDetails (line 19798) | type WillResizeDetails = Electron.WillResizeDetails;
  type EditFlags (line 19799) | type EditFlags = Electron.EditFlags;
  type Env (line 19800) | type Env = Electron.Env;
  type FoundInPageResult (line 19801) | type FoundInPageResult = Electron.FoundInPageResult;
  type LaunchItems (line 19802) | type LaunchItems = Electron.LaunchItems;
  type Margins (line 19803) | type Margins = Electron.Margins;
  type MediaFlags (line 19804) | type MediaFlags = Electron.MediaFlags;
  type PageRanges (line 19805) | type PageRanges = Electron.PageRanges;
  type Params (line 19806) | type Params = Electron.Params;
  type TitleBarOverlay (line 19807) | type TitleBarOverlay = Electron.TitleBarOverlay;
  type Video (line 19808) | type Video = Electron.Video;
  type WebPreferences (line 19809) | type WebPreferences = Electron.WebPreferences;
  type DefaultFontFamily (line 19810) | type DefaultFontFamily = Electron.DefaultFontFamily;
  type BluetoothDevice (line 19811) | type BluetoothDevice = Electron.BluetoothDevice;
  type Certificate (line 19812) | type Certificate = Electron.Certificate;
  type CertificatePrincipal (line 19813) | type CertificatePrincipal = Electron.CertificatePrincipal;
  type Cookie (line 19814) | type Cookie = Electron.Cookie;
  type CPUUsage (line 19815) | type CPUUsage = Electron.CPUUsage;
  type CrashReport (line 19816) | type CrashReport = Electron.CrashReport;
  type CustomScheme (line 19817) | type CustomScheme = Electron.CustomScheme;
  type DesktopCapturerSource (line 19818) | type DesktopCapturerSource = Electron.DesktopCapturerSource;
  type Display (line 19819) | type Display = Electron.Display;
  type Extension (line 19820) | type Extension = Electron.Extension;
  type ExtensionInfo (line 19821) | type ExtensionInfo = Electron.ExtensionInfo;
  type FileFilter (line 19822) | type FileFilter = Electron.FileFilter;
  type FilePathWithHeaders (line 19823) | type FilePathWithHeaders = Electron.FilePathWithHeaders;
  type GPUFeatureStatus (line 19824) | type GPUFeatureStatus = Electron.GPUFeatureStatus;
  type HIDDevice (line 19825) | type HIDDevice = Electron.HIDDevice;
  type InputEvent (line 19826) | type InputEvent = Electron.InputEvent;
  type IOCounters (line 19827) | type IOCounters = Electron.IOCounters;
  type IpcMainEvent (line 19828) | type IpcMainEvent = Electron.IpcMainEvent;
  type IpcMainInvokeEvent (line 19829) | type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
  type IpcRendererEvent (line 19830) | type IpcRendererEvent = Electron.IpcRendererEvent;
  type JumpListCategory (line 19831) | type JumpListCategory = Electron.JumpListCategory;
  type JumpListItem (line 19832) | type JumpListItem = Electron.JumpListItem;
  type KeyboardEvent (line 19833) | type KeyboardEvent = Electron.KeyboardEvent;
  type KeyboardInputEvent (line 19834) | type KeyboardInputEvent = Electron.KeyboardInputEvent;
  type MemoryInfo (line 19835) | type MemoryInfo = Electron.MemoryInfo;
  type MemoryUsageDetails (line 19836) | type MemoryUsageDetails = Electron.MemoryUsageDetails;
  type MimeTypedBuffer (line 19837) | type MimeTypedBuffer = Electron.MimeTypedBuffer;
  type MouseInputEvent (line 19838) | type MouseInputEvent = Electron.MouseInputEvent;
  type MouseWheelInputEvent (line 19839) | type MouseWheelInputEvent = Electron.MouseWheelInputEvent;
  type NotificationAction (line 19840) | type NotificationAction = Electron.NotificationAction;
  type NotificationResponse (line 19841) | type NotificationResponse = Electron.NotificationResponse;
  type PaymentDiscount (line 19842) | type PaymentDiscount = Electron.PaymentDiscount;
  type Point (line 19843) | type Point = Electron.Point;
  type PostBody (line 19844) | type PostBody = Electron.PostBody;
  type PrinterInfo (line 19845) | type PrinterInfo = Electron.PrinterInfo;
  type ProcessMemoryInfo (line 19846) | type ProcessMemoryInfo = Electron.ProcessMemoryInfo;
  type ProcessMetric (line 19847) | type ProcessMetric = Electron.ProcessMetric;
  type Product (line 19848) | type Product = Electron.Product;
  type ProductDiscount (line 19849) | type ProductDiscount = Electron.ProductDiscount;
  type ProductSubscriptionPeriod (line 19850) | type ProductSubscriptionPeriod = Electron.ProductSubscriptionPeriod;
  type ProtocolRequest (line 19851) | type ProtocolRequest = Electron.ProtocolRequest;
  type ProtocolResponse (line 19852) | type ProtocolResponse = Electron.ProtocolResponse;
  type ProtocolResponseUploadData (line 19853) | type ProtocolResponseUploadData = Electron.ProtocolResponseUploadData;
  type Rectangle (line 19854) | type Rectangle = Electron.Rectangle;
  type Referrer (line 19855) | type Referrer = Electron.Referrer;
  type ResolvedEndpoint (line 19856) | type ResolvedEndpoint = Electron.ResolvedEndpoint;
  type ResolvedHost (line 19857) | type ResolvedHost = Electron.ResolvedHost;
  type ScrubberItem (line 19858) | type ScrubberItem = Electron.ScrubberItem;
  type SegmentedControlSegment (line 19859) | type SegmentedControlSegment = Electron.SegmentedControlSegment;
  type SerialPort (line 19860) | type SerialPort = Electron.SerialPort;
  type ServiceWorkerInfo (line 19861) | type ServiceWorkerInfo = Electron.ServiceWorkerInfo;
  type SharedWorkerInfo (line 19862) | type SharedWorkerInfo = Electron.SharedWorkerInfo;
  type SharingItem (line 19863) | type SharingItem = Electron.SharingItem;
  type ShortcutDetails (line 19864) | type ShortcutDetails = Electron.ShortcutDetails;
  type Size (line 19865) | type Size = Electron.Size;
  type Task (line 19866) | type Task = Electron.Task;
  type ThumbarButton (line 19867) | type ThumbarButton = Electron.ThumbarButton;
  type TraceCategoriesAndOptions (line 19868) | type TraceCategoriesAndOptions = Electron.TraceCategoriesAndOptions;
  type TraceConfig (line 19869) | type TraceConfig = Electron.TraceConfig;
  type Transaction (line 19870) | type Transaction = Electron.Transaction;
  type UploadData (line 19871) | type UploadData = Electron.UploadData;
  type UploadFile (line 19872) | type UploadFile = Electron.UploadFile;
  type UploadRawData (line 19873) | type UploadRawData = Electron.UploadRawData;
  type USBDevice (line 19874) | type USBDevice = Electron.USBDevice;
  type UserDefaultTypes (line 19875) | type UserDefaultTypes = Electron.UserDefaultTypes;
  type WebRequestFilter (line 19876) | type WebRequestFilter = Electron.WebRequestFilter;
  type WebSource (line 19877) | type WebSource = Electron.WebSource;
  type Event (line 19881) | type Event<Params extends object = {}> = Electron.Event<Params>;
  type App (line 19883) | type App = Electron.App;
  type AutoUpdater (line 19885) | type AutoUpdater = Electron.AutoUpdater;
  class BrowserView (line 19886) | class BrowserView extends Electron.BrowserView {}
  class BrowserWindow (line 19887) | class BrowserWindow extends Electron.BrowserWindow {}
  type ClientRequest (line 19888) | type ClientRequest = Electron.ClientRequest;
  type Clipboard (line 19890) | type Clipboard = Electron.Clipboard;
  type CommandLine (line 19891) | type CommandLine = Electron.CommandLine;
  type ContentTracing (line 19893) | type ContentTracing = Electron.ContentTracing;
  type ContextBridge (line 19895) | type ContextBridge = Electron.ContextBridge;
  type Cookies (line 19896) | type Cookies = Electron.Cookies;
  type CrashReporter (line 19898) | type CrashReporter = Electron.CrashReporter;
  type Debugger (line 19899) | type Debugger = Electron.Debugger;
  type DesktopCapturer (line 19901) | type DesktopCapturer = Electron.DesktopCapturer;
  type Dialog (line 19903) | type Dialog = Electron.Dialog;
  type Dock (line 19904) | type Dock = Electron.Dock;
  type DownloadItem (line 19905) | type DownloadItem = Electron.DownloadItem;
  type GlobalShortcut (line 19907) | type GlobalShortcut = Electron.GlobalShortcut;
  type InAppPurchase (line 19909) | type InAppPurchase = Electron.InAppPurchase;
  type IncomingMessage (line 19910) | type IncomingMessage = Electron.IncomingMessage;
  type IpcMain (line 19912) | type IpcMain = Electron.IpcMain;
  type IpcRenderer (line 19914) | type IpcRenderer = Electron.IpcRenderer;
  class Menu (line 19915) | class Menu extends Electron.Menu {}
  class MenuItem (line 19916) | class MenuItem extends Electron.MenuItem {}
  class MessageChannelMain (line 19917) | class MessageChannelMain extends Electron.MessageChannelMain {}
  type MessagePortMain (line 19918) | type MessagePortMain = Electron.MessagePortMain;
  type NativeImage (line 19920) | type NativeImage = Electron.NativeImage;
  type NativeTheme (line 19922) | type NativeTheme = Electron.NativeTheme;
  type Net (line 19924) | type Net = Electron.Net;
  type NetLog (line 19926) | type NetLog = Electron.NetLog;
  class Notification (line 19927) | class Notification extends Electron.Notification {}
  type PowerMonitor (line 19929) | type PowerMonitor = Electron.PowerMonitor;
  type PowerSaveBlocker (line 19931) | type PowerSaveBlocker = Electron.PowerSaveBlocker;
  type Protocol (line 19933) | type Protocol = Electron.Protocol;
  type PushNotifications (line 19935) | type PushNotifications = Electron.PushNotifications;
  type SafeStorage (line 19937) | type SafeStorage = Electron.SafeStorage;
  type Screen (line 19939) | type Screen = Electron.Screen;
  type ServiceWorkers (line 19940) | type ServiceWorkers = Electron.ServiceWorkers;
  type Session (line 19942) | type Session = Electron.Session;
  class ShareMenu (line 19943) | class ShareMenu extends Electron.ShareMenu {}
  type Shell (line 19945) | type Shell = Electron.Shell;
  type SystemPreferences (line 19947) | type SystemPreferences = Electron.SystemPreferences;
  class TouchBar (line 19948) | class TouchBar extends Electron.TouchBar {}
  type TouchBarButton (line 19949) | type TouchBarButton = Electron.TouchBarButton;
  type TouchBarColorPicker (line 19950) | type TouchBarColorPicker = Electron.TouchBarColorPicker;
  type TouchBarGroup (line 19951) | type TouchBarGroup = Electron.TouchBarGroup;
  type TouchBarLabel (line 19952) | type TouchBarLabel = Electron.TouchBarLabel;
  type TouchBarOtherItemsProxy (line 19953) | type TouchBarOtherItemsProxy = Electron.TouchBarOtherItemsProxy;
  type TouchBarPopover (line 19954) | type TouchBarPopover = Electron.TouchBarPopover;
  type TouchBarScrubber (line 19955) | type TouchBarScrubber = Electron.TouchBarScrubber;
  type TouchBarSegmentedControl (line 19956) | type TouchBarSegmentedControl = Electron.TouchBarSegmentedControl;
  type TouchBarSlider (line 19957) | type TouchBarSlider = Electron.TouchBarSlider;
  type TouchBarSpacer (line 19958) | type TouchBarSpacer = Electron.TouchBarSpacer;
  class Tray (line 19959) | class Tray extends Electron.Tray {}
  type UtilityProcess (line 19961) | type UtilityProcess = Electron.UtilityProcess;
  type WebContents (line 19963) | type WebContents = Electron.WebContents;
  type WebFrame (line 19965) | type WebFrame = Electron.WebFrame;
  type WebFrameMain (line 19967) | type WebFrameMain = Electron.WebFrameMain;
  type WebRequest (line 19968) | type WebRequest = Electron.WebRequest;
  type WebviewTag (line 19969) | type WebviewTag = Electron.WebviewTag;
  type AboutPanelOptionsOptions (line 19970) | type AboutPanelOptionsOptions = Electron.AboutPanelOptionsOptions;
  type AddRepresentationOptions (line 19971) | type AddRepresentationOptions = Electron.AddRepresentationOptions;
  type AdjustSelectionOptions (line 19972) | type AdjustSelectionOptions = Electron.AdjustSelectionOptions;
  type AnimationSettings (line 19973) | type AnimationSettings = Electron.AnimationSettings;
  type AppDetailsOptions (line 19974) | type AppDetailsOptions = Electron.AppDetailsOptions;
  type ApplicationInfoForProtocolReturnValue (line 19975) | type ApplicationInfoForProtocolReturnValue = Electron.ApplicationInfoFor...
  type AuthenticationResponseDetails (line 19976) | type AuthenticationResponseDetails = Electron.AuthenticationResponseDeta...
  type AuthInfo (line 19977) | type AuthInfo = Electron.AuthInfo;
  type AutoResizeOptions (line 19978) | type AutoResizeOptions = Electron.AutoResizeOptions;
  type BeforeSendResponse (line 19979) | type BeforeSendResponse = Electron.BeforeSendResponse;
  type BitmapOptions (line 19980) | type BitmapOptions = Electron.BitmapOptions;
  type BlinkMemoryInfo (line 19981) | type BlinkMemoryInfo = Electron.BlinkMemoryInfo;
  type BluetoothPairingHandlerHandlerDetails (line 19982) | type BluetoothPairingHandlerHandlerDetails = Electron.BluetoothPairingHa...
  type BrowserViewConstructorOptions (line 19983) | type BrowserViewConstructorOptions = Electron.BrowserViewConstructorOpti...
  type BrowserWindowConstructorOptions (line 19984) | type BrowserWindowConstructorOptions = Electron.BrowserWindowConstructor...
  type CallbackResponse (line 19985) | type CallbackResponse = Electron.CallbackResponse;
  type CertificateTrustDialogOptions (line 19986) | type CertificateTrustDialogOptions = Electron.CertificateTrustDialogOpti...
  type ClearCodeCachesOptions (line 19987) | type ClearCodeCachesOptions = Electron.ClearCodeCachesOptions;
  type ClearStorageDataOptions (line 19988) | type ClearStorageDataOptions = Electron.ClearStorageDataOptions;
  type ClientRequestConstructorOptions (line 19989) | type ClientRequestConstructorOptions = Electron.ClientRequestConstructor...
  type CloseOpts (line 19990) | type CloseOpts = Electron.CloseOpts;
  type Config (line 19991) | type Config = Electron.Config;
  type ConfigureHostResolverOptions (line 19992) | type ConfigureHostResolverOptions = Electron.ConfigureHostResolverOptions;
  type ConsoleMessageEvent (line 19993) | type ConsoleMessageEvent = Electron.ConsoleMessageEvent;
  type ContextMenuEvent (line 19994) | type ContextMenuEvent = Electron.ContextMenuEvent;
  type ContextMenuParams (line 19995) | type ContextMenuParams = Electron.ContextMenuParams;
  type ContinueActivityDetails (line 19996) | type ContinueActivityDetails = Electron.ContinueActivityDetails;
  type CookiesGetFilter (line 19997) | type CookiesGetFilter = Electron.CookiesGetFilter;
  type CookiesSetDetails (line 19998) | type CookiesSetDetails = Electron.CookiesSetDetails;
  type CrashReporterStartOptions (line 19999) | type CrashReporterStartOptions = Electron.CrashReporterStartOptions;
  type CreateFromBitmapOptions (line 20000) | type CreateFromBitmapOptions = Electron.CreateFromBitmapOptions;
  type CreateFromBufferOptions (line 20001) | type CreateFromBufferOptions = Electron.CreateFromBufferOptions;
  type CreateInterruptedDownloadOptions (line 20002) | type CreateInterruptedDownloadOptions = Electron.CreateInterruptedDownlo...
  type Data (line 20003) | type Data = Electron.Data;
  type Details (line 20004) | type Details = Electron.Details;
  type DevicePermissionHandlerHandlerDetails (line 20005) | type DevicePermissionHandlerHandlerDetails = Electron.DevicePermissionHa...
  type DevtoolsOpenUrlEvent (line 20006) | type DevtoolsOpenUrlEvent = Electron.DevtoolsOpenUrlEvent;
  type DidChangeThemeColorEvent (line 20007) | type DidChangeThemeColorEvent = Electron.DidChangeThemeColorEvent;
  type DidCreateWindowDetails (line 20008) | type DidCreateWindowDetails = Electron.DidCreateWindowDetails;
  type DidFailLoadEvent (line 20009) | type DidFailLoadEvent = Electron.DidFailLoadEvent;
  type DidFrameFinishLoadEvent (line 20010) | type DidFrameFinishLoadEvent = Electron.DidFrameFinishLoadEvent;
  type DidFrameNavigateEvent (line 20011) | type DidFrameNavigateEvent = Electron.DidFrameNavigateEvent;
  type DidNavigateEvent (line 20012) | type DidNavigateEvent = Electron.DidNavigateEvent;
  type DidNavigateInPageEvent (line 20013) | type DidNavigateInPageEvent = Electron.DidNavigateInPageEvent;
  type DidRedirectNavigationEvent (line 20014) | type DidRedirectNavigationEvent = Electron.DidRedirectNavigationEvent;
  type DidStartNavigationEvent (line 20015) | type DidStartNavigationEvent = Electron.DidStartNavigationEvent;
  type DisplayBalloonOptions (line 20016) | type DisplayBalloonOptions = Electron.DisplayBalloonOptions;
  type DisplayMediaRequestHandlerHandlerRequest (line 20017) | type DisplayMediaRequestHandlerHandlerRequest = Electron.DisplayMediaReq...
  type EnableNetworkEmulationOptions (line 20018) | type EnableNetworkEmulationOptions = Electron.EnableNetworkEmulationOpti...
  type FeedURLOptions (line 20019) | type FeedURLOptions = Electron.FeedURLOptions;
  type FileIconOptions (line 20020) | type FileIconOptions = Electron.FileIconOptions;
  type FindInPageOptions (line 20021) | type FindInPageOptions = Electron.FindInPageOptions;
  type FocusOptions (line 20022) | type FocusOptions = Electron.FocusOptions;
  type ForkOptions (line 20023) | type ForkOptions = Electron.ForkOptions;
  type FoundInPageEvent (line 20024) | type FoundInPageEvent = Electron.FoundInPageEvent;
  type FrameCreatedDetails (line 20025) | type FrameCreatedDetails = Electron.FrameCreatedDetails;
  type FromPartitionOptions (line 20026) | type FromPartitionOptions = Electron.FromPartitionOptions;
  type FromPathOptions (line 20027) | type FromPathOptions = Electron.FromPathOptions;
  type HandlerDetails (line 20028) | type HandlerDetails = Electron.HandlerDetails;
  type HeadersReceivedResponse (line 20029) | type HeadersReceivedResponse = Electron.HeadersReceivedResponse;
  type HeapStatistics (line 20030) | type HeapStatistics = Electron.HeapStatistics;
  type HidDeviceAddedDetails (line 20031) | type HidDeviceAddedDetails = Electron.HidDeviceAddedDetails;
  type HidDeviceRemovedDetails (line 20032) | type HidDeviceRemovedDetails = Electron.HidDeviceRemovedDetails;
  type HidDeviceRevokedDetails (line 20033) | type HidDeviceRevokedDetails = Electron.HidDeviceRevokedDetails;
  type IgnoreMouseEventsOptions (line 20034) | type IgnoreMouseEventsOptions = Electron.IgnoreMouseEventsOptions;
  type ImportCertificateOptions (line 20035) | type ImportCertificateOptions = Electron.ImportCertificateOptions;
  type Info (line 20036) | type Info = Electron.Info;
  type Input (line 20037) | type Input = Electron.Input;
  type InsertCSSOptions (line 20038) | type InsertCSSOptions = Electron.InsertCSSOptions;
  type IpcMessageEvent (line 20039) | type IpcMessageEvent = Electron.IpcMessageEvent;
  type Item (line 20040) | type Item = Electron.Item;
  type JumpListSettings (line 20041) | type JumpListSettings = Electron.JumpListSettings;
  type LoadCommitEvent (line 20042) | type LoadCommitEvent = Electron.LoadCommitEvent;
  type LoadExtensionOptions (line 20043) | type LoadExtensionOptions = Electron.LoadExtensionOptions;
  type LoadFileOptions (line 20044) | type LoadFileOptions = Electron.LoadFileOptions;
  type LoadURLOptions (line 20045) | type LoadURLOptions = Electron.LoadURLOptions;
  type LoginItemSettings (line 20046) | type LoginItemSettings = Electron.LoginItemSettings;
  type LoginItemSettingsOptions (line 20047) | type LoginItemSettingsOptions = Electron.LoginItemSettingsOptions;
  type MenuItemConstructorOptions (line 20048) | type MenuItemConstructorOptions = Electron.MenuItemConstructorOptions;
  type MessageBoxOptions (line 20049) | type MessageBoxOptions = Electron.MessageBoxOptions;
  type MessageBoxReturnValue (line 20050) | type MessageBoxReturnValue = Electron.MessageBoxReturnValue;
  type MessageBoxSyncOptions (line 20051) | type MessageBoxSyncOptions = Electron.MessageBoxSyncOptions;
  type MessageDetails (line 20052) | type MessageDetails = Electron.MessageDetails;
  type MessageEvent (line 20053) | type MessageEvent = Electron.MessageEvent;
  type MoveToApplicationsFolderOptions (line 20054) | type MoveToApplicationsFolderOptions = Electron.MoveToApplicationsFolder...
  type NotificationConstructorOptions (line 20055) | type NotificationConstructorOptions = Electron.NotificationConstructorOp...
  type OnBeforeRedirectListenerDetails (line 20056) | type OnBeforeRedirectListenerDetails = Electron.OnBeforeRedirectListener...
  type OnBeforeRequestListenerDetails (line 20057) | type OnBeforeRequestListenerDetails = Electron.OnBeforeRequestListenerDe...
  type OnBeforeSendHeadersListenerDetails (line 20058) | type OnBeforeSendHeadersListenerDetails = Electron.OnBeforeSendHeadersLi...
  type OnCompletedListenerDetails (line 20059) | type OnCompletedListenerDetails = Electron.OnCompletedListenerDetails;
  type OnErrorOccurredListenerDetails (line 20060) | type OnErrorOccurredListenerDetails = Electron.OnErrorOccurredListenerDe...
  type OnHeadersReceivedListenerDetails (line 20061) | type OnHeadersReceivedListenerDetails = Electron.OnHeadersReceivedListen...
  type OnResponseStartedListenerDetails (line 20062) | type OnResponseStartedListenerDetails = Electron.OnResponseStartedListen...
  type OnSendHeadersListenerDetails (line 20063) | type OnSendHeadersListenerDetails = Electron.OnSendHeadersListenerDetails;
  type OpenDevToolsOptions (line 20064) | type OpenDevToolsOptions = Electron.OpenDevToolsOptions;
  type OpenDialogOptions (line 20065) | type OpenDialogOptions = Electron.OpenDialogOptions;
  type OpenDialogReturnValue (line 20066) | type OpenDialogReturnValue = Electron.OpenDialogReturnValue;
  type OpenDialogSyncOptions (line 20067) | type OpenDialogSyncOptions = Electron.OpenDialogSyncOptions;
  type OpenExternalOptions (line 20068) | type OpenExternalOptions = Electron.OpenExternalOptions;
  type Options (line 20069) | type Options = Electron.Options;
  type Opts (line 20070) | type Opts = Electron.Opts;
  type PageFaviconUpdatedEvent (line 20071) | type PageFaviconUpdatedEvent = Electron.PageFaviconUpdatedEvent;
  type PageTitleUpdatedEvent (line 20072) | type PageTitleUpdatedEvent = Electron.PageTitleUpdatedEvent;
  type Parameters (line 20073) | type Parameters = Electron.Parameters;
  type Payment (line 20074) | type Payment = Electron.Payment;
  type PermissionCheckHandlerHandlerDetails (line 20075) | type PermissionCheckHandlerHandlerDetails = Electron.PermissionCheckHand...
  type PermissionRequestHandlerHandlerDetails (line 20076) | type PermissionRequestHandlerHandlerDetails = Electron.PermissionRequest...
  type PluginCrashedEvent (line 20077) | type PluginCrashedEvent = Electron.PluginCrashedEvent;
  type PopupOptions (line 20078) | type PopupOptions = Electron.PopupOptions;
  type PreconnectOptions (line 20079) | type PreconnectOptions = Electron.PreconnectOptions;
  type PrintToPDFOptions (line 20080) | type PrintToPDFOptions = Electron.PrintToPDFOptions;
  type Privileges (line 20081) | type Privileges = Electron.Privileges;
  type ProgressBarOptions (line 20082) | type ProgressBarOptions = Electron.ProgressBarOptions;
  type Provider (line 20083) | type Provider = Electron.Provider;
  type PurchaseProductOpts (line 20084) | type PurchaseProductOpts = Electron.PurchaseProductOpts;
  type ReadBookmark (line 20085) | type ReadBookmark = Electron.ReadBookmark;
  type RegistrationCompletedDetails (line 20086) | type RegistrationCompletedDetails = Electron.RegistrationCompletedDetails;
  type RelaunchOptions (line 20087) | type RelaunchOptions = Electron.RelaunchOptions;
  type RenderProcessGoneDetails (line 20088) | type RenderProcessGoneDetails = Electron.RenderProcessGoneDetails;
  type Request (line 20089) | type Request = Electron.Request;
  type ResizeOptions (line 20090) | type ResizeOptions = Electron.ResizeOptions;
  type ResolveHostOptions (line 20091) | type ResolveHostOptions = Electron.ResolveHostOptions;
  type ResourceUsage (line 20092) | type ResourceUsage = Electron.ResourceUsage;
  type Response (line 20093) | type Response = Electron.Response;
  type Result (line 20094) | type Result = Electron.Result;
  type SaveDialogOptions (line 20095) | type SaveDialogOptions = Electron.SaveDialogOptions;
  type SaveDialogReturnValue (line 20096) | type SaveDialogReturnValue = Electron.SaveDialogReturnValue;
  type SaveDialogSyncOptions (line 20097) | type SaveDialogSyncOptions = Electron.SaveDialogSyncOptions;
  type SelectHidDeviceDetails (line 20098) | type SelectHidDeviceDetails = Electron.SelectHidDeviceDetails;
  type SelectUsbDeviceDetails (line 20099) | type SelectUsbDeviceDetails = Electron.SelectUsbDeviceDetails;
  type SerialPortRevokedDetails (line 20100) | type SerialPortRevokedDetails = Electron.SerialPortRevokedDetails;
  type Settings (line 20101) | type Settings = Electron.Settings;
  type SourcesOptions (line 20102) | type SourcesOptions = Electron.SourcesOptions;
  type SSLConfigConfig (line 20103) | type SSLConfigConfig = Electron.SSLConfigConfig;
  type StartLoggingOptions (line 20104) | type StartLoggingOptions = Electron.StartLoggingOptions;
  type Streams (line 20105) | type Streams = Electron.Streams;
  type SystemMemoryInfo (line 20106) | type SystemMemoryInfo = Electron.SystemMemoryInfo;
  type TitleBarOverlayOptions (line 20107) | type TitleBarOverlayOptions = Electron.TitleBarOverlayOptions;
  type TitleOptions (line 20108) | type TitleOptions = Electron.TitleOptions;
  type ToBitmapOptions (line 20109) | type ToBitmapOptions = Electron.ToBitmapOptions;
  type ToDataURLOptions (line 20110) | type ToDataURLOptions = Electron.ToDataURLOptions;
  type ToPNGOptions (line 20111) | type ToPNGOptions = Electron.ToPNGOptions;
  type TouchBarButtonConstructorOptions (line 20112) | type TouchBarButtonConstructorOptions = Electron.TouchBarButtonConstruct...
  type TouchBarColorPickerConstructorOptions (line 20113) | type TouchBarColorPickerConstructorOptions = Electron.TouchBarColorPicke...
  type TouchBarConstructorOptions (line 20114) | type TouchBarConstructorOptions = Electron.TouchBarConstructorOptions;
  type TouchBarGroupConstructorOptions (line 20115) | type TouchBarGroupConstructorOptions = Electron.TouchBarGroupConstructor...
  type TouchBarLabelConstructorOptions (line 20116) | type TouchBarLabelConstructorOptions = Electron.TouchBarLabelConstructor...
  type TouchBarPopoverConstructorOptions (line 20117) | type TouchBarPopoverConstructorOptions = Electron.TouchBarPopoverConstru...
  type TouchBarScrubberConstructorOptions (line 20118) | type TouchBarScrubberConstructorOptions = Electron.TouchBarScrubberConst...
  type TouchBarSegmentedControlConstructorOptions (line 20119) | type TouchBarSegmentedControlConstructorOptions = Electron.TouchBarSegme...
  type TouchBarSliderConstructorOptions (line 20120) | type TouchBarSliderConstructorOptions = Electron.TouchBarSliderConstruct...
  type TouchBarSpacerConstructorOptions (line 20121) | type TouchBarSpacerConstructorOptions = Electron.TouchBarSpacerConstruct...
  type TraceBufferUsageReturnValue (line 20122) | type TraceBufferUsageReturnValue = Electron.TraceBufferUsageReturnValue;
  type UpdateTargetUrlEvent (line 20123) | type UpdateTargetUrlEvent = Electron.UpdateTargetUrlEvent;
  type UploadProgress (line 20124) | type UploadProgress = Electron.UploadProgress;
  type UsbDeviceRevokedDetails (line 20125) | type UsbDeviceRevokedDetails = Electron.UsbDeviceRevokedDetails;
  type USBProtectedClassesHandlerHandlerDetails (line 20126) | type USBProtectedClassesHandlerHandlerDetails = Electron.USBProtectedCla...
  type VisibleOnAllWorkspacesOptions (line 20127) | type VisibleOnAllWorkspacesOptions = Electron.VisibleOnAllWorkspacesOpti...
  type WebContentsAudioStateChangedEventParams (line 20128) | type WebContentsAudioStateChangedEventParams = Electron.WebContentsAudio...
  type WebContentsDidRedirectNavigationEventParams (line 20129) | type WebContentsDidRedirectNavigationEventParams = Electron.WebContentsD...
  type WebContentsDidStartNavigationEventParams (line 20130) | type WebContentsDidStartNavigationEventParams = Electron.WebContentsDidS...
  type WebContentsPrintOptions (line 20131) | type WebContentsPrintOptions = Electron.WebContentsPrintOptions;
  type WebContentsWillFrameNavigateEventParams (line 20132) | type WebContentsWillFrameNavigateEventParams = Electron.WebContentsWillF...
  type WebContentsWillNavigateEventParams (line 20133) | type WebContentsWillNavigateEventParams = Electron.WebContentsWillNaviga...
  type WebContentsWillRedirectEventParams (line 20134) | type WebContentsWillRedirectEventParams = Electron.WebContentsWillRedire...
  type WebviewTagPrintOptions (line 20135) | type WebviewTagPrintOptions = Electron.WebviewTagPrintOptions;
  type WillFrameNavigateEvent (line 20136) | type WillFrameNavigateEvent = Electron.WillFrameNavigateEvent;
  type WillNavigateEvent (line 20137) | type WillNavigateEvent = Electron.WillNavigateEvent;
  type WillResizeDetails (line 20138) | type WillResizeDetails = Electron.WillResizeDetails;
  type EditFlags (line 20139) | type EditFlags = Electron.EditFlags;
  type Env (line 20140) | type Env = Electron.Env;
  type FoundInPageResult (line 20141) | type FoundInPageResult = Electron.FoundInPageResult;
  type LaunchItems (line 20142) | type LaunchItems = Electron.LaunchItems;
  type Margins (line 20143) | type Margins = Electron.Margins;
  type MediaFlags (line 20144) | type MediaFlags = Electron.MediaFlags;
  type PageRanges (line 20145) | type PageRanges = Electron.PageRanges;
  type Params (line 20146) | type Params = Electron.Params;
  type TitleBarOverlay (line 20147) | type TitleBarOverlay = Electron.TitleBarOverlay;
  type Video (line 20148) | type Video = Electron.Video;
  type WebPreferences (line 20149) | type WebPreferences = Electron.WebPreferences;
  type DefaultFontFamily (line 20150) | type DefaultFontFamily = Electron.DefaultFontFamily;
  type BluetoothDevice (line 20151) | type BluetoothDevice = Electron.BluetoothDevice;
  type Certificate (line 20152) | type Certificate = Electron.Certificate;
  type CertificatePrincipal (line 20153) | type CertificatePrincipal = Electron.CertificatePrincipal;
  type Cookie (line 20154) | type Cookie = Electron.Cookie;
  type CPUUsage (line 20155) | type CPUUsage = Electron.CPUUsage;
  type CrashReport (line 20156) | type CrashReport = Electron.CrashReport;
  type CustomScheme (line 20157) | type CustomScheme = Electron.CustomScheme;
  type DesktopCapturerSource (line 20158) | type DesktopCapturerSource = Electron.DesktopCapturerSource;
  type Display (line 20159) | type Display = Electron.Display;
  type Extension (line 20160) | type Extension = Electron.Extension;
  type ExtensionInfo (line 20161) | type ExtensionInfo = Electron.ExtensionInfo;
  type FileFilter (line 20162) | type FileFilter = Electron.FileFilter;
  type FilePathWithHeaders (line 20163) | type FilePathWithHeaders = Electron.FilePathWithHeaders;
  type GPUFeatureStatus (line 20164) | type GPUFeatureStatus = Electron.GPUFeatureStatus;
  type HIDDevice (line 20165) | type HIDDevice = Electron.HIDDevice;
  type InputEvent (line 20166) | type InputEvent = Electron.InputEvent;
  type IOCounters (line 20167) | type IOCounters = Electron.IOCounters;
  type IpcMainEvent (line 20168) | type IpcMainEvent = Electron.IpcMainEvent;
  type IpcMainInvokeEvent (line 20169) | type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
  type IpcRendererEvent (line 20170) | type IpcRendererEvent = Electron.IpcRendererEvent;
  type JumpListCategory (line 20171) | type JumpListCategory = Electron.JumpListCategory;
  type JumpListItem (line 20172) | type JumpListItem = Electron.JumpListItem;
  type KeyboardEvent (line 20173) | type KeyboardEvent = Electron.KeyboardEvent;
  type KeyboardInputEvent (line 20174) | type KeyboardInputEvent = Electron.KeyboardInputEvent;
  type MemoryInfo (line 20175) | type MemoryInfo = Electron.MemoryInfo;
  type MemoryUsageDetails (line 20176) | type MemoryUsageDetails = Electron.MemoryUsageDetails;
  type MimeTypedBuffer (line 20177) | type MimeTypedBuffer = Electron.MimeTypedBuffer;
  type MouseInputEvent (line 20178) | type MouseInputEvent = Electron.MouseInputEvent;
  type MouseWheelInputEvent (line 20179) | type MouseWheelInputEvent = Electron.MouseWheelInputEvent;
  type NotificationAction (line 20180) | type NotificationAction = Electron.NotificationAction;
  type NotificationResponse (line 20181) | type NotificationResponse = Electron.NotificationResponse;
  type PaymentDiscount (line 20182) | type PaymentDiscount = Electron.PaymentDiscount;
  type Point (line 20183) | type Point = Electron.Point;
  type PostBody (line 20184) | type PostBody = Electron.PostBody;
  type PrinterInfo (line 20185) | type PrinterInfo = Electron.PrinterInfo;
  type ProcessMemoryInfo (line 20186) | type ProcessMemoryInfo = Electron.ProcessMemoryInfo;
  type ProcessMetric (line 20187) | type ProcessMetric = Electron.ProcessMetric;
  type Product (line 20188) | type Product = Electron.Product;
  type ProductDiscount (line 20189) | type ProductDiscount = Electron.ProductDiscount;
  type ProductSubscriptionPeriod (line 20190) | type ProductSubscriptionPeriod = Electron.ProductSubscriptionPeriod;
  type ProtocolRequest (line 20191) | type ProtocolRequest = Electron.ProtocolRequest;
  type ProtocolResponse (line 20192) | type ProtocolResponse = Electron.ProtocolResponse;
  type ProtocolResponseUploadData (line 20193) | type ProtocolResponseUploadData = Electron.ProtocolResponseUploadData;
  type Rectangle (line 20194) | type Rectangle = Electron.Rectangle;
  type Referrer (line 20195) | type Referrer = Electron.Referrer;
  type ResolvedEndpoint (line 20196) | type ResolvedEndpoint = Electron.ResolvedEndpoint;
  type ResolvedHost (line 20197) | type ResolvedHost = Electron.ResolvedHost;
  type ScrubberItem (line 20198) | type ScrubberItem = Electron.ScrubberItem;
  type SegmentedControlSegment (line 20199) | type SegmentedControlSegment = Electron.SegmentedControlSegment;
  type SerialPort (line 20200) | type SerialPort = Electron.SerialPort;
  type ServiceWorkerInfo (line 20201) | type ServiceWorkerInfo = Electron.ServiceWorkerInfo;
  type SharedWorkerInfo (line 20202) | type SharedWorkerInfo = Electron.SharedWorkerInfo;
  type SharingItem (line 20203) | type SharingItem = Electron.SharingItem;
  type ShortcutDetails (line 20204) | type ShortcutDetails = Electron.ShortcutDetails;
  type Size (line 20205) | type Size = Electron.Size;
  type Task (line 20206) | type Task = Electron.Task;
  type ThumbarButton (line 20207) | type ThumbarButton = Electron.ThumbarButton;
  type TraceCategoriesAndOptions (line 20208) | type TraceCategoriesAndOptions = Electron.TraceCategoriesAndOptions;
  type TraceConfig (line 20209) | type TraceConfig = Electron.TraceConfig;
  type Transaction (line 20210) | type Transaction = Electron.Transaction;
  type UploadData (line 20211) | type UploadData = Electron.UploadData;
  type UploadFile (line 20212) | type UploadFile = Electron.UploadFile;
  type UploadRawData (line 20213) | type UploadRawData = Electron.UploadRawData;
  type USBDevice (line 20214) | type USBDevice = Electron.USBDevice;
  type UserDefaultTypes (line 20215) | type UserDefaultTypes = Electron.UserDefaultTypes;
  type WebRequestFilter (line 20216) | type WebRequestFilter = Electron.WebRequestFilter;
  type WebSource (line 20217) | type WebSource = Electron.WebSource;
  type NodeRequireFunction (line 20268) | interface NodeRequireFunction {
  type NodeRequire (line 20275) | interface NodeRequire {
  type File (line 20282) | interface File {
  type Document (line 20294) | interface Document {
  type Process (line 20299) | interface Process extends NodeJS.EventEmitter {
  type ProcessVersions (line 20516) | interface ProcessVersions {

FILE: src/typings/index.d.ts
  type Direction (line 23) | type Direction = "in" | "out";
  type Type (line 24) | type Type = "request" | "response";
  type Response (line 25) | type Response = { errMsg: string; result: number };
  type Request (line 26) | type Request = any[];
  type Args (line 27) | type Args<T> = [{ type: string; eventName: string; callbackId: string },...
  type InterruptIPCOptions (line 28) | interface InterruptIPCOptions {
  type InterruptFunction (line 46) | type InterruptFunction = (args: Args<any>, channel: string, sender?: Ele...
  type InterruptArgsFunction (line 50) | type InterruptArgsFunction = (args: Electron.BrowserWindowConstructorOpt...
  type InterruptFunction (line 51) | type InterruptFunction = (window: Electron.BrowserWindow) => void;
  type Configuration (line 54) | interface Configuration {
  type Environment (line 90) | interface Environment {
  class Main (line 113) | class Main {
  class Renderer (line 119) | class Renderer {
  type Plugin (line 131) | interface Plugin {
  type InjectionMain (line 162) | interface InjectionMain {
  type InjectionRenderer (line 166) | interface InjectionRenderer {
  type Injection (line 173) | type Injection = InjectionMain | InjectionRenderer;
  type AllUsersPlugins (line 174) | type AllUsersPlugins = Record<string, UserPlugins>;
  type UserPlugins (line 175) | type UserPlugins = Record<string, Plugin>;
  type LoadedPlugins (line 176) | type LoadedPlugins = Record<string, Plugin>;
  type DefineModulesFunction (line 180) | type DefineModulesFunction = (newModules: Record<string, any>) => void;
  type WindowLoadPromise (line 292) | type WindowLoadPromise = Promise<void>;
  type MessageElementBase (line 295) | interface MessageElementBase {
  type MessageElementText (line 301) | interface MessageElementText extends MessageElementBase {
  type MessageElementImage (line 308) | interface MessageElementImage extends MessageElementBase {
  type MessageElementFace (line 319) | interface MessageElementFace extends MessageElementBase {
  type MessageElementRaw (line 335) | interface MessageElementRaw extends MessageElementBase {
  type MessageElement (line 338) | type MessageElement = MessageElementText | MessageElementImage | Message...
  type MessageElementSend (line 339) | type MessageElementSend = Omit<MessageElementText, "raw"> | Omit<Message...
  type Message (line 340) | interface Message {
  type Sender (line 362) | interface Sender {
  type Peer (line 377) | interface Peer {
  type User (line 392) | interface User {
  type Group (line 426) | interface Group {
  type LoginAccount (line 456) | interface LoginAccount {
  type Events (line 467) | type Events = {
  type EventEmitter (line 487) | type EventEmitter = import("typed-emitter").default
  type NT (line 489) | interface NT extends NT.EventEmitter {
  type BrowserWindowAPI (line 537) | interface BrowserWindowAPI {
  type AppAPI (line 541) | interface AppAPI {
  type DialogAPI (line 555) | interface DialogAPI {
  type Manifest (line 620) | interface Manifest {
  type Page (line 658) | type Page = "login" | "main" | "chat" | "settings" | "others";
  type PageWithAbout (line 659) | type PageWithAbout = Page | "about";
  type InjectionMain (line 663) | interface InjectionMain {
  type InjectionRenderer (line 676) | interface InjectionRenderer {
  type RequirementsOS (line 698) | interface RequirementsOS {
  type Injection (line 724) | type Injection = InjectionMain | InjectionRenderer;
  type Requirements (line 725) | interface Requirements {
  type ManifestVersion (line 742) | type ManifestVersion = "1.0" | "2.0" | "3.0";
  type Panel (line 746) | type Panel = (props: PanelProps) => React.JSX.Element;
  type PanelProps (line 748) | interface PanelProps {
  type ProcessVersions (line 769) | interface ProcessVersions {
  type HTMLElement (line 775) | interface HTMLElement {
Condensed preview — 103 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,154K chars).
[
  {
    "path": ".gitattributes",
    "chars": 142,
    "preview": "/.yarn/**            linguist-vendored\n/.yarn/releases/*    binary\n/.yarn/plugins/**/*  binary\n/.pnp.*              bina"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 501,
    "preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 2399,
    "preview": "name: Build\n\non:\n    workflow_dispatch:\n    push:\n\njobs:\n    build:\n        runs-on: ubuntu-latest\n        permissions:\n"
  },
  {
    "path": ".gitignore",
    "chars": 2217,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n.pnpm-debug.log*\n\n# Diagnostic reports"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 52,
    "preview": "{\n    \"recommendations\": [\"arcanis.vscode-zipfs\"]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 191,
    "preview": "{\n    \"search.exclude\": {\n        \"**/.yarn\": true,\n        \"**/.pnp.*\": true\n    },\n    \"typescript.tsdk\": \".yarn/sdks/"
  },
  {
    "path": ".yarn/sdks/integrations.yml",
    "chars": 115,
    "preview": "# This file is automatically generated by @yarnpkg/sdks.\n# Manual changes might be lost!\n\nintegrations:\n  - vscode\n"
  },
  {
    "path": ".yarn/sdks/typescript/bin/tsc",
    "chars": 580,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/bin/tsserver",
    "chars": 595,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/lib/tsc.js",
    "chars": 589,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/lib/tsserver.js",
    "chars": 8713,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/lib/tsserverlibrary.js",
    "chars": 8734,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/lib/typescript.js",
    "chars": 610,
    "preview": "#!/usr/bin/env node\n\nconst {existsSync} = require(`fs`);\nconst {createRequire} = require(`module`);\nconst {resolve} = re"
  },
  {
    "path": ".yarn/sdks/typescript/package.json",
    "chars": 108,
    "preview": "{\n  \"name\": \"typescript\",\n  \"version\": \"5.0.4-sdk\",\n  \"main\": \"./lib/typescript.js\",\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "COPYING",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "COPYING.LESSER",
    "chars": 7652,
    "preview": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007"
  },
  {
    "path": "DEVELOPMENT.md",
    "chars": 2886,
    "preview": "# 开发文档\n\n此文档包含了插件开发文档(插件清单规范 v2.0)。\n\n**在开始之前,强烈建议你使用我们的[插件模板仓库](https://github.com/Flysoft-Studio/QQNTim-Plugin-Template)"
  },
  {
    "path": "MANUAL.md",
    "chars": 5753,
    "preview": "# 使用手册\n\n此文档包含了使用教程。\n\n## 已知支持的 QQNT 版本\n\n| 操作系统 | 最高版本 | 最低版本 |\n| -------- | -------- | -------- |\n| Windows  | 9.9.1    |"
  },
  {
    "path": "README.md",
    "chars": 1187,
    "preview": "# QQNT-Improved - PC 端 QQNT 插件管理器\n\n此项目已废弃,我们正在全力开发全新 QQ 客户端——QPlugged,敬请期待。\n\n[![Maintainability](https://api.codeclimate"
  },
  {
    "path": "build.ts",
    "chars": 4029,
    "preview": "import { BuildOptions, build } from \"esbuild\";\nimport { copy, emptyDir, ensureDir, readdir, writeFile } from \"fs-extra\";"
  },
  {
    "path": "examples/NT-API/consts.js",
    "chars": 231,
    "preview": "module.exports = {\n    id: \"example-nt-api\",\n    defaults: {\n        showAccountInfo: true,\n        showHistoryMessages:"
  },
  {
    "path": "examples/NT-API/qqntim.json",
    "chars": 267,
    "preview": "{\n    \"manifestVersion\": \"3.0\",\n    \"id\": \"example-nt-api\",\n    \"name\": \"示例插件:NT API\",\n    \"author\": \"Flysoft\",\n    \"inj"
  },
  {
    "path": "examples/NT-API/renderer.js",
    "chars": 3684,
    "preview": "const path = require(\"path\");\nconst qqntim = require(\"qqntim/renderer\");\nconst { id, defaults } = require(\"./consts\");\n\n"
  },
  {
    "path": "examples/NT-API/settings.js",
    "chars": 6168,
    "preview": "const { Fragment, createElement } = require(\"react\");\nconst { defineSettingsPanels } = require(\"qqntim-settings\");\nconst"
  },
  {
    "path": "package.json",
    "chars": 2009,
    "preview": "{\n    \"name\": \"qqnt-improved\",\n    \"private\": true,\n    \"version\": \"3.1.3\",\n    \"license\": \"LGPL-3.0-or-later\",\n    \"pac"
  },
  {
    "path": "publish/_/install.ps1",
    "chars": 7295,
    "preview": "$ErrorActionPreference = \"Stop\"\r\n\r\n$Host.UI.RawUI.WindowTitle = \"QQNTim 安装程序 (PowerShell)\"\r\nSet-Location (Split-Path -P"
  },
  {
    "path": "publish/_/uninstall.ps1",
    "chars": 3139,
    "preview": "$ErrorActionPreference = \"Stop\"\r\n\r\n$Host.UI.RawUI.WindowTitle = \"QQNTim 卸载程序 (PowerShell)\"\r\nSet-Location (Split-Path -P"
  },
  {
    "path": "publish/install.cmd",
    "chars": 825,
    "preview": "@setlocal enableextensions\r\n@echo off\r\ncd /d %~dp0_\r\ncolor F0\r\nmode con cols=65 lines=16\r\n\r\nset PS_PREFIX=powershell -No"
  },
  {
    "path": "publish/install.sh",
    "chars": 1826,
    "preview": "#!/usr/bin/env bash\n\npushd \"$( dirname \"${BASH_SOURCE[0]}\" )/_\" > /dev/null\n\n# 判断是否拥有 root 权限\nif [ ! \"$(whoami)\" == \"roo"
  },
  {
    "path": "publish/install_macos.sh",
    "chars": 1829,
    "preview": "#!/usr/bin/env bash\n\npushd \"$( dirname \"${BASH_SOURCE[0]}\" )/_\" > /dev/null\n\n# 判断是否拥有 root 权限\nif [ ! \"$(whoami)\" == \"roo"
  },
  {
    "path": "publish/uninstall.cmd",
    "chars": 831,
    "preview": "@setlocal enableextensions\r\n@echo off\r\ncd /d %~dp0_\r\ncolor F0\r\nmode con cols=65 lines=16\r\n\r\nset PS_PREFIX=powershell -No"
  },
  {
    "path": "publish/uninstall.sh",
    "chars": 1694,
    "preview": "#!/usr/bin/env bash\n\npushd \"$( dirname \"${BASH_SOURCE[0]}\" )/_\" > /dev/null\n\n# 判断是否拥有 root 权限\nif [ ! \"$(whoami)\" == \"roo"
  },
  {
    "path": "publish/uninstall_macos.sh",
    "chars": 1573,
    "preview": "#!/usr/bin/env bash\n\npushd \"$( dirname \"${BASH_SOURCE[0]}\" )/_\" > /dev/null\n\n# 判断是否拥有 root 权限\nif [ ! \"$(whoami)\" == \"roo"
  },
  {
    "path": "rome.json",
    "chars": 670,
    "preview": "{\n    \"$schema\": \"https://docs.rome.tools/schemas/12.1.3/schema.json\",\n    \"organizeImports\": {\n        \"enabled\": true\n"
  },
  {
    "path": "scripts/pack.ps1",
    "chars": 929,
    "preview": "$ErrorActionPreference = \"Stop\"\r\n\r\nSet-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + \"\\..\")\r\n$CD "
  },
  {
    "path": "scripts/pack.sh",
    "chars": 360,
    "preview": "#!/usr/bin/env bash\n\ncd \"$( dirname \"${BASH_SOURCE[0]}\" )/..\"\n\npushd ./dist/_/node_modules > /dev/null\n\n# 设置特定时间戳,确保两次构建"
  },
  {
    "path": "scripts/start.ps1",
    "chars": 731,
    "preview": "$ErrorActionPreference = \"Stop\"\r\n\r\nSet-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + \"\\..\")\r\n\r\n# "
  },
  {
    "path": "scripts/start.sh",
    "chars": 452,
    "preview": "#!/usr/bin/env bash\n\ncd \"$( dirname \"${BASH_SOURCE[0]}\" )/..\"\n\n( qq || linuxqq || flatpak run com.qq.QQ ) 2>&1 | sed -e "
  },
  {
    "path": "src/builtins/settings/package.json",
    "chars": 367,
    "preview": "{\n    \"name\": \"@flysoftbeta/qqntim-plugin-settings\",\n    \"private\": true,\n    \"devDependencies\": {\n        \"@flysoftbeta"
  },
  {
    "path": "src/builtins/settings/publish/qqntim.json",
    "chars": 295,
    "preview": "{\n    \"manifestVersion\": \"3.0\",\n    \"id\": \"builtin-settings-ui\",\n    \"name\": \"设置\",\n    \"author\": \"Flysoft\",\n    \"injecti"
  },
  {
    "path": "src/builtins/settings/publish/style.css",
    "chars": 2812,
    "preview": ".q-switch {\n    position: relative;\n}\n\n.q-switch > input {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0"
  },
  {
    "path": "src/builtins/settings/src/_renderer.tsx",
    "chars": 2137,
    "preview": "import * as exports from \"./exports\";\nimport * as exportsComponents from \"./exports/components\";\nimport { Navigation, Ta"
  },
  {
    "path": "src/builtins/settings/src/exports/components.tsx",
    "chars": 7677,
    "preview": "import { cl } from \"../utils/consts\";\nimport { Fragment, ReactNode, useState } from \"react\";\n\nexport function SettingsSe"
  },
  {
    "path": "src/builtins/settings/src/exports/index.ts",
    "chars": 393,
    "preview": "export const panels: [string, QQNTim.Settings.Panel, string | undefined][] = [];\nlet renderNav: Function = () => undefin"
  },
  {
    "path": "src/builtins/settings/src/installer.ts",
    "chars": 4315,
    "preview": "import { s } from \"./utils/sep\";\nimport { randomUUID } from \"crypto\";\nimport * as path from \"path\";\nimport { allPlugins,"
  },
  {
    "path": "src/builtins/settings/src/main.ts",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/builtins/settings/src/nav.tsx",
    "chars": 4816,
    "preview": "import { panels } from \"./exports\";\nimport { cl } from \"./utils/consts\";\nimport { utils } from \"qqntim/renderer\";\nimport"
  },
  {
    "path": "src/builtins/settings/src/panel.tsx",
    "chars": 9008,
    "preview": "import { Button, SettingsBox, SettingsBoxItem, SettingsSection, Switch } from \"./exports/components\";\nimport { installFo"
  },
  {
    "path": "src/builtins/settings/src/qqntim-env.d.ts",
    "chars": 54,
    "preview": "/// <reference types=\"@flysoftbeta/qqntim-typings\" />\n"
  },
  {
    "path": "src/builtins/settings/src/renderer.ts",
    "chars": 55,
    "preview": "import Entry from \"./_renderer\";\nexport default Entry;\n"
  },
  {
    "path": "src/builtins/settings/src/utils/consts.ts",
    "chars": 1582,
    "preview": "export const cl = {\n    nav: {\n        c: \"qqntim-settings-nav\",\n        item: {\n            c: \"qqntim-settings-nav-ite"
  },
  {
    "path": "src/builtins/settings/src/utils/hooks.tsx",
    "chars": 295,
    "preview": "import { useEffect, useRef } from \"react\";\n\n// Thanks https://learnersbucket.com/examples/interview/useprevious-hook-in-"
  },
  {
    "path": "src/builtins/settings/src/utils/sep.ts",
    "chars": 33,
    "preview": "export { sep as s } from \"path\";\n"
  },
  {
    "path": "src/builtins/settings/src/utils/utils.ts",
    "chars": 2345,
    "preview": "import { allPlugins, modules } from \"qqntim/renderer\";\nconst { fs } = modules;\n\nexport function isInWhitelist(id: string"
  },
  {
    "path": "src/builtins/settings/tsconfig.json",
    "chars": 364,
    "preview": "{\n    \"compilerOptions\": {\n        \"jsx\": \"react-jsx\",\n        \"module\": \"CommonJS\",\n        \"moduleResolution\": \"Node\","
  },
  {
    "path": "src/common/global.ts",
    "chars": 294,
    "preview": "export const env = {} as QQNTim.Environment;\nexport const allPlugins = {} as QQNTim.Plugin.AllUsersPlugins;\n\nexport cons"
  },
  {
    "path": "src/common/ipc.ts",
    "chars": 1812,
    "preview": "import { env } from \"./global\";\nimport { printObject } from \"./utils/console\";\nimport { isMainProcess } from \"./utils/pr"
  },
  {
    "path": "src/common/loader.ts",
    "chars": 1466,
    "preview": "import { s } from \"./sep\";\n\nconst loadedPlugins: QQNTim.Plugin.LoadedPlugins = {};\n\nfunction getUserPlugins(allPlugins: "
  },
  {
    "path": "src/common/patch.ts",
    "chars": 329,
    "preview": "const modules: Record<string, any> = {};\n\nexport function defineModules(newModules: Record<string, any>) {\n    for (cons"
  },
  {
    "path": "src/common/paths.ts",
    "chars": 380,
    "preview": "import { s } from \"./sep\";\n\nexport const dataDir = process.env[\"QQNTIM_HOME\"] || (process.platform == \"win32\" ? `${proce"
  },
  {
    "path": "src/common/sep.ts",
    "chars": 33,
    "preview": "export { sep as s } from \"path\";\n"
  },
  {
    "path": "src/common/utils/console.ts",
    "chars": 419,
    "preview": "import { isMainProcess } from \"./process\";\nimport supportsColor from \"supports-color\";\nimport { inspect } from \"util\";\n\n"
  },
  {
    "path": "src/common/utils/freePort.ts",
    "chars": 222,
    "preview": "import { AddressInfo, createServer } from \"net\";\n\nexport function findFreePort() {\n    const server = createServer().lis"
  },
  {
    "path": "src/common/utils/ntVersion.ts",
    "chars": 587,
    "preview": "import { s } from \"../sep\";\nimport { readJSONSync } from \"fs-extra\";\n\nexport function getCurrentNTVersion() {\n    let ve"
  },
  {
    "path": "src/common/utils/process.ts",
    "chars": 80,
    "preview": "import { app } from \"electron\";\n\nexport const isMainProcess = !!app as boolean;\n"
  },
  {
    "path": "src/common/version.ts",
    "chars": 346,
    "preview": "import { version } from \"../../package.json\";\nimport { getCurrentNTVersion } from \"./utils/ntVersion\";\n\nexport function "
  },
  {
    "path": "src/common/watch.ts",
    "chars": 1448,
    "preview": "import { env } from \"./global\";\nimport { printObject } from \"./utils/console\";\n\ntype Constructor<T> = new (...args: any["
  },
  {
    "path": "src/electron/README.txt",
    "chars": 19,
    "preview": "Silence is golden.\n"
  },
  {
    "path": "src/electron/package.json",
    "chars": 73,
    "preview": "{\n    \"name\": \"electron\",\n    \"private\": true,\n    \"version\": \"25.2.0\"\n}\n"
  },
  {
    "path": "src/main/api.ts",
    "chars": 796,
    "preview": "import { env } from \"../common/global\";\nimport { addInterruptIpc } from \"../common/ipc\";\nimport { defineModules } from \""
  },
  {
    "path": "src/main/compatibility.ts",
    "chars": 421,
    "preview": "import { env } from \"../common/global\";\nimport { existsSync } from \"fs-extra\";\nimport { resolve } from \"path\";\n\nexport f"
  },
  {
    "path": "src/main/config.ts",
    "chars": 2401,
    "preview": "import { configFile, dataDir, pluginDir, pluginPerUserDir } from \"../common/paths\";\nimport * as fs from \"fs-extra\";\n\nfun"
  },
  {
    "path": "src/main/debugger.ts",
    "chars": 1968,
    "preview": "import { env } from \"../common/global\";\nimport { findFreePort } from \"../common/utils/freePort\";\nimport axios from \"axio"
  },
  {
    "path": "src/main/loader.ts",
    "chars": 823,
    "preview": "import { loadPlugins } from \"../common/loader\";\n\nlet scripts: [QQNTim.Plugin, string][] = [];\n\nfunction shouldInject(inj"
  },
  {
    "path": "src/main/main.ts",
    "chars": 682,
    "preview": "/**\n * @license\n * Copyright (c) Flysoft.\n */\n\nimport { setAllPlugins, setEnv } from \"../common/global\";\nimport { watchI"
  },
  {
    "path": "src/main/patch.ts",
    "chars": 7495,
    "preview": "import { env } from \"../common/global\";\nimport { handleIpc } from \"../common/ipc\";\nimport { defineModules, getModule } f"
  },
  {
    "path": "src/main/plugins.ts",
    "chars": 3938,
    "preview": "import { env } from \"../common/global\";\nimport { s } from \"../common/sep\";\nimport * as fs from \"fs-extra\";\nimport * as o"
  },
  {
    "path": "src/qqntim-env.d.ts",
    "chars": 54,
    "preview": "/// <reference types=\"@flysoftbeta/qqntim-typings\" />\n"
  },
  {
    "path": "src/renderer/api/app.ts",
    "chars": 398,
    "preview": "import { ipcRenderer } from \"electron\";\n\nclass AppAPI implements QQNTim.API.Renderer.AppAPI {\n    relaunch() {\n        i"
  },
  {
    "path": "src/renderer/api/browserWindow.ts",
    "chars": 698,
    "preview": "import { ipcRenderer } from \"electron\";\n\nclass BrowserWindowAPI implements QQNTim.API.Renderer.BrowserWindowAPI {\n    se"
  },
  {
    "path": "src/renderer/api/dialog.ts",
    "chars": 1008,
    "preview": "import { ipcRenderer } from \"electron\";\n\nclass DialogAPI implements QQNTim.API.Renderer.DialogAPI {\n    async confirm(me"
  },
  {
    "path": "src/renderer/api/getVueId.ts",
    "chars": 479,
    "preview": "export function getVueId(element: HTMLElement) {\n    let vueId: string | undefined;\n\n    for (const item in element.data"
  },
  {
    "path": "src/renderer/api/index.ts",
    "chars": 1242,
    "preview": "import { allPlugins, env } from \"../../common/global\";\nimport { addInterruptIpc } from \"../../common/ipc\";\nimport { defi"
  },
  {
    "path": "src/renderer/api/nt/call.ts",
    "chars": 1478,
    "preview": "import { addInterruptIpc } from \"../../../common/ipc\";\nimport { webContentsId } from \"../../main\";\nimport { randomUUID }"
  },
  {
    "path": "src/renderer/api/nt/constructor.ts",
    "chars": 3063,
    "preview": "import { ntMedia } from \"./media\";\n\nexport function constructTextElement(ele: any): QQNTim.API.Renderer.NT.MessageElemen"
  },
  {
    "path": "src/renderer/api/nt/destructor.ts",
    "chars": 1613,
    "preview": "export function destructTextElement(element: QQNTim.API.Renderer.NT.MessageElementText) {\n    return {\n        elementTy"
  },
  {
    "path": "src/renderer/api/nt/index.ts",
    "chars": 5895,
    "preview": "import { addInterruptIpc } from \"../../../common/ipc\";\nimport { ntCall } from \"./call\";\nimport { constructGroup, constru"
  },
  {
    "path": "src/renderer/api/nt/media.ts",
    "chars": 2662,
    "preview": "import { ntCall } from \"./call\";\nimport { NTWatcher } from \"./watcher\";\nimport { exists } from \"fs-extra\";\n\nclass NTMedi"
  },
  {
    "path": "src/renderer/api/nt/watcher.ts",
    "chars": 936,
    "preview": "import { addInterruptIpc } from \"../../../common/ipc\";\n\nexport class NTWatcher<T extends string | number> {\n    private "
  },
  {
    "path": "src/renderer/api/waitForElement.ts",
    "chars": 870,
    "preview": "import { windowLoadPromise } from \"./windowLoadPromise\";\n\nlet waitForElementSelectors: [string, (element: Element) => vo"
  },
  {
    "path": "src/renderer/api/windowLoadPromise.ts",
    "chars": 115,
    "preview": "export const windowLoadPromise = new Promise<void>((resolve) => window.addEventListener(\"load\", () => resolve()));\n"
  },
  {
    "path": "src/renderer/debugger.ts",
    "chars": 691,
    "preview": "import { env } from \"../common/global\";\nimport { debuggerOrigin, webContentsId } from \"./main\";\n\nexport function attachD"
  },
  {
    "path": "src/renderer/loader.ts",
    "chars": 2488,
    "preview": "import { loadPlugins } from \"../common/loader\";\nimport { windowLoadPromise } from \"./api/windowLoadPromise\";\nimport { ip"
  },
  {
    "path": "src/renderer/main.ts",
    "chars": 1130,
    "preview": "import { setAllPlugins, setEnv } from \"../common/global\";\nimport { watchIpc } from \"../common/ipc\";\nimport { initAPI } f"
  },
  {
    "path": "src/renderer/patch.ts",
    "chars": 3439,
    "preview": "import { env } from \"../common/global\";\nimport { handleIpc } from \"../common/ipc\";\nimport { defineModules, getModule } f"
  },
  {
    "path": "src/renderer/vueHelper.ts",
    "chars": 2478,
    "preview": "interface Component {\n    vnode: {\n        el: VueElement;\n        component: Component;\n    };\n    bum: Function[];\n   "
  },
  {
    "path": "src/typings/COPYING",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "src/typings/COPYING.LESSER",
    "chars": 7652,
    "preview": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007"
  },
  {
    "path": "src/typings/electron.d.ts",
    "chars": 824866,
    "preview": "// Type definitions for Electron 25.2.0\n// Project: http://electronjs.org/\n// Definitions by: The Electron Team <https:/"
  },
  {
    "path": "src/typings/index.d.ts",
    "chars": 23087,
    "preview": "/// <reference types=\"node\" />\n/// <reference types=\"react\" />\n/// <reference types=\"./electron\" />\n\ndeclare module \"qqn"
  },
  {
    "path": "src/typings/package.json",
    "chars": 436,
    "preview": "{\n    \"name\": \"@flysoftbeta/qqntim-typings\",\n    \"version\": \"3.1.3\",\n    \"license\": \"LGPL-3.0-or-later\",\n    \"publishCon"
  },
  {
    "path": "src/typings/tsconfig.json",
    "chars": 359,
    "preview": "{\n    \"compilerOptions\": {\n        \"module\": \"CommonJS\",\n        \"moduleResolution\": \"Node\",\n        \"target\": \"ESNext\","
  },
  {
    "path": "tsconfig.json",
    "chars": 378,
    "preview": "{\n    \"compilerOptions\": {\n        \"jsx\": \"react-jsx\",\n        \"module\": \"CommonJS\",\n        \"moduleResolution\": \"Node\","
  }
]

About this extraction

This page contains the full source code of the Flysoft-Studio/QQNTim GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 103 files (1.1 MB), approximately 240.5k tokens, and a symbol index with 1646 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!