Repository: fuergaosi233/wechat-chatgpt Branch: main Commit: e96349ffa217 Files: 19 Total size: 59.2 KB Directory structure: gitextract_52g6r067/ ├── .dockerignore ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ └── config.yml │ └── workflows/ │ └── publish-docker-hub.yml ├── .gitignore ├── Dockerfile ├── README.md ├── README_ZH.md ├── docker-compose.yml ├── package.json ├── public/ │ └── .gitignore ├── src/ │ ├── bot.ts │ ├── config.ts │ ├── data.ts │ ├── interface.ts │ ├── main.ts │ ├── openai.ts │ └── utils.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ # Created by https://www.toptal.com/developers/gitignore/api/node # Edit at https://www.toptal.com/developers/gitignore?templates=node ### Node ### # 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 # 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 v2 .yarn/cache .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz .pnp.* ### Node Patch ### # Serverless Webpack directories .webpack/ # Optional stylelint cache # SvelteKit build / generate output .svelte-kit # End of https://www.toptal.com/developers/gitignore/api/node n *memory-card.json # Created by https://www.toptal.com/developers/gitignore/api/python # Edit at https://www.toptal.com/developers/gitignore?templates=python ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ ### Python Patch ### # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration poetry.toml docs/ # End of https://www.toptal.com/developers/gitignore/api/python n config.json cache.json config.yaml .vscode ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug Report title: "[Bug]: " labels: ["bug"] description: "Create a report to help us improve." body: - type: checkboxes id: terms attributes: label: Welcome options: - label: Yes, I've searched similar issues on GitHub and didn't find any. required: true - label: Yes, I've included all information below (version, **FULL** config, **FULL** log, etc). required: true - type: checkboxes id: platform attributes: label: Deployment Platform options: - label: Railway - label: Fly.io - label: Docker & Docker Compose - label: Node.js - type: textarea id: problem attributes: label: Description of the problem placeholder: Your problem description validations: required: true - type: textarea id: log attributes: label: wechat-chatgpt operation log value: |-
```console # Paste output here ```
validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Discord Chat url: https://discord.gg/8xWdppS7bE about: Join our Discord server to chat with the community and get help with your issue. ================================================ FILE: .github/workflows/publish-docker-hub.yml ================================================ name: Publish Docker image on: # Test pub with dev tag push: branches: - ci/fix-muti-platform release: types: [published] jobs: push_to_registry: name: Push Docker image to Docker Hub runs-on: ubuntu-latest steps: - name: Check out the repo uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log in to Docker Hub uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 with: images: holegots/wechat-chatgpt - name: Build and push Docker image uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc with: context: . push: true tags: ${{ steps.meta.outputs.tags }} # FIXME: Chrome doesn't seem to install on ARM, so skip it for now # platforms: linux/amd64,linux/arm64 labels: ${{ steps.meta.outputs.labels }} ================================================ FILE: .gitignore ================================================ # Created by https://www.toptal.com/developers/gitignore/api/node # Edit at https://www.toptal.com/developers/gitignore?templates=node ### Node ### # 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 # 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 v2 .yarn/cache .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz .pnp.* ### Node Patch ### # Serverless Webpack directories .webpack/ # Optional stylelint cache # SvelteKit build / generate output .svelte-kit # End of https://www.toptal.com/developers/gitignore/api/node n *memory-card.json # Created by https://www.toptal.com/developers/gitignore/api/python # Edit at https://www.toptal.com/developers/gitignore?templates=python ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ ### Python Patch ### # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration poetry.toml # End of https://www.toptal.com/developers/gitignore/api/python n config.json cache.json config.yaml .vscode data/ ================================================ FILE: Dockerfile ================================================ FROM node:19 AS app # We don't need the standalone Chromium RUN apt-get install -y wget \ && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list \ && apt-get update && apt-get -y install google-chrome-stable chromium xvfb\ && rm -rf /var/lib/apt/lists/* \ && echo "Chrome: " && google-chrome --version WORKDIR /app COPY package*.json ./ RUN npm install COPY . . CMD xvfb-run --server-args="-screen 0 1280x800x24 -ac -nolisten tcp -dpi 96 +extension RANDR" npm run dev ================================================ FILE: README.md ================================================

!!!! Project Archived 📦 !!!!

> This project has been archived. Thank you to everyone who contributed! 🙌😔

Welcome to wechat-chatgpt 👋

Version License: ISC Twitter: fuergaosi join discord community of github profile readme generator

