ForcomeBot 2.2.3__tar.gz → 2.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {forcomebot-2.2.3 → forcomebot-2.2.4}/PKG-INFO +1 -1
- {forcomebot-2.2.3 → forcomebot-2.2.4}/config.example.yaml +13 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/pyproject.toml +1 -1
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/api/routes.py +77 -0
- forcomebot-2.2.4/src/auth/__init__.py +33 -0
- forcomebot-2.2.4/src/auth/database.py +87 -0
- forcomebot-2.2.4/src/auth/dingtalk.py +373 -0
- forcomebot-2.2.4/src/auth/jwt_handler.py +129 -0
- forcomebot-2.2.4/src/auth/middleware.py +260 -0
- forcomebot-2.2.4/src/auth/models.py +107 -0
- forcomebot-2.2.4/src/auth/routes.py +385 -0
- forcomebot-2.2.4/src/clients/qianxun.py +388 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/core/config_manager.py +145 -41
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/core/state_store.py +82 -222
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/handlers/message_handler.py +106 -29
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/handlers/scheduler.py +338 -4
- forcomebot-2.2.4/web/node_modules/@babel/runtime/README.md +19 -0
- forcomebot-2.2.4/web/node_modules/@babel/types/LICENSE +22 -0
- forcomebot-2.2.4/web/node_modules/@popperjs/core/README.md +376 -0
- forcomebot-2.2.4/web/node_modules/@restart/hooks/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/@restart/hooks/README.md +20 -0
- forcomebot-2.2.4/web/node_modules/@types/date-arithmetic/README.md +15 -0
- forcomebot-2.2.4/web/node_modules/@types/prop-types/README.md +15 -0
- forcomebot-2.2.4/web/node_modules/@types/react/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/@types/react-big-calendar/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/@types/react-big-calendar/README.md +15 -0
- forcomebot-2.2.4/web/node_modules/@types/react-dom/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/@types/warning/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/@types/warning/README.md +21 -0
- forcomebot-2.2.4/web/node_modules/date-arithmetic/README.md +65 -0
- forcomebot-2.2.4/web/node_modules/date-fns/README.md +58 -0
- forcomebot-2.2.4/web/node_modules/dayjs/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/dayjs/README.md +202 -0
- forcomebot-2.2.4/web/node_modules/dom-helpers/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/dom-helpers/README.md +70 -0
- forcomebot-2.2.4/web/node_modules/globalize/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/globalize/README.md +865 -0
- forcomebot-2.2.4/web/node_modules/invariant/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/invariant/README.md +37 -0
- forcomebot-2.2.4/web/node_modules/lodash/LICENSE +47 -0
- forcomebot-2.2.4/web/node_modules/lodash/README.md +39 -0
- forcomebot-2.2.4/web/node_modules/lodash-es/README.md +10 -0
- forcomebot-2.2.4/web/node_modules/lodash.merge/LICENSE +47 -0
- forcomebot-2.2.4/web/node_modules/loose-envify/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/loose-envify/README.md +45 -0
- forcomebot-2.2.4/web/node_modules/luxon/README.md +55 -0
- forcomebot-2.2.4/web/node_modules/memoize-one/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/memoize-one/README.md +630 -0
- forcomebot-2.2.4/web/node_modules/moment/LICENSE +22 -0
- forcomebot-2.2.4/web/node_modules/moment/README.md +55 -0
- forcomebot-2.2.4/web/node_modules/moment-timezone/LICENSE +20 -0
- forcomebot-2.2.4/web/node_modules/moment-timezone/README.md +64 -0
- forcomebot-2.2.4/web/node_modules/prop-types/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/prop-types/README.md +302 -0
- forcomebot-2.2.4/web/node_modules/react-big-calendar/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/react-big-calendar/README.md +174 -0
- forcomebot-2.2.4/web/node_modules/react-is/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/react-is/README.md +104 -0
- forcomebot-2.2.4/web/node_modules/react-lifecycles-compat/README.md +57 -0
- forcomebot-2.2.4/web/node_modules/react-overlays/LICENSE +22 -0
- forcomebot-2.2.4/web/node_modules/react-overlays/README.md +30 -0
- forcomebot-2.2.4/web/node_modules/uncontrollable/LICENSE +21 -0
- forcomebot-2.2.4/web/node_modules/uncontrollable/README.md +146 -0
- forcomebot-2.2.4/web/node_modules/warning/README.md +69 -0
- forcomebot-2.2.3/src/clients/qianxun.py +0 -678
- forcomebot-2.2.3/src/web.py +0 -257
- {forcomebot-2.2.3 → forcomebot-2.2.4}/.gitignore +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/__main__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/api/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/api/websocket.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/clients/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/clients/langbot.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/core/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/core/log_collector.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/core/message_queue.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/handlers/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/handlers/message_parser.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/models.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/static/assets/index-B4i68B5_.js +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/static/assets/index-BPXisDkw.css +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/static/index.html +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/static/vite.svg +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/utils/__init__.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/utils/text_processor.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/src/utils/xml_parser.py +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/code-frame/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/code-frame/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/compat-data/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/compat-data/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/core/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/generator/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/generator/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-compilation-targets/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-compilation-targets/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-globals/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-globals/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-module-imports/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-module-imports/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-module-transforms/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-module-transforms/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-plugin-utils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-plugin-utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-string-parser/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-string-parser/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-validator-identifier/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-validator-identifier/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-validator-option/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helper-validator-option/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helpers/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/helpers/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/parser/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/parser/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/plugin-transform-react-jsx-self/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/plugin-transform-react-jsx-self/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/plugin-transform-react-jsx-source/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/plugin-transform-react-jsx-source/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@babel/template → forcomebot-2.2.4/web/node_modules/@babel/runtime}/LICENSE +0 -0
- {forcomebot-2.2.3/web/node_modules/@babel/traverse → forcomebot-2.2.4/web/node_modules/@babel/template}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/template/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@babel/types → forcomebot-2.2.4/web/node_modules/@babel/traverse}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/traverse/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@babel/types/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/core/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/runtime/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/runtime/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/wasi-threads/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@emnapi/wasi-threads/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/config-array/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/config-array/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/config-helpers/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/config-helpers/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/core/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/eslintrc/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/eslintrc/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/js/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/js/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/object-schema/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/object-schema/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/plugin-kit/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint/plugin-kit/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/eslint-utils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/eslint-utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/regexpp/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@eslint-community/regexpp/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanfs/core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanfs/core/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanfs/node/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanfs/node/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanwhocodes/module-importer/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanwhocodes/module-importer/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanwhocodes/retry/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@humanwhocodes/retry/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/gen-mapping/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/gen-mapping/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/remapping/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/remapping/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/resolve-uri/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/resolve-uri/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/sourcemap-codec/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/sourcemap-codec/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/trace-mapping/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@jridgewell/trace-mapping/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@oxc-project/runtime/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@oxc-project/runtime/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@oxc-project/types/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@oxc-project/types/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@rolldown/binding-win32-x64-msvc/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@rolldown/pluginutils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@rolldown/pluginutils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/node/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/node/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/oxide/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/oxide-win32-x64-msvc/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/oxide-win32-x64-msvc/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/vite/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tailwindcss/vite/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tanstack/query-core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tanstack/react-query/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tanstack/react-query/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@tybys/wasm-util/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__core/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__core/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__generator/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__generator/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__template/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__template/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__traverse/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/babel__traverse/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@types/estree → forcomebot-2.2.4/web/node_modules/@types/date-arithmetic}/LICENSE +0 -0
- {forcomebot-2.2.3/web/node_modules/@types/json-schema → forcomebot-2.2.4/web/node_modules/@types/estree}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/estree/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@types/node → forcomebot-2.2.4/web/node_modules/@types/json-schema}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/json-schema/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@types/react-dom → forcomebot-2.2.4/web/node_modules/@types/node}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/node/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/@types/react → forcomebot-2.2.4/web/node_modules/@types/prop-types}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/react/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@types/react-dom/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/eslint-plugin/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/eslint-plugin/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/parser/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/parser/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/project-service/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/project-service/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/scope-manager/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/scope-manager/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/tsconfig-utils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/tsconfig-utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/type-utils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/type-utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/types/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/types/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/semver/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/typescript-estree/node_modules/semver/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/utils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/visitor-keys/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@typescript-eslint/visitor-keys/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@vitejs/plugin-react/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/@vitejs/plugin-react/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/acorn/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/acorn/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/acorn-jsx/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/acorn-jsx/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/ajv/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/ajv/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/argparse/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/argparse/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/asynckit/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/asynckit/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/axios/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/axios/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/balanced-match/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/baseline-browser-mapping/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/brace-expansion/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/brace-expansion/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/browserslist/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/browserslist/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/call-bind-apply-helpers/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/call-bind-apply-helpers/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/caniuse-lite/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/caniuse-lite/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/color-convert/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/color-convert/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/color-name/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/color-name/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/concat-map/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/convert-source-map/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/convert-source-map/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/cookie/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/cookie/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/cross-spawn/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/cross-spawn/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/csstype/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/csstype/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/debug/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/debug/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/deep-is/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/detect-libc/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/detect-libc/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/dunder-proto/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/dunder-proto/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/electron-to-chromium/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/electron-to-chromium/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/enhanced-resolve/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/enhanced-resolve/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-define-property/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-define-property/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-errors/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-errors/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-object-atoms/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-object-atoms/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-set-tostringtag/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/es-set-tostringtag/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-plugin-react-hooks/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-plugin-react-hooks/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-plugin-react-refresh/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-plugin-react-refresh/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-scope/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-scope/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-visitor-keys/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/eslint-visitor-keys/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/espree/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/espree/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/esquery/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/esrecurse/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/estraverse/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/esutils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fast-deep-equal/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fast-deep-equal/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fast-json-stable-stringify/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fast-json-stable-stringify/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fast-levenshtein/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fdir/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/fdir/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/file-entry-cache/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/file-entry-cache/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/flat-cache/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/flat-cache/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/flatted/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/flatted/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/follow-redirects/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/follow-redirects/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/form-data/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/function-bind/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/function-bind/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/gensync/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/gensync/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/get-intrinsic/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/get-intrinsic/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/get-proto/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/get-proto/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/glob-parent/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/glob-parent/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/gopd/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/gopd/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/graceful-fs/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/graceful-fs/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/has-symbols/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/has-symbols/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/has-tostringtag/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/has-tostringtag/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hasown/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hasown/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hermes-estree/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hermes-estree/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hermes-parser/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/hermes-parser/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/ignore/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/imurmurhash/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/is-extglob/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/is-extglob/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/is-glob/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/is-glob/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/isexe/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/isexe/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/jiti/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/jiti/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/js-tokens/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/js-tokens/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/js-yaml/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/js-yaml/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/jsesc/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json-buffer/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json-buffer/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json-schema-traverse/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json-schema-traverse/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json-stable-stringify-without-jsonify/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/json5/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/keyv/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/levn/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/levn/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lightningcss/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lightningcss/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lightningcss-win32-x64-msvc/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lightningcss-win32-x64-msvc/README.md +0 -0
- {forcomebot-2.2.3/web/node_modules/lodash.merge → forcomebot-2.2.4/web/node_modules/lodash-es}/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lodash.merge/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lru-cache/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/lru-cache/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/magic-string/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/magic-string/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/math-intrinsics/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/math-intrinsics/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/mime-db/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/mime-db/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/mime-types/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/mime-types/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/minimatch/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/minimatch/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/nanoid/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/nanoid/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/natural-compare/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/node-releases/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/node-releases/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/optionator/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/optionator/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/picocolors/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/picocolors/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/picomatch/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/picomatch/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/postcss/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/postcss/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/prelude-ls/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/prelude-ls/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/proxy-from-env/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/proxy-from-env/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/punycode/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-dom/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-dom/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-refresh/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-refresh/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-router/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/react-router-dom/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/rolldown/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/rolldown/node_modules/@rolldown/pluginutils/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/rolldown/node_modules/@rolldown/pluginutils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/scheduler/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/scheduler/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/semver/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/semver/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/set-cookie-parser/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/set-cookie-parser/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/source-map-js/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/source-map-js/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tailwindcss/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tailwindcss/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tapable/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tapable/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tinyglobby/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tinyglobby/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/ts-api-utils/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/tslib/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/type-check/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/type-check/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/typescript/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/typescript-eslint/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/typescript-eslint/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/undici-types/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/undici-types/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/update-browserslist-db/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/update-browserslist-db/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/uri-js/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/uri-js/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/vite/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/which/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/which/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/word-wrap/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/word-wrap/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/yallist/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/yallist/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/zod/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/zod/README.md +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/zod-validation-error/LICENSE +0 -0
- {forcomebot-2.2.3 → forcomebot-2.2.4}/web/node_modules/zod-validation-error/README.md +0 -0
|
@@ -5,6 +5,19 @@ server:
|
|
|
5
5
|
host: "0.0.0.0"
|
|
6
6
|
port: 789
|
|
7
7
|
|
|
8
|
+
# 认证配置
|
|
9
|
+
auth:
|
|
10
|
+
enabled: false # 是否启用认证(false时所有API无需登录)
|
|
11
|
+
jwt_secret: "your-jwt-secret-key-change-in-production" # JWT密钥(生产环境请修改)
|
|
12
|
+
jwt_expire_hours: 24 # Token过期时间(小时)
|
|
13
|
+
|
|
14
|
+
# 钉钉配置(启用认证时需要配置)
|
|
15
|
+
dingtalk:
|
|
16
|
+
app_key: "" # 钉钉应用AppKey
|
|
17
|
+
app_secret: "" # 钉钉应用AppSecret
|
|
18
|
+
corp_id: "" # 企业CorpId
|
|
19
|
+
agent_id: "" # 应用AgentId(工作台应用需要)
|
|
20
|
+
|
|
8
21
|
# 千寻框架配置
|
|
9
22
|
qianxun:
|
|
10
23
|
# 千寻框架HTTP API地址
|
|
@@ -696,3 +696,80 @@ async def broadcast_applet(data: BroadcastAppletRequest):
|
|
|
696
696
|
"message_ids": message_ids,
|
|
697
697
|
"message": f"已将 {len(data.targets)} 条消息加入发送队列"
|
|
698
698
|
}
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
# ============ 节假日API ============
|
|
702
|
+
|
|
703
|
+
# 尝试导入中国节假日库
|
|
704
|
+
try:
|
|
705
|
+
import chinese_calendar
|
|
706
|
+
HAS_CHINESE_CALENDAR = True
|
|
707
|
+
except ImportError:
|
|
708
|
+
HAS_CHINESE_CALENDAR = False
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
@router.get("/holidays/{year}")
|
|
712
|
+
async def get_holidays(year: int):
|
|
713
|
+
"""获取指定年份的中国法定节假日列表
|
|
714
|
+
|
|
715
|
+
Args:
|
|
716
|
+
year: 年份,如 2026
|
|
717
|
+
|
|
718
|
+
Returns:
|
|
719
|
+
{
|
|
720
|
+
"year": 2026,
|
|
721
|
+
"holidays": ["2026-01-01", "2026-01-28", ...], # 节假日列表
|
|
722
|
+
"workdays": ["2026-01-25", ...], # 调休补班日列表
|
|
723
|
+
"available": true # 是否有节假日数据
|
|
724
|
+
}
|
|
725
|
+
"""
|
|
726
|
+
if not HAS_CHINESE_CALENDAR:
|
|
727
|
+
return {
|
|
728
|
+
"year": year,
|
|
729
|
+
"holidays": [],
|
|
730
|
+
"workdays": [],
|
|
731
|
+
"available": False,
|
|
732
|
+
"error": "chinese-calendar 库未安装"
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
try:
|
|
736
|
+
from datetime import date, timedelta
|
|
737
|
+
|
|
738
|
+
holidays: List[str] = []
|
|
739
|
+
workdays: List[str] = []
|
|
740
|
+
|
|
741
|
+
# 遍历全年每一天
|
|
742
|
+
start_date = date(year, 1, 1)
|
|
743
|
+
end_date = date(year, 12, 31)
|
|
744
|
+
current = start_date
|
|
745
|
+
|
|
746
|
+
while current <= end_date:
|
|
747
|
+
try:
|
|
748
|
+
is_holiday = chinese_calendar.is_holiday(current)
|
|
749
|
+
is_workday = chinese_calendar.is_workday(current)
|
|
750
|
+
weekday = current.weekday()
|
|
751
|
+
|
|
752
|
+
if is_holiday:
|
|
753
|
+
holidays.append(current.isoformat())
|
|
754
|
+
elif is_workday and weekday >= 5:
|
|
755
|
+
# 周末但是工作日 = 调休补班
|
|
756
|
+
workdays.append(current.isoformat())
|
|
757
|
+
except Exception:
|
|
758
|
+
pass
|
|
759
|
+
current += timedelta(days=1)
|
|
760
|
+
|
|
761
|
+
return {
|
|
762
|
+
"year": year,
|
|
763
|
+
"holidays": holidays,
|
|
764
|
+
"workdays": workdays,
|
|
765
|
+
"available": True
|
|
766
|
+
}
|
|
767
|
+
except Exception as e:
|
|
768
|
+
logger.error(f"获取节假日数据失败: {e}")
|
|
769
|
+
return {
|
|
770
|
+
"year": year,
|
|
771
|
+
"holidays": [],
|
|
772
|
+
"workdays": [],
|
|
773
|
+
"available": False,
|
|
774
|
+
"error": str(e)
|
|
775
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""认证模块"""
|
|
2
|
+
from .database import Database, get_db, init_database
|
|
3
|
+
from .models import User, OperationLog
|
|
4
|
+
from .jwt_handler import JWTHandler
|
|
5
|
+
from .dingtalk import DingTalkClient, init_dingtalk_client, get_dingtalk_client
|
|
6
|
+
from .middleware import (
|
|
7
|
+
AuthMiddleware,
|
|
8
|
+
get_current_user,
|
|
9
|
+
get_optional_user,
|
|
10
|
+
init_auth,
|
|
11
|
+
is_auth_enabled,
|
|
12
|
+
log_operation
|
|
13
|
+
)
|
|
14
|
+
from .routes import router as auth_router
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"Database",
|
|
18
|
+
"get_db",
|
|
19
|
+
"init_database",
|
|
20
|
+
"User",
|
|
21
|
+
"OperationLog",
|
|
22
|
+
"JWTHandler",
|
|
23
|
+
"DingTalkClient",
|
|
24
|
+
"init_dingtalk_client",
|
|
25
|
+
"get_dingtalk_client",
|
|
26
|
+
"AuthMiddleware",
|
|
27
|
+
"get_current_user",
|
|
28
|
+
"get_optional_user",
|
|
29
|
+
"init_auth",
|
|
30
|
+
"is_auth_enabled",
|
|
31
|
+
"log_operation",
|
|
32
|
+
"auth_router",
|
|
33
|
+
]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""数据库连接管理"""
|
|
2
|
+
import logging
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import AsyncGenerator
|
|
5
|
+
|
|
6
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
|
7
|
+
from sqlalchemy.orm import DeclarativeBase
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Base(DeclarativeBase):
|
|
13
|
+
"""SQLAlchemy 基类"""
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Database:
|
|
18
|
+
"""数据库管理器"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, db_path: str = "data/app.db"):
|
|
21
|
+
self.db_path = db_path
|
|
22
|
+
self.engine = None
|
|
23
|
+
self.session_factory = None
|
|
24
|
+
|
|
25
|
+
async def init(self):
|
|
26
|
+
"""初始化数据库连接"""
|
|
27
|
+
# 确保目录存在
|
|
28
|
+
Path(self.db_path).parent.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
|
|
30
|
+
# 创建异步引擎
|
|
31
|
+
self.engine = create_async_engine(
|
|
32
|
+
f"sqlite+aiosqlite:///{self.db_path}",
|
|
33
|
+
echo=False,
|
|
34
|
+
future=True
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# 创建会话工厂
|
|
38
|
+
self.session_factory = async_sessionmaker(
|
|
39
|
+
self.engine,
|
|
40
|
+
class_=AsyncSession,
|
|
41
|
+
expire_on_commit=False
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# 创建表
|
|
45
|
+
async with self.engine.begin() as conn:
|
|
46
|
+
from .models import User, OperationLog # 导入模型以注册
|
|
47
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
48
|
+
|
|
49
|
+
logger.info(f"数据库初始化完成: {self.db_path}")
|
|
50
|
+
|
|
51
|
+
async def close(self):
|
|
52
|
+
"""关闭数据库连接"""
|
|
53
|
+
if self.engine:
|
|
54
|
+
await self.engine.dispose()
|
|
55
|
+
logger.info("数据库连接已关闭")
|
|
56
|
+
|
|
57
|
+
async def get_session(self) -> AsyncGenerator[AsyncSession, None]:
|
|
58
|
+
"""获取数据库会话"""
|
|
59
|
+
if not self.session_factory:
|
|
60
|
+
raise RuntimeError("数据库未初始化")
|
|
61
|
+
|
|
62
|
+
async with self.session_factory() as session:
|
|
63
|
+
try:
|
|
64
|
+
yield session
|
|
65
|
+
await session.commit()
|
|
66
|
+
except Exception:
|
|
67
|
+
await session.rollback()
|
|
68
|
+
raise
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# 全局数据库实例
|
|
72
|
+
_database: Database = None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
async def init_database(db_path: str = "data/app.db") -> Database:
|
|
76
|
+
"""初始化全局数据库实例"""
|
|
77
|
+
global _database
|
|
78
|
+
_database = Database(db_path)
|
|
79
|
+
await _database.init()
|
|
80
|
+
return _database
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_db() -> Database:
|
|
84
|
+
"""获取全局数据库实例"""
|
|
85
|
+
if _database is None:
|
|
86
|
+
raise RuntimeError("数据库未初始化,请先调用 init_database()")
|
|
87
|
+
return _database
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
"""钉钉API客户端"""
|
|
2
|
+
import logging
|
|
3
|
+
import time
|
|
4
|
+
from typing import Optional, Dict, Any
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DingTalkClient:
|
|
12
|
+
"""钉钉开放平台API客户端"""
|
|
13
|
+
|
|
14
|
+
# API基础地址
|
|
15
|
+
BASE_URL = "https://oapi.dingtalk.com"
|
|
16
|
+
NEW_API_URL = "https://api.dingtalk.com"
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
app_key: str,
|
|
21
|
+
app_secret: str,
|
|
22
|
+
corp_id: str = "",
|
|
23
|
+
agent_id: str = ""
|
|
24
|
+
):
|
|
25
|
+
"""
|
|
26
|
+
初始化钉钉客户端
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
app_key: 应用AppKey
|
|
30
|
+
app_secret: 应用AppSecret
|
|
31
|
+
corp_id: 企业CorpId(工作台免登需要)
|
|
32
|
+
agent_id: 应用AgentId(工作台免登需要)
|
|
33
|
+
"""
|
|
34
|
+
self.app_key = app_key
|
|
35
|
+
self.app_secret = app_secret
|
|
36
|
+
self.corp_id = corp_id
|
|
37
|
+
self.agent_id = agent_id
|
|
38
|
+
|
|
39
|
+
# Access Token缓存
|
|
40
|
+
self._access_token: Optional[str] = None
|
|
41
|
+
self._token_expire_time: float = 0
|
|
42
|
+
|
|
43
|
+
# HTTP客户端
|
|
44
|
+
self._client = httpx.AsyncClient(timeout=30.0)
|
|
45
|
+
|
|
46
|
+
async def close(self):
|
|
47
|
+
"""关闭HTTP客户端"""
|
|
48
|
+
await self._client.aclose()
|
|
49
|
+
|
|
50
|
+
async def get_access_token(self) -> str:
|
|
51
|
+
"""
|
|
52
|
+
获取企业内部应用的Access Token
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Access Token字符串
|
|
56
|
+
"""
|
|
57
|
+
# 检查缓存
|
|
58
|
+
if self._access_token and time.time() < self._token_expire_time - 60:
|
|
59
|
+
return self._access_token
|
|
60
|
+
|
|
61
|
+
# 请求新Token
|
|
62
|
+
url = f"{self.BASE_URL}/gettoken"
|
|
63
|
+
params = {
|
|
64
|
+
"appkey": self.app_key,
|
|
65
|
+
"appsecret": self.app_secret
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
response = await self._client.get(url, params=params)
|
|
70
|
+
data = response.json()
|
|
71
|
+
|
|
72
|
+
if data.get("errcode") == 0:
|
|
73
|
+
self._access_token = data["access_token"]
|
|
74
|
+
# Token有效期7200秒
|
|
75
|
+
self._token_expire_time = time.time() + data.get("expires_in", 7200)
|
|
76
|
+
logger.info("获取钉钉Access Token成功")
|
|
77
|
+
return self._access_token
|
|
78
|
+
else:
|
|
79
|
+
logger.error(f"获取钉钉Access Token失败: {data}")
|
|
80
|
+
raise Exception(f"获取Access Token失败: {data.get('errmsg')}")
|
|
81
|
+
except Exception as e:
|
|
82
|
+
logger.error(f"请求钉钉API异常: {e}")
|
|
83
|
+
raise
|
|
84
|
+
|
|
85
|
+
async def get_user_info_by_code(self, auth_code: str) -> Dict[str, Any]:
|
|
86
|
+
"""
|
|
87
|
+
通过授权码获取用户信息(新版OAuth2扫码登录)
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
auth_code: 授权码
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
用户信息字典
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
# 1. 通过授权码获取用户access_token(新版OAuth2 API)
|
|
97
|
+
url = f"{self.NEW_API_URL}/v1.0/oauth2/userAccessToken"
|
|
98
|
+
body = {
|
|
99
|
+
"clientId": self.app_key,
|
|
100
|
+
"clientSecret": self.app_secret,
|
|
101
|
+
"code": auth_code,
|
|
102
|
+
"grantType": "authorization_code"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
response = await self._client.post(url, json=body)
|
|
106
|
+
data = response.json()
|
|
107
|
+
|
|
108
|
+
if "accessToken" not in data:
|
|
109
|
+
logger.error(f"获取用户Token失败: {data}")
|
|
110
|
+
raise Exception(f"获取用户Token失败: {data.get('message', data)}")
|
|
111
|
+
|
|
112
|
+
user_access_token = data["accessToken"]
|
|
113
|
+
logger.info("获取用户access_token成功")
|
|
114
|
+
|
|
115
|
+
# 2. 使用用户access_token获取用户信息
|
|
116
|
+
user_info_url = f"{self.NEW_API_URL}/v1.0/contact/users/me"
|
|
117
|
+
headers = {"x-acs-dingtalk-access-token": user_access_token}
|
|
118
|
+
|
|
119
|
+
user_response = await self._client.get(user_info_url, headers=headers)
|
|
120
|
+
user_data = user_response.json()
|
|
121
|
+
|
|
122
|
+
if "unionId" not in user_data:
|
|
123
|
+
logger.error(f"获取用户信息失败: {user_data}")
|
|
124
|
+
raise Exception(f"获取用户信息失败: {user_data.get('message', user_data)}")
|
|
125
|
+
|
|
126
|
+
unionid = user_data.get("unionId")
|
|
127
|
+
logger.info(f"获取用户信息成功: unionId={unionid}")
|
|
128
|
+
|
|
129
|
+
# 3. 通过unionId获取企业内用户userid
|
|
130
|
+
userid = await self.get_userid_by_unionid(unionid)
|
|
131
|
+
|
|
132
|
+
if userid:
|
|
133
|
+
# 获取企业内用户详细信息
|
|
134
|
+
user_detail = await self.get_user_detail(userid)
|
|
135
|
+
return {
|
|
136
|
+
"userid": userid,
|
|
137
|
+
"unionid": unionid,
|
|
138
|
+
"name": user_detail.get("name", user_data.get("nick", "")),
|
|
139
|
+
"avatar": user_detail.get("avatar", user_data.get("avatarUrl", "")),
|
|
140
|
+
"mobile": user_detail.get("mobile", user_data.get("mobile", "")),
|
|
141
|
+
"email": user_detail.get("email", user_data.get("email", "")),
|
|
142
|
+
"department": self._format_department(user_detail.get("dept_id_list", [])),
|
|
143
|
+
"title": user_detail.get("title", ""),
|
|
144
|
+
}
|
|
145
|
+
else:
|
|
146
|
+
# 非企业内用户,使用OAuth返回的基本信息
|
|
147
|
+
return {
|
|
148
|
+
"userid": user_data.get("openId", unionid),
|
|
149
|
+
"unionid": unionid,
|
|
150
|
+
"name": user_data.get("nick", ""),
|
|
151
|
+
"avatar": user_data.get("avatarUrl", ""),
|
|
152
|
+
"mobile": user_data.get("mobile", ""),
|
|
153
|
+
"email": user_data.get("email", ""),
|
|
154
|
+
"department": "",
|
|
155
|
+
"title": "",
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.error(f"通过授权码获取用户信息异常: {e}")
|
|
160
|
+
raise
|
|
161
|
+
|
|
162
|
+
async def get_user_info_by_code_internal(self, auth_code: str) -> Dict[str, Any]:
|
|
163
|
+
"""
|
|
164
|
+
通过免登授权码获取用户信息(企业内部应用/H5免登)
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
auth_code: 免登授权码(通过钉钉JSAPI获取)
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
用户信息字典
|
|
171
|
+
"""
|
|
172
|
+
access_token = await self.get_access_token()
|
|
173
|
+
|
|
174
|
+
# 通过免登授权码获取用户userid
|
|
175
|
+
url = f"{self.BASE_URL}/topapi/v2/user/getuserinfo"
|
|
176
|
+
params = {"access_token": access_token}
|
|
177
|
+
body = {"code": auth_code}
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
response = await self._client.post(url, params=params, json=body)
|
|
181
|
+
data = response.json()
|
|
182
|
+
|
|
183
|
+
if data.get("errcode") != 0:
|
|
184
|
+
logger.error(f"获取用户信息失败: {data}")
|
|
185
|
+
raise Exception(f"获取用户信息失败: {data.get('errmsg')}")
|
|
186
|
+
|
|
187
|
+
result = data.get("result", {})
|
|
188
|
+
userid = result.get("userid")
|
|
189
|
+
unionid = result.get("unionid")
|
|
190
|
+
|
|
191
|
+
if not userid:
|
|
192
|
+
raise Exception("未获取到用户userid")
|
|
193
|
+
|
|
194
|
+
# 获取用户详细信息
|
|
195
|
+
user_detail = await self.get_user_detail(userid)
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
"userid": userid,
|
|
199
|
+
"unionid": unionid,
|
|
200
|
+
"name": user_detail.get("name", ""),
|
|
201
|
+
"avatar": user_detail.get("avatar", ""),
|
|
202
|
+
"mobile": user_detail.get("mobile", ""),
|
|
203
|
+
"email": user_detail.get("email", ""),
|
|
204
|
+
"department": self._format_department(user_detail.get("dept_id_list", [])),
|
|
205
|
+
"title": user_detail.get("title", ""),
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
except Exception as e:
|
|
209
|
+
logger.error(f"通过免登授权码获取用户信息异常: {e}")
|
|
210
|
+
raise
|
|
211
|
+
|
|
212
|
+
async def get_user_detail(self, userid: str) -> Dict[str, Any]:
|
|
213
|
+
"""
|
|
214
|
+
获取用户详细信息
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
userid: 用户ID
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
用户详细信息
|
|
221
|
+
"""
|
|
222
|
+
access_token = await self.get_access_token()
|
|
223
|
+
|
|
224
|
+
url = f"{self.BASE_URL}/topapi/v2/user/get"
|
|
225
|
+
params = {"access_token": access_token}
|
|
226
|
+
body = {"userid": userid}
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
response = await self._client.post(url, params=params, json=body)
|
|
230
|
+
data = response.json()
|
|
231
|
+
|
|
232
|
+
if data.get("errcode") != 0:
|
|
233
|
+
logger.error(f"获取用户详情失败: {data}")
|
|
234
|
+
raise Exception(f"获取用户详情失败: {data.get('errmsg')}")
|
|
235
|
+
|
|
236
|
+
return data.get("result", {})
|
|
237
|
+
|
|
238
|
+
except Exception as e:
|
|
239
|
+
logger.error(f"获取用户详情异常: {e}")
|
|
240
|
+
raise
|
|
241
|
+
|
|
242
|
+
async def get_userid_by_unionid(self, unionid: str) -> Optional[str]:
|
|
243
|
+
"""
|
|
244
|
+
通过UnionId获取UserId
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
unionid: 用户UnionId
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
用户UserId
|
|
251
|
+
"""
|
|
252
|
+
access_token = await self.get_access_token()
|
|
253
|
+
|
|
254
|
+
url = f"{self.BASE_URL}/topapi/user/getbyunionid"
|
|
255
|
+
params = {"access_token": access_token}
|
|
256
|
+
body = {"unionid": unionid}
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
response = await self._client.post(url, params=params, json=body)
|
|
260
|
+
data = response.json()
|
|
261
|
+
|
|
262
|
+
if data.get("errcode") != 0:
|
|
263
|
+
logger.warning(f"通过UnionId获取UserId失败: {data}")
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
return data.get("result", {}).get("userid")
|
|
267
|
+
|
|
268
|
+
except Exception as e:
|
|
269
|
+
logger.error(f"通过UnionId获取UserId异常: {e}")
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
async def get_jsapi_ticket(self) -> str:
|
|
273
|
+
"""
|
|
274
|
+
获取JSAPI Ticket(H5页面调用钉钉JS API需要)
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
JSAPI Ticket
|
|
278
|
+
"""
|
|
279
|
+
access_token = await self.get_access_token()
|
|
280
|
+
|
|
281
|
+
url = f"{self.BASE_URL}/get_jsapi_ticket"
|
|
282
|
+
params = {"access_token": access_token}
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
response = await self._client.get(url, params=params)
|
|
286
|
+
data = response.json()
|
|
287
|
+
|
|
288
|
+
if data.get("errcode") != 0:
|
|
289
|
+
logger.error(f"获取JSAPI Ticket失败: {data}")
|
|
290
|
+
raise Exception(f"获取JSAPI Ticket失败: {data.get('errmsg')}")
|
|
291
|
+
|
|
292
|
+
return data.get("ticket", "")
|
|
293
|
+
|
|
294
|
+
except Exception as e:
|
|
295
|
+
logger.error(f"获取JSAPI Ticket异常: {e}")
|
|
296
|
+
raise
|
|
297
|
+
|
|
298
|
+
def _format_department(self, dept_ids: list) -> str:
|
|
299
|
+
"""格式化部门信息"""
|
|
300
|
+
if not dept_ids:
|
|
301
|
+
return ""
|
|
302
|
+
# 简单返回部门ID列表,实际可以查询部门名称
|
|
303
|
+
return ",".join(str(d) for d in dept_ids)
|
|
304
|
+
|
|
305
|
+
def generate_qrcode_url(self, redirect_uri: str, state: str = "") -> str:
|
|
306
|
+
"""
|
|
307
|
+
生成钉钉扫码登录URL(新版OAuth2)
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
redirect_uri: 回调地址
|
|
311
|
+
state: 状态参数
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
扫码登录URL
|
|
315
|
+
"""
|
|
316
|
+
import urllib.parse
|
|
317
|
+
|
|
318
|
+
params = {
|
|
319
|
+
"client_id": self.app_key,
|
|
320
|
+
"response_type": "code",
|
|
321
|
+
"scope": "openid",
|
|
322
|
+
"redirect_uri": redirect_uri,
|
|
323
|
+
"state": state or "dingtalk_login",
|
|
324
|
+
"prompt": "consent"
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
query = urllib.parse.urlencode(params)
|
|
328
|
+
return f"https://login.dingtalk.com/oauth2/auth?{query}"
|
|
329
|
+
|
|
330
|
+
def generate_h5_auth_url(self, redirect_uri: str, state: str = "") -> str:
|
|
331
|
+
"""
|
|
332
|
+
生成H5页面授权URL(用于钉钉内H5应用)
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
redirect_uri: 回调地址
|
|
336
|
+
state: 状态参数
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
H5授权URL
|
|
340
|
+
"""
|
|
341
|
+
import urllib.parse
|
|
342
|
+
|
|
343
|
+
params = {
|
|
344
|
+
"appid": self.app_key,
|
|
345
|
+
"response_type": "code",
|
|
346
|
+
"scope": "snsapi_auth",
|
|
347
|
+
"redirect_uri": redirect_uri,
|
|
348
|
+
"state": state or "dingtalk_h5"
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
query = urllib.parse.urlencode(params)
|
|
352
|
+
return f"https://login.dingtalk.com/oauth2/auth?{query}"
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
# 全局客户端实例
|
|
356
|
+
_dingtalk_client: Optional[DingTalkClient] = None
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def init_dingtalk_client(
|
|
360
|
+
app_key: str,
|
|
361
|
+
app_secret: str,
|
|
362
|
+
corp_id: str = "",
|
|
363
|
+
agent_id: str = ""
|
|
364
|
+
) -> DingTalkClient:
|
|
365
|
+
"""初始化全局钉钉客户端"""
|
|
366
|
+
global _dingtalk_client
|
|
367
|
+
_dingtalk_client = DingTalkClient(app_key, app_secret, corp_id, agent_id)
|
|
368
|
+
return _dingtalk_client
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def get_dingtalk_client() -> Optional[DingTalkClient]:
|
|
372
|
+
"""获取全局钉钉客户端"""
|
|
373
|
+
return _dingtalk_client
|