> Use ChatGPT On Wechat via wechaty > English | [中文文档](README_ZH.md) [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/dMLG70?referralCode=bIYugQ) ## 🌟 Features - Interact with WeChat and ChatGPT: - Use ChatGPT on WeChat with [wechaty](https://github.com/wechaty/wechaty) and [Official API](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) - Add conversation support - Support command setting - Deployment and configuration options: - Add Dockerfile, deployable with [docker](#use-with-docker) - Support deployment using [docker compose](#use-with-docker-compose) - Support [Railway](#use-with-railway) and [Fly.io](#use-with-flyio) deployment - Other features: - Support [Dall·E](https://labs.openai.com/) - Support [whisper](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) - Support setting prompt - Support proxy (in development) ## 🚀 Usage - [Use with Railway](#use-with-railway)(PaaS, Free, Stable, ✅Recommended) - [Use with Fly.io](#use-with-flyio)(Paas, Free, ✅Recommended) - [Use with docker](#use-with-docker)(Self-hosted, Stable, ✅Recommended) - [Use with docker compose](#use-with-docker-compose)(Self-hosted, Stable, ✅Recommended) - [Use with nodejs](#use-with-nodejs)(Self-hosted) ## Use with Railway > Railway offers $5 or 500 hours of runtime per month 1. Click the [Railway](https://railway.app/template/dMLG70?referralCode=bIYugQ) button to go to the Railway deployment page 2. Click the `Deploy Now` button to enter the Railway deployment page 3. Fill in the repository name and `OPENAI_API_KEY` (need to link GitHub account) 4. Click the `Deploy` button 5. Click the `View Logs` button and wait for the deployment to complete ## Use with Fly.io > Please allocate 512MB memory for the application to meet the application requirements > fly.io offers free bills up to $5(Free Allowances 3 256MB are not included in the bill) 1. Install [flyctl](https://fly.io/docs/getting-started/installing-flyctl/) ```shell # macOS brew install flyctl # Windows scoop install flyctl # Linux curl https://fly.io/install.sh | sh ``` 2. Clone the project and enter the project directory ```shell git clone https://github.com/fuergaosi233/wechat-chatgpt.git && cd wechat-chatgpt ``` 3. Create a new app ```shell ➜ flyctl launch ? Would you like to copy its configuration to the new app? No ? App Name (leave blank to use an auto-generated name): ? Select region: ? Would you like to setup a Postgresql database now? No ? Would you like to deploy now? No ``` 4. Configure the environment variables ```shell flyctl secrets set OPENAI_API_KEY="" MODEL="" ``` 5. Deploy the app ```shell flyctl deploy ``` ## Use with docker ```sh # pull image docker pull holegots/wechat-chatgpt # run container docker run -d --name wechat-chatgpt \ -e OPENAI_API_KEY= \ -e MODEL="gpt-3.5-turbo" \ -e CHAT_PRIVATE_TRIGGER_KEYWORD="" \ -v $(pwd)/data:/app/data/wechat-assistant.memory-card.json \ holegots/wechat-chatgpt:latest # View the QR code to log in to wechat docker logs -f wechat-chatgpt ``` > How to get OPENAI API KEY? [Click here](https://platform.openai.com/account/api-keys) ## Use with docker compose ```sh # Copy the configuration file according to the template cp .env.example .env # Edit the configuration file vim .env # Start the container docker-compose up -d # View the QR code to log in to wechat docker logs -f wechat-chatgpt ``` ## Use with nodejs > You need NodeJS 18.0.0 version and above ```sh # Clone the project git clone https://github.com/fuergaosi233/wechat-chatgpt.git && cd wechat-chatgpt # Install dependencies npm install # Copy the configuration file according to the template cp .env.example .env # Edit the configuration file vim .env # Start project npm run dev ``` > Please make sure your WeChat account can log in [WeChat on web](https://wx.qq.com/) ## 📝 Environment Variables | name | description | |------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | API | API endpoint of ChatGPT | | OPENAI_API_KEY | [create new secret key](https://platform.openai.com/account/api-keys) | | MODEL | ID of the model to use. Currently, only gpt-3.5-turbo and gpt-3.5-turbo-0301 are supported. | | TEMPERATURE | What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. | | CHAT_TRIGGER_RULE | Private chat triggering rules. | | DISABLE_GROUP_MESSAGE | Prohibited to use ChatGPT in group chat. | | CHAT_PRIVATE_TRIGGER_KEYWORD | Keyword to trigger ChatGPT reply in WeChat private chat | | BLOCK_WORDS | Chat blocker words, (works for both private and group chats, Use, Split) | | CHATGPT_BLOCK_WORDS | The blocked words returned by ChatGPT(works for both private and group chats, Use, Split) | ## 📝 Using Custom ChatGPT API > https://github.com/fuergaosi233/openai-proxy ```shell # Clone the project git clone https://github.com/fuergaosi233/openai-proxy # Install dependencies npm install && npm install -g wrangler && npm run build # Deploy to CloudFlare Workers npm run deploy # Custom domain (optional) Add `Route` to `wrangler.toml` routes = [ { pattern = "Your Custom Domain", custom_domain = true }, ] ``` ## ⌨️ Commands > Enter in the WeChat chat box ```shell /cmd help # Show help /cmd prompt # Set prompt /cmd clear # Clear all sessions since last boot ``` ## ✨ Contributor ## 🤝 Contributing Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/fuergaosi233/wechat-chatgpt/issues). ## Show your support Give a ⭐️ if this project helped you! ================================================ FILE: README_ZH.md ================================================

欢迎使用 wechat-chatgpt 👋

Version License: ISC Twitter: fuergaosi join discord community of github profile readme generator

> 在微信上迅速接入 ChatGPT,让它成为你最好的助手! > [English](README.md) | 中文文档 [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/dMLG70?referralCode=bIYugQ) ## 🌟 功能点 - 使用 WeChat 和 ChatGPT 进行互动: - 基于 [wechaty](https://github.com/wechaty/wechaty) 和 [Official API](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) 在微信中使用 ChatGPT - 支持多轮对话 - 支持[命令](#-命令)设置 - 部署和配置选项: - 提供 Dockerfile,可以通过 [docker](#通过docker使用) 进行部署 - 支持使用 [docker compose](#通过docker-compose使用) 进行部署 - 支持在 [Railway](#使用railway进行部署) 和 [Fly.io](#通过flyio进行部署) 上部署 - 其他功能: - 支持 [Dall·E](https://labs.openai.com/) - 支持 [whisper](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) - 支持设置 prompt - 支持代理(开发中) ## 🚀 使用 - [在 Railway 部署](#使用railway进行部署)(PaaS, 免费, 稳定, ✅推荐) - [在 Fly.io 部署](#通过flyio进行部署)(PaaS, 免费, ✅推荐) - [使用 Docker 部署](#通过docker使用)(自托管, 稳定, ✅推荐) - [使用 Docker Compose 部署](#通过docker-compose使用)(自托管, 稳定, ✅推荐) - [使用 NodeJS 部署](#使用nodejs运行) ## 使用Railway进行部署 > Railway 是一个免费的 PaaS 平台,5刀以内的账单免费或者每个月500小时的运行时间 1. 点击 [Railway](https://railway.app/template/dMLG70?referralCode=bIYugQ) 按钮,进入 Railway 部署页面 2. 点击 `Deploy Now` 按钮,进入 Railway 部署页面 3. 填写 仓库名称和 `OPENAI_API_KEY`(需要连接 GitHub 账号) 4. 点击 `Deploy` 按钮 5. 点击 `View Logs` 按钮,等待部署完成 ## 通过Fly.io进行部署 > 请为应用程序分配 512 MB 内存,否则可能会出现内存溢出 > Fly.io 5刀以内的账单免费(免费计划的3个256MB的应用不在账单内)也就是可以同时可以部署 `1*512MB + 3*256MB` 1. 安装 [flyctl](https://fly.io/docs/getting-started/installing-flyctl/) ```shell # macOS brew install flyctl # Windows scoop install flyctl # Linux curl https://fly.io/install.sh | sh ``` 2. 克隆项目并进入项目目录 ```shell git clone https://github.com/fuergaosi233/wechat-chatgpt.git && cd wechat-chatgpt ``` 3. 创建应用 ```shell ➜ flyctl launch ? Would you like to copy its configuration to the new app? No ? App Name (leave blank to use an auto-generated name): ? Select region: ? Would you like to setup a Postgresql database now? No ? Would you like to deploy now? No ``` 4. 配置环境变量 ```shell flyctl secrets set OPENAI_API_KEY="" MODEL="" ``` 5. 部署应用 ```shell flyctl deploy ``` ## 通过Docker使用 ```sh # 拉取镜像 docker pull holegots/wechat-chatgpt:latest # 运行容器 docker run -it --name wechat-chatgpt \ -e OPENAI_API_KEY= \ -e MODEL="gpt-3.5-turbo" \ -e CHAT_PRIVATE_TRIGGER_KEYWORD="" \ -v $(pwd)/data:/app/data/wechat-assistant.memory-card.json \ holegots/wechat-chatgpt:latest # 使用二维码登陆 docker logs -f wechat-chatgpt ``` > 如何获取 OPENAI API KEY?请参考 [OpenAI API](https://platform.openai.com/account/api-keys)。 ## 通过docker compose使用 ```sh # 根据模板拷贝配置文件 cp .env.example .env # 使用你喜欢的文本编辑器修改配置文件 vim .env # 在Linux或WindowsPowerShell上运行如下命令 docker compose up -d # 使用二维码登陆 docker logs -f wechat-chatgpt ``` ## 使用NodeJS运行 > 请确认安装的NodeJS版本为18.0.0以上 ```sh # 克隆项目 git clone https://github.com/fuergaosi233/wechat-chatgpt.git && cd wechat-chatgpt # 安装依赖 npm install # 编辑配置 cp .env.example .env vim .env # 使用你喜欢的文本编辑器修改配置文件 # 启动项目 npm run dev # 如果您是初次登陆,那么需要扫描二维码 ``` > 请确保您的账号可以登陆 [网页版微信](https://wx.qq.com/)。 ## 📝 Environment Variables | name | default | example | description | |--------------------------|------------------------|------------------------------------------------|-------------------------------------------------------------| | API | https://api.openai.com | | 自定义ChatGPT API 地址 | | OPENAI_API_KEY | 123456789 | sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | [创建你的 API 密钥](https://platform.openai.com/account/api-keys) | | MODEL | gpt-3.5-turbo | | 要使用的模型ID, 目前仅支持`gpt-3.5-turbo` 和 `gpt-3.5-turbo-0301` | | TEMPERATURE | 0.6 | | 在0和2之间。较高的数值如0.8会使 ChatGPT 输出更加随机,而较低的数值如0.2会使其更加稳定。 | | CHAT_TRIGGER_RULE | | | 私聊触发规则 | | DISABLE_GROUP_MESSAGE | true | | 禁用在群聊里使用ChatGPT | | CHAT_PRIVATE_TRIGGER_KEYWORD | | | 在私聊中触发ChatGPT的关键词, 默认是无需关键词即可触发 | | BLOCK_WORDS | "VPN" | "WORD1,WORD2,WORD3" | 聊天屏蔽关键词(同时在群组和私聊中生效, 避免 bot 用户恶意提问导致封号 | | CHATGPT_BLOCK_WORDS | "VPN" | "WORD1,WORD2,WORD3" | ChatGPT回复屏蔽词, 如果ChatGPT的回复中包含了屏蔽词, 则不回复 | ## 📝 使用自定义ChatGPT API > https://github.com/fuergaosi233/openai-proxy ```shell # 克隆项目 git clone https://github.com/fuergaosi233/openai-proxy # 安装依赖 npm install && npm install -g wrangler && npm run build # 部署到 CloudFlare Workers npm run deploy # 自定义域名(可选) 添加 `Route`` 到 `wrangler.toml` routes = [ { pattern = "Your Custom Domain", custom_domain = true }, ] ``` ## ⌨️ 命令 > 在微信聊天框中输入 ```shell /cmd help # 显示帮助信息 /cmd prompt # 设置ChatGPT Prompt /cmd clear # 清除WeChat-ChatGPT保存的会话记录 ``` ## ✨ Contributor ## 🤝 为项目添砖加瓦 欢迎提出 Contributions, issues 与 feature requests!
随时查看 [issues page](https://github.com/fuergaosi233/wechat-chatgpt/issues). ## 感谢支持 🙏 如果这个项目对你产生了一点的帮助,请为这个项目点上一颗 ⭐️ ================================================ FILE: docker-compose.yml ================================================ version: '3' services: wechat-chatgpt: image: wechat-chatgpt build: . volumes: - ./data/wechat-assistant.memory-card.json:/app/wechat-assistant.memory-card.json env_file: - .env ================================================ FILE: package.json ================================================ { "name": "wechat-chatgpt", "version": "1.0.0", "description": "", "main": "dist/main.js", "export": "dist/main.js", "scripts": { "dev": "nodemon --exec node --loader ts-node/esm src/main.ts", "build": "tsc" }, "author": "", "license": "ISC", "dependencies": { "async-retry": "^1.3.3", "dotenv": "^16.0.3", "execa": "^6.1.0", "gpt3-tokenizer": "^1.1.5", "openai": "^3.2.1", "qrcode": "^1.5.1", "uuid": "^9.0.0", "wechaty": "^1.20.2", "wechaty-puppet-wechat": "^1.18.4" }, "devDependencies": { "@types/async-retry": "^1.4.5", "@types/qrcode": "^1.5.0", "@types/uuid": "^9.0.0", "nodemon": "^2.0.20", "ts-node": "^10.9.1" }, "nodemonConfig": { "watch": [ "src/*.ts" ], "ignore": [ "src/main.ts" ], "ext": "ts", "exec": "node --loader ts-node/esm src/main.ts", "delay": 500 }, "type": "module" } ================================================ FILE: public/.gitignore ================================================ # Ignore everything in this directory * # Except this file !.gitignore ================================================ FILE: src/bot.ts ================================================ import { config } from "./config.js"; import {ContactImpl, ContactInterface, RoomImpl, RoomInterface} from "wechaty/impls"; import { Message } from "wechaty"; import {FileBox} from "file-box"; import {chatgpt, dalle, whisper} from "./openai.js"; import DBUtils from "./data.js"; import { regexpEncode } from "./utils.js"; enum MessageType { Unknown = 0, Attachment = 1, // Attach(6), Audio = 2, // Audio(1), Voice(34) Contact = 3, // ShareCard(42) ChatHistory = 4, // ChatHistory(19) Emoticon = 5, // Sticker: Emoticon(15), Emoticon(47) Image = 6, // Img(2), Image(3) Text = 7, // Text(1) Location = 8, // Location(48) MiniProgram = 9, // MiniProgram(33) GroupNote = 10, // GroupNote(53) Transfer = 11, // Transfers(2000) RedEnvelope = 12, // RedEnvelopes(2001) Recalled = 13, // Recalled(10002) Url = 14, // Url(5) Video = 15, // Video(4), Video(43) Post = 16, // Moment, Channel, Tweet, etc } const SINGLE_MESSAGE_MAX_SIZE = 500; type Speaker = RoomImpl | ContactImpl; interface ICommand{ name:string; description:string; exec: (talker:Speaker, text:string) => Promise; } export class ChatGPTBot { chatPrivateTriggerKeyword = config.chatPrivateTriggerKeyword; chatTriggerRule = config.chatTriggerRule? new RegExp(config.chatTriggerRule): undefined; disableGroupMessage = config.disableGroupMessage || false; botName: string = ""; ready = false; setBotName(botName: string) { this.botName = botName; } get chatGroupTriggerRegEx(): RegExp { return new RegExp(`^@${regexpEncode(this.botName)}\\s`); } get chatPrivateTriggerRule(): RegExp | undefined { const { chatPrivateTriggerKeyword, chatTriggerRule } = this; let regEx = chatTriggerRule if (!regEx && chatPrivateTriggerKeyword) { regEx = new RegExp(regexpEncode(chatPrivateTriggerKeyword)) } return regEx } private readonly commands:ICommand[] = [ { name: "help", description: "显示帮助信息", exec: async (talker) => { await this.trySay(talker,"========\n" + "/cmd help\n" + "# 显示帮助信息\n" + "/cmd prompt \n" + "# 设置当前会话的 prompt \n" + "/img \n" + "# 根据 prompt 生成图片\n" + "/cmd clear\n" + "# 清除自上次启动以来的所有会话\n" + "========"); } }, { name: "prompt", description: "设置当前会话的prompt", exec: async (talker, prompt) => { if (talker instanceof RoomImpl) { DBUtils.setPrompt(await talker.topic(), prompt); }else { DBUtils.setPrompt(talker.name(), prompt); } } }, { name: "clear", description: "清除自上次启动以来的所有会话", exec: async (talker) => { if (talker instanceof RoomImpl) { DBUtils.clearHistory(await talker.topic()); }else{ DBUtils.clearHistory(talker.name()); } } } ] /** * EXAMPLE: * /cmd help * /cmd prompt * /cmd img * /cmd clear * @param contact * @param rawText */ async command(contact: any, rawText: string): Promise { const [commandName, ...args] = rawText.split(/\s+/); const command = this.commands.find( (command) => command.name === commandName ); if (command) { await command.exec(contact, args.join(" ")); } } // remove more times conversation and mention cleanMessage(rawText: string, privateChat: boolean = false): string { let text = rawText; const item = rawText.split("- - - - - - - - - - - - - - -"); if (item.length > 1) { text = item[item.length - 1]; } const { chatTriggerRule, chatPrivateTriggerRule } = this; if (privateChat && chatPrivateTriggerRule) { text = text.replace(chatPrivateTriggerRule, "") } else if (!privateChat) { text = text.replace(this.chatGroupTriggerRegEx, "") text = chatTriggerRule? text.replace(chatTriggerRule, ""): text } // remove more text via - - - - - - - - - - - - - - - return text } async getGPTMessage(talkerName: string,text: string): Promise { let gptMessage = await chatgpt(talkerName,text); if (gptMessage !=="") { DBUtils.addAssistantMessage(talkerName,gptMessage); return gptMessage; } return "Sorry, please try again later. 😔"; } // Check if the message returned by chatgpt contains masked words] checkChatGPTBlockWords(message: string): boolean { if (config.chatgptBlockWords.length == 0) { return false; } return config.chatgptBlockWords.some((word) => message.includes(word)); } // The message is segmented according to its size async trySay( talker: RoomInterface | ContactInterface, mesasge: string ): Promise { const messages: Array = []; if (this.checkChatGPTBlockWords(mesasge)) { console.log(`🚫 Blocked ChatGPT: ${mesasge}`); return; } let message = mesasge; while (message.length > SINGLE_MESSAGE_MAX_SIZE) { messages.push(message.slice(0, SINGLE_MESSAGE_MAX_SIZE)); message = message.slice(SINGLE_MESSAGE_MAX_SIZE); } messages.push(message); for (const msg of messages) { await talker.say(msg); } } // Check whether the ChatGPT processing can be triggered triggerGPTMessage(text: string, privateChat: boolean = false): boolean { const { chatTriggerRule } = this; let triggered = false; if (privateChat) { const regEx = this.chatPrivateTriggerRule triggered = regEx? regEx.test(text): true; } else { triggered = this.chatGroupTriggerRegEx.test(text); // group message support `chatTriggerRule` if (triggered && chatTriggerRule) { triggered = chatTriggerRule.test(text.replace(this.chatGroupTriggerRegEx, "")) } } if (triggered) { console.log(`🎯 Triggered ChatGPT: ${text}`); } return triggered; } // Check whether the message contains the blocked words. if so, the message will be ignored. if so, return true checkBlockWords(message: string): boolean { if (config.blockWords.length == 0) { return false; } return config.blockWords.some((word) => message.includes(word)); } // Filter out the message that does not need to be processed isNonsense( talker: ContactInterface, messageType: MessageType, text: string ): boolean { return ( talker.self() || // TODO: add doc support !(messageType == MessageType.Text || messageType == MessageType.Audio) || talker.name() === "微信团队" || // 语音(视频)消息 text.includes("收到一条视频/语音聊天消息,请在手机上查看") || // 红包消息 text.includes("收到红包,请在手机上查看") || // Transfer message text.includes("收到转账,请在手机上查看") || // 位置消息 text.includes("/cgi-bin/mmwebwx-bin/webwxgetpubliclinkimg") || // 聊天屏蔽词 this.checkBlockWords(text) ); } async onPrivateMessage(talker: ContactInterface, text: string) { const gptMessage = await this.getGPTMessage(talker.name(),text); await this.trySay(talker, gptMessage); } async onGroupMessage( talker: ContactInterface, text: string, room: RoomInterface ) { const gptMessage = await this.getGPTMessage(await room.topic(),text); const result = `@${talker.name()} ${text}\n\n------\n ${gptMessage}`; await this.trySay(room, result); } async onMessage(message: Message) { const talker = message.talker(); const rawText = message.text(); const room = message.room(); const messageType = message.type(); const privateChat = !room; if (privateChat) { console.log(`🤵 Contact: ${talker.name()} 💬 Text: ${rawText}`) } else { const topic = await room.topic() console.log(`🚪 Room: ${topic} 🤵 Contact: ${talker.name()} 💬 Text: ${rawText}`) } if (this.isNonsense(talker, messageType, rawText)) { return; } if (messageType == MessageType.Audio){ // 保存语音文件 const fileBox = await message.toFileBox(); let fileName = "./public/" + fileBox.name; await fileBox.toFile(fileName, true).catch((e) => { console.log("保存语音失败",e); return; }); // Whisper whisper("",fileName).then((text) => { message.say(text); }) return; } if (rawText.startsWith("/cmd ")){ console.log(`🤖 Command: ${rawText}`) const cmdContent = rawText.slice(5) // 「/cmd 」一共5个字符(注意空格) if (privateChat) { await this.command(talker, cmdContent); }else{ await this.command(room, cmdContent); } return; } // 使用DallE生成图片 if (rawText.startsWith("/img")){ console.log(`🤖 Image: ${rawText}`) const imgContent = rawText.slice(4) if (privateChat) { let url = await dalle(talker.name(), imgContent) as string; const fileBox = FileBox.fromUrl(url) message.say(fileBox) }else{ let url = await dalle(await room.topic(), imgContent) as string; const fileBox = FileBox.fromUrl(url) message.say(fileBox) } return; } if (this.triggerGPTMessage(rawText, privateChat)) { const text = this.cleanMessage(rawText, privateChat); if (privateChat) { return await this.onPrivateMessage(talker, text); } else{ if (!this.disableGroupMessage){ return await this.onGroupMessage(talker, text, room); } else { return; } } } else { return; } } } ================================================ FILE: src/config.ts ================================================ import * as dotenv from "dotenv"; dotenv.config(); import { IConfig } from "./interface"; export const config: IConfig = { api: process.env.API, openai_api_key: process.env.OPENAI_API_KEY || "123456789", model: process.env.MODEL || "gpt-3.5-turbo", chatPrivateTriggerKeyword: process.env.CHAT_PRIVATE_TRIGGER_KEYWORD || "", chatTriggerRule: process.env.CHAT_TRIGGER_RULE || "", disableGroupMessage: process.env.DISABLE_GROUP_MESSAGE === "true", temperature: process.env.TEMPERATURE ? parseFloat(process.env.TEMPERATURE) : 0.6, blockWords: process.env.BLOCK_WORDS?.split(",") || [], chatgptBlockWords: process.env.CHATGPT_BLOCK_WORDS?.split(",") || [], }; ================================================ FILE: src/data.ts ================================================ import {ChatCompletionRequestMessage, ChatCompletionRequestMessageRoleEnum} from "openai"; import {User} from "./interface"; import {isTokenOverLimit} from "./utils.js"; /** * 使用内存作为数据库 */ class DB { private static data: User[] = []; /** * 添加一个用户, 如果用户已存在则返回已存在的用户 * @param username */ public addUser(username: string): User { let existUser = DB.data.find((user) => user.username === username); if (existUser) { console.log(`用户${username}已存在`); return existUser; } const newUser: User = { username: username, chatMessage: [ { role: ChatCompletionRequestMessageRoleEnum.System, content: "You are a helpful assistant." } ], }; DB.data.push(newUser); return newUser; } /** * 根据用户名获取用户, 如果用户不存在则添加用户 * @param username */ public getUserByUsername(username: string): User { return DB.data.find((user) => user.username === username) || this.addUser(username); } /** * 获取用户的聊天记录 * @param username */ public getChatMessage(username: string): Array { return this.getUserByUsername(username).chatMessage; } /** * 设置用户的prompt * @param username * @param prompt */ public setPrompt(username: string, prompt: string): void { const user = this.getUserByUsername(username); if (user) { user.chatMessage.find( (msg) => msg.role === ChatCompletionRequestMessageRoleEnum.System )!.content = prompt; } } /** * 添加用户输入的消息 * @param username * @param message */ public addUserMessage(username: string, message: string): void { const user = this.getUserByUsername(username); if (user) { while (isTokenOverLimit(user.chatMessage)){ // 删除从第2条开始的消息(因为第一条是prompt) user.chatMessage.splice(1,1); } user.chatMessage.push({ role: ChatCompletionRequestMessageRoleEnum.User, content: message, }); } } /** * 添加ChatGPT的回复 * @param username * @param message */ public addAssistantMessage(username: string, message: string): void { const user = this.getUserByUsername(username); if (user) { while (isTokenOverLimit(user.chatMessage)){ // 删除从第2条开始的消息(因为第一条是prompt) user.chatMessage.splice(1,1); } user.chatMessage.push({ role: ChatCompletionRequestMessageRoleEnum.Assistant, content: message, }); } } /** * 清空用户的聊天记录, 并将prompt设置为默认值 * @param username */ public clearHistory(username: string): void { const user = this.getUserByUsername(username); if (user) { user.chatMessage = [ { role: ChatCompletionRequestMessageRoleEnum.System, content: "You are a helpful assistant." } ]; } } public getAllData(): User[] { return DB.data; } } const DBUtils = new DB(); export default DBUtils; ================================================ FILE: src/interface.ts ================================================ import {ChatCompletionRequestMessage} from "openai"; export interface IConfig { api?: string; openai_api_key: string; model: string; chatTriggerRule: string; disableGroupMessage: boolean; temperature: number; blockWords: string[]; chatgptBlockWords: string[]; chatPrivateTriggerKeyword: string; } export interface User { username: string, chatMessage: Array, } ================================================ FILE: src/main.ts ================================================ import { WechatyBuilder } from "wechaty"; import QRCode from "qrcode"; import { ChatGPTBot } from "./bot.js"; import {config} from "./config.js"; const chatGPTBot = new ChatGPTBot(); const bot = WechatyBuilder.build({ name: "wechat-assistant", // generate xxxx.memory-card.json and save login data for the next login puppet: "wechaty-puppet-wechat", puppetOptions: { uos: true } }); async function main() { const initializedAt = Date.now() bot .on("scan", async (qrcode, status) => { const url = `https://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`; console.log(`Scan QR Code to login: ${status}\n${url}`); console.log( await QRCode.toString(qrcode, { type: "terminal", small: true }) ); }) .on("login", async (user) => { chatGPTBot.setBotName(user.name()); console.log(`User ${user} logged in`); console.log(`私聊触发关键词: ${config.chatPrivateTriggerKeyword}`); console.log(`已设置 ${config.blockWords.length} 个聊天关键词屏蔽. ${config.blockWords}`); console.log(`已设置 ${config.chatgptBlockWords.length} 个ChatGPT回复关键词屏蔽. ${config.chatgptBlockWords}`); }) .on("message", async (message) => { if (message.date().getTime() < initializedAt) { return; } if (message.text().startsWith("/ping")) { await message.say("pong"); return; } try { await chatGPTBot.onMessage(message); } catch (e) { console.error(e); } }); try { await bot.start(); } catch (e) { console.error( `⚠️ Bot start failed, can you log in through wechat on the web?: ${e}` ); } } main(); ================================================ FILE: src/openai.ts ================================================ import { Configuration, CreateImageRequestResponseFormatEnum, CreateImageRequestSizeEnum, OpenAIApi } from "openai"; import fs from "fs"; import DBUtils from "./data.js"; import {config} from "./config.js"; const configuration = new Configuration({ apiKey: config.openai_api_key, basePath: config.api, }); const openai = new OpenAIApi(configuration); /** * Get completion from OpenAI * @param username * @param message */ async function chatgpt(username:string,message: string): Promise { // 先将用户输入的消息添加到数据库中 DBUtils.addUserMessage(username, message); const messages = DBUtils.getChatMessage(username); const response = await openai.createChatCompletion({ model: "gpt-3.5-turbo", messages: messages, temperature: config.temperature, }); let assistantMessage = ""; try { if (response.status === 200) { assistantMessage = response.data.choices[0].message?.content.replace(/^\n+|\n+$/g, "") as string; }else{ console.log(`Something went wrong,Code: ${response.status}, ${response.statusText}`) } }catch (e:any) { if (e.request){ console.log("请求出错"); } } return assistantMessage; } /** * Get image from Dall·E * @param username * @param prompt */ async function dalle(username:string,prompt: string) { const response = await openai.createImage({ prompt: prompt, n:1, size: CreateImageRequestSizeEnum._256x256, response_format: CreateImageRequestResponseFormatEnum.Url, user: username }).then((res) => res.data).catch((err) => console.log(err)); if (response) { return response.data[0].url; }else{ return "Generate image failed" } } /** * Speech to text * @param username * @param videoPath */ async function whisper(username:string,videoPath: string): Promise { const file:any= fs.createReadStream(videoPath); const response = await openai.createTranscription(file,"whisper-1") .then((res) => res.data).catch((err) => console.log(err)); if (response) { return response.text; }else{ return "Speech to text failed" } } export {chatgpt,dalle,whisper}; ================================================ FILE: src/utils.ts ================================================ import {ChatCompletionRequestMessage} from "openai"; import GPT3TokenizerImport from 'gpt3-tokenizer'; import {config} from "./config.js"; export const regexpEncode = (str: string) => str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); const GPT3Tokenizer: typeof GPT3TokenizerImport = typeof GPT3TokenizerImport === 'function' ? GPT3TokenizerImport : (GPT3TokenizerImport as any).default; // https://github.com/chathub-dev/chathub/blob/main/src/app/bots/chatgpt-api/usage.ts const tokenizer = new GPT3Tokenizer({ type: 'gpt3' }) function calTokens(chatMessage:ChatCompletionRequestMessage[]):number { let count = 0 for (const msg of chatMessage) { count += countTokens(msg.content) count += countTokens(msg.role) } return count + 2 } function countTokens(str: string):number { const encoded = tokenizer.encode(str) return encoded.bpe.length } export function isTokenOverLimit(chatMessage:ChatCompletionRequestMessage[]): boolean { let limit = 4096; if (config.model==="gpt-3.5-turbo" || config.model==="gpt-3.5-turbo-0301") { limit = 4096; } return calTokens(chatMessage) > limit; } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */ /* Projects */ // "incremental": true, /* Enable incremental compilation */ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ /* Modules */ "module": "esnext", /* Specify what module code is generated. */ "rootDir": "src", /* Specify the root folder within your source files. */ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ "resolveJsonModule": true, /* Enable importing .json files */ // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ "outDir": "dist", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ // "newLine": "crlf", /* Set the newline character for emitting files. */ // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Type Checking */ "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ } }