mirror of
https://git.victorphan.net/basketballcantho/zalo-monitor.git
synced 2026-08-05 06:13:10 +07:00
init
This commit is contained in:
+41
@@ -0,0 +1,41 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -0,0 +1,5 @@
|
||||
<!-- BEGIN:nextjs-agent-rules -->
|
||||
# This is NOT the Next.js you know
|
||||
|
||||
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
|
||||
<!-- END:nextjs-agent-rules -->
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: CI/CD
|
||||
about: Report issues with CI/CD pipeline or suggest improvements
|
||||
title: "[CI/CD]"
|
||||
labels: ci-cd
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the CI/CD issue**
|
||||
A clear and concise description of the CI/CD problem.
|
||||
|
||||
**Current pipeline behavior**
|
||||
Describe what's happening in the current pipeline.
|
||||
|
||||
**Expected pipeline behavior**
|
||||
Describe what should happen in the pipeline.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the CI/CD issue here.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
---
|
||||
name: Code of Conduct Violation
|
||||
about: Report a violation of our Code of Conduct
|
||||
title: "[CONDUCT]"
|
||||
labels: ["CONDUCT", "community"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
## Code of Conduct Violation Report
|
||||
|
||||
**IMPORTANT**: This issue will be handled privately and with respect for all parties involved.
|
||||
|
||||
### Type of Violation
|
||||
<!-- Please select the type of violation -->
|
||||
- [ ] Harassment or bullying
|
||||
- [ ] Inappropriate language or behavior
|
||||
- [ ] Privacy violation (sharing personal information)
|
||||
- [ ] Spam or trolling
|
||||
- [ ] Discrimination
|
||||
- [ ] Other (please describe)
|
||||
|
||||
### Description
|
||||
<!-- Please provide a clear and detailed description of the incident -->
|
||||
|
||||
### When did this occur?
|
||||
<!-- Date and time if known -->
|
||||
|
||||
### Where did this occur?
|
||||
<!-- Please specify where the incident took place -->
|
||||
- [ ] GitHub Issues
|
||||
- [ ] GitHub Discussions
|
||||
- [ ] GitHub Pull Requests
|
||||
- [ ] GitHub Comments
|
||||
- [ ] External communication (Discord, email, etc.)
|
||||
- [ ] Other (please specify)
|
||||
|
||||
### People Involved
|
||||
<!-- Please list the usernames of people involved (if known) -->
|
||||
|
||||
### Evidence
|
||||
<!-- Please provide any relevant links, screenshots, or other evidence -->
|
||||
<!-- You can drag and drop images here -->
|
||||
|
||||
### Impact
|
||||
<!-- How did this incident affect you or the community? -->
|
||||
|
||||
### Additional Context
|
||||
<!-- Any additional information that might be helpful -->
|
||||
|
||||
### Preferred Resolution
|
||||
<!-- What would you like to see happen? (optional) -->
|
||||
|
||||
---
|
||||
|
||||
**Note**: This report will be reviewed by the team and handled according to our [Code of Conduct](https://github.com/RFS-ADRENO/zca-js/blob/main/CODE_OF_CONDUCT.md). We are committed to maintaining a safe and welcoming community for everyone.
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FEAT]"
|
||||
labels: enhancement
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Help Wanted request
|
||||
about: Ask for help with something
|
||||
title: "[HELP]"
|
||||
labels: help wanted
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is your help wanted request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I need help with a problem [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the help wanted request here.
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Performance
|
||||
about: Report performance issues or suggest optimizations
|
||||
title: "[PERF]"
|
||||
labels: performance
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the performance issue**
|
||||
A clear and concise description of the performance problem.
|
||||
|
||||
**Current behavior**
|
||||
Describe the current performance metrics or behavior.
|
||||
|
||||
**Expected behavior**
|
||||
Describe what performance you expect to see.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the performance issue here.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Question
|
||||
about: Questions arising during use.
|
||||
title: "[Question] Some question..."
|
||||
labels: question
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Ask the questions you want!**
|
||||
A clear and concise question about what. Ex. When to use API [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the question here.
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
name: Security Vulnerability Report
|
||||
about: Report a security vulnerability
|
||||
title: "[SECURITY]"
|
||||
labels: security
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
## Security Vulnerability Report
|
||||
|
||||
**IMPORTANT**: This issue will be handled privately and with the highest priority. Please do not disclose details publicly until the issue is resolved.
|
||||
|
||||
### Vulnerability Type
|
||||
<!-- Please select the type of vulnerability -->
|
||||
- [ ] Authentication bypass
|
||||
- [ ] Data exposure/information disclosure
|
||||
- [ ] Code injection
|
||||
- [ ] Cross-site scripting (XSS)
|
||||
- [ ] Cross-site request forgery (CSRF)
|
||||
- [ ] Denial of service (DoS)
|
||||
- [ ] Privilege escalation
|
||||
- [ ] Dependency vulnerability
|
||||
- [ ] Other (please describe)
|
||||
|
||||
### Severity Level
|
||||
<!-- Please assess the severity -->
|
||||
- [ ] Critical (immediate action required)
|
||||
- [ ] High (action required within 24 hours)
|
||||
- [ ] Medium (action required within 1 week)
|
||||
- [ ] Low (action required within 1 month)
|
||||
|
||||
### Description
|
||||
<!-- Please provide a clear and detailed description of the vulnerability -->
|
||||
|
||||
### Steps to Reproduce
|
||||
<!-- Please provide clear steps to reproduce the vulnerability -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Expected Behavior
|
||||
<!-- What should happen normally? -->
|
||||
|
||||
### Actual Behavior
|
||||
<!-- What actually happens due to the vulnerability? -->
|
||||
|
||||
### Environment
|
||||
<!-- Please provide details about the environment -->
|
||||
- **zca-js Version**:
|
||||
- **Node.js Version**:
|
||||
- **Operating System**:
|
||||
- **Browser** (if applicable):
|
||||
|
||||
### Impact Assessment
|
||||
<!-- What is the potential impact of this vulnerability? -->
|
||||
- **Data at Risk**:
|
||||
- **Users Affected**:
|
||||
- **Business Impact**:
|
||||
|
||||
### Suggested Fix
|
||||
<!-- Do you have any suggestions for fixing this vulnerability? (optional) -->
|
||||
|
||||
### Additional Information
|
||||
<!-- Any additional context, logs, or evidence -->
|
||||
<!-- You can drag and drop files here -->
|
||||
|
||||
### Disclosure Timeline
|
||||
<!-- When do you plan to disclose this publicly? (if applicable) -->
|
||||
|
||||
---
|
||||
|
||||
**Note**: This report will be reviewed by the security team and handled according to our [Security Policy](https://github.com/RFS-ADRENO/zca-js/blob/main/SECURITY.md). We appreciate your responsible disclosure and will work to resolve this issue promptly.
|
||||
|
||||
**⚠️ Warning**: This is an unofficial API library. Please ensure your testing does not violate Zalo's terms of service or put any accounts at risk.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Testing
|
||||
about: Report testing issues or suggest test improvements
|
||||
title: "[TEST]"
|
||||
labels: testing
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the testing issue**
|
||||
A clear and concise description of the testing problem.
|
||||
|
||||
**Test case**
|
||||
Describe the test case that's failing or needs improvement.
|
||||
|
||||
**Expected test result**
|
||||
Describe what the test should verify.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the testing issue here.
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
## What does this PR do?
|
||||
<!-- Briefly describe the changes you have made -->
|
||||
|
||||
## Reason for this PR
|
||||
<!-- Why is this change needed? -->
|
||||
|
||||
## How did you verify your code works?
|
||||
- [ ] All related features have been fully tested
|
||||
- [ ] Unit tests have been updated/created if needed
|
||||
- [ ] No lint/format errors
|
||||
- [ ] Documentation has been updated if needed
|
||||
- [ ] Code changes
|
||||
|
||||
## Related Issue (if any)
|
||||
<!-- Attach a link to the related issue or ticket -->
|
||||
|
||||
## Testing Instructions
|
||||
<!-- Provide instructions for reviewers to test this PR -->
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
name: lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "18.x"
|
||||
- run: npm install
|
||||
- run: npm run build:clean && npm run build:esm && npm run build:cjs
|
||||
- run: npm run lint
|
||||
@@ -0,0 +1,136 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
bun.lockb
|
||||
cookies.json
|
||||
credentials.json
|
||||
/.dev
|
||||
test/**/*.test.*
|
||||
@@ -0,0 +1 @@
|
||||
bunx lint-staged
|
||||
@@ -0,0 +1,15 @@
|
||||
.dev
|
||||
examples
|
||||
src
|
||||
test
|
||||
|
||||
bun.lockb
|
||||
bun.lock
|
||||
package-lock.json
|
||||
tsconfig.json
|
||||
|
||||
.husky
|
||||
.github
|
||||
.vscode
|
||||
|
||||
scripts
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"printWidth": 120,
|
||||
"semi": true
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib"
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
# Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement through:
|
||||
- **GitHub Issues**: Create a private issue with the `[CONDUCT]` label
|
||||
- **GitHub Discussions**: Use the "Community" category for general concerns
|
||||
- **Direct Contact**: Reach out to any team member through GitHub
|
||||
- **Team Members**:
|
||||
- [@RFS-ADRENO](https://github.com/RFS-ADRENO)
|
||||
- [@truong9c2208](https://github.com/truong9c2208)
|
||||
- [@JustKemForFun](https://github.com/JustKemForFun)
|
||||
|
||||
All complaints will be reviewed and investigated promptly and fairly by the team.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
||||
## Special Considerations for zca-js
|
||||
|
||||
Given that zca-js is an unofficial API library for Zalo, we have additional
|
||||
guidelines specific to our project:
|
||||
|
||||
### Responsible Usage
|
||||
|
||||
* **Respect Zalo's Terms of Service**: While this is an unofficial library,
|
||||
users should be aware of and respect Zalo's terms of service
|
||||
* **Account Safety**: Do not encourage or provide guidance on circumventing
|
||||
Zalo's security measures
|
||||
* **Privacy**: Respect user privacy and do not share personal information
|
||||
obtained through the API
|
||||
* **Rate Limiting**: Encourage responsible usage that doesn't overload Zalo's
|
||||
servers
|
||||
|
||||
### Technical Discussions
|
||||
|
||||
* **Security**: When discussing security-related topics, use appropriate
|
||||
channels and follow responsible disclosure practices
|
||||
* **Bugs and Issues**: Report bugs and issues through proper channels
|
||||
* **Documentation**: Help improve documentation and examples for the community
|
||||
|
||||
---
|
||||
|
||||
**Note**: This Code of Conduct is a living document and may be updated as our
|
||||
community grows and evolves.
|
||||
@@ -0,0 +1,470 @@
|
||||
# Contributing to zca-js
|
||||
|
||||
Thank you for your interest in contributing to zca-js! This project is maintained by the community and we welcome all contributions.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Development Setup](#development-setup)
|
||||
- [How to Contribute](#how-to-contribute)
|
||||
- [Pull Request Process](#pull-request-process)
|
||||
- [Code Style Guidelines](#code-style-guidelines)
|
||||
- [Testing Guidelines](#testing-guidelines)
|
||||
- [Documentation Guidelines](#documentation-guidelines)
|
||||
- [Security Guidelines](#security-guidelines)
|
||||
- [Release Process](#release-process)
|
||||
- [Getting Help](#getting-help)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project adheres to our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you agree to abide by these rules.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js >= 18.0.0
|
||||
- Bun (recommended) or npm
|
||||
- Git
|
||||
|
||||
### Fork and Clone
|
||||
|
||||
1. Fork this repository
|
||||
2. Clone your fork:
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/zca-js.git
|
||||
cd zca-js
|
||||
```
|
||||
3. Add upstream remote:
|
||||
```bash
|
||||
git remote add upstream https://github.com/RFS-ADRENO/zca-js.git
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
# Using Bun (recommended)
|
||||
bun install
|
||||
|
||||
# Or using npm
|
||||
npm install
|
||||
```
|
||||
|
||||
### Build Project
|
||||
|
||||
```bash
|
||||
# Build both ESM and CJS
|
||||
bun run build
|
||||
|
||||
# Build ESM only
|
||||
bun run build:esm
|
||||
|
||||
# Build CJS only
|
||||
bun run build:cjs
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
# Run feature tests
|
||||
bun run test:feat
|
||||
|
||||
# Run specific test file
|
||||
bun run test/test.ts
|
||||
```
|
||||
|
||||
### Code Formatting
|
||||
|
||||
```bash
|
||||
# Format code with Prettier
|
||||
bun run prettier
|
||||
```
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### Types of Contributions
|
||||
|
||||
We welcome the following types of contributions:
|
||||
|
||||
- 🐛 **Bug Reports**: Report bugs and issues
|
||||
- ✨ **Feature Requests**: Suggest new features
|
||||
- 🔧 **Code Contributions**: Fix bugs and add features
|
||||
- 📚 **Documentation**: Improve docs and examples
|
||||
- 🧪 **Tests**: Add or improve tests
|
||||
- 🔒 **Security**: Report security vulnerabilities
|
||||
- 🌐 **Translations**: Translate docs to other languages
|
||||
|
||||
### Before You Start
|
||||
|
||||
1. **Check existing issues**: Search for existing issues before creating new ones
|
||||
2. **Discuss major changes**: Create an issue to discuss major changes
|
||||
3. **Follow the roadmap**: Check the current roadmap and priorities
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
### Creating a Pull Request
|
||||
|
||||
1. **Create a feature branch**:
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
# or
|
||||
git checkout -b fix/your-bug-fix
|
||||
```
|
||||
|
||||
2. **Make your changes**:
|
||||
- Follow code style guidelines
|
||||
- Add tests for new functionality
|
||||
- Update documentation if needed
|
||||
|
||||
3. **Test your changes**:
|
||||
```bash
|
||||
bun run build
|
||||
bun run test:feat
|
||||
```
|
||||
|
||||
4. **Commit your changes**:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new API method for group management"
|
||||
```
|
||||
|
||||
5. **Push to your fork**:
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
6. **Create a Pull Request**:
|
||||
- Use the provided PR template
|
||||
- Link related issues
|
||||
- Provide clear description of changes
|
||||
|
||||
### PR Review Process
|
||||
|
||||
1. **Automated checks** must pass
|
||||
2. **Code review** by at least one maintainer
|
||||
3. **Security review** for security-related changes
|
||||
4. **Documentation review** for API changes
|
||||
5. **Final approval** before merge
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### TypeScript Guidelines
|
||||
|
||||
- Use TypeScript strict mode
|
||||
- Prefer interfaces over types for object shapes
|
||||
- Use meaningful variable and function names
|
||||
- Add JSDoc comments for public APIs
|
||||
- Use async/await over Promises when possible
|
||||
|
||||
### Code Organization
|
||||
|
||||
The project follows a modular structure for better maintainability and organization:
|
||||
|
||||
```
|
||||
zca-js/
|
||||
├── src/ # Source code directory
|
||||
│ ├── apis/ # API methods (100+ files)
|
||||
│ │ ├── sendMessage.ts # Core messaging functionality
|
||||
│ │ ├── login.ts # Authentication methods
|
||||
│ │ ├── loginQR.ts # QR code login
|
||||
│ │ ├── listen.ts # Event listening
|
||||
│ │ ├── sendVideo.ts # Video sending
|
||||
│ │ ├── sendVoice.ts # Voice sending
|
||||
│ │ ├── sendSticker.ts # Sticker sending
|
||||
│ │ ├── createGroup.ts # Group management
|
||||
│ │ ├── addReaction.ts # Message reactions
|
||||
│ │ ├── uploadAttachment.ts # File uploads
|
||||
│ │ └── ... # 90+ other API methods
|
||||
│ ├── models/ # TypeScript interfaces and types
|
||||
│ │ ├── Message.ts # Message interface
|
||||
│ │ ├── Attachment.ts # File attachment types
|
||||
│ │ ├── Reaction.ts # Reaction types
|
||||
│ │ ├── FriendEvent.ts # Friend event types
|
||||
│ │ ├── GroupEvent.ts # Group event types
|
||||
│ │ ├── Typing.ts # Typing indicators
|
||||
│ │ ├── SeenMessage.ts # Message seen events
|
||||
│ │ ├── DeliveredMessage.ts # Message delivery events
|
||||
│ │ ├── Undo.ts # Undo functionality
|
||||
│ │ ├── Enum.ts # Enumerations
|
||||
│ │ └── index.ts # Model exports
|
||||
│ ├── Errors/ # Error handling
|
||||
│ │ ├── ZaloApiError.ts # Custom API error class
|
||||
│ │ └── index.ts # Error exports
|
||||
│ ├── context.ts # Context management and state
|
||||
│ ├── utils.ts # Utility functions and helpers
|
||||
│ ├── zalo.ts # Main Zalo class implementation
|
||||
│ ├── update.ts # Update checking functionality
|
||||
│ └── index.ts # Public API exports
|
||||
├── examples/ # Usage examples
|
||||
│ └── echobot.ts # Echo bot example
|
||||
├── test/ # Test files
|
||||
│ ├── feat.ts # Feature tests
|
||||
│ ├── feat.test.ts # Feature test suite
|
||||
│ ├── test.ts # General tests
|
||||
│ └── a.png # Test assets
|
||||
├── .github/ # GitHub configuration
|
||||
│ └── ISSUE_TEMPLATE/ # Issue templates
|
||||
├── .dev/ # Development tools (developer generated)
|
||||
├── dist/ # Build output (generated)
|
||||
├── node_modules/ # Dependencies (generated)
|
||||
├── package.json # Project configuration
|
||||
├── tsconfig.json # TypeScript configuration
|
||||
├── rollup.config.js # Build configuration
|
||||
├── README.md # Project documentation
|
||||
├── CONTRIBUTING.md # Contribution guidelines
|
||||
├── SECURITY.md # Security policy
|
||||
├── CODE_OF_CONDUCT.md # Community guidelines
|
||||
└── LICENSE # MIT License
|
||||
```
|
||||
|
||||
### Key Directories Explained
|
||||
|
||||
- **`src/apis/`**: Contains all API method implementations (~100 files)
|
||||
|
||||
- **`src/models/`**: TypeScript interfaces and type definitions
|
||||
- Core data structures for messages, events, and API responses
|
||||
- Ensures type safety across the application
|
||||
|
||||
- **`src/Errors/`**: Custom error handling
|
||||
- `ZaloApiError.ts`: Handles API-specific errors
|
||||
- Provides consistent error handling across the library
|
||||
|
||||
- **`examples/`**: Usage examples and demonstrations
|
||||
- `echobot.ts`: Complete example of a Zalo bot implementation
|
||||
|
||||
- **`test/`**: Test suites and test assets
|
||||
- Feature tests for core functionality
|
||||
- Integration tests for API methods
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- **Files**: camelCase (e.g., `sendMessage.ts`)
|
||||
- **Classes**: PascalCase (e.g., `ZaloApiError`)
|
||||
- **Functions**: camelCase (e.g., `sendMessage`)
|
||||
- **Constants**: UPPER_SNAKE_CASE (e.g., `API_BASE_URL`)
|
||||
- **Interfaces**: PascalCase with `I` prefix (e.g., `IMessage`)
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
// Good
|
||||
try {
|
||||
const result = await api.sendMessage(message);
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof ZaloApiError) {
|
||||
throw error;
|
||||
}
|
||||
throw new ZaloApiError(`Failed to send message: ${error.message}`);
|
||||
}
|
||||
|
||||
// Bad
|
||||
try {
|
||||
const result = await api.sendMessage(message);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
### Test Structure
|
||||
|
||||
```typescript
|
||||
describe('API Method', () => {
|
||||
beforeEach(() => {
|
||||
// Setup
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Cleanup
|
||||
});
|
||||
|
||||
it('should handle success case', async () => {
|
||||
// Test implementation
|
||||
});
|
||||
|
||||
it('should handle error case', async () => {
|
||||
// Test error handling
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Testing Best Practices
|
||||
|
||||
- Test both success and failure scenarios
|
||||
- Mock external dependencies
|
||||
- Use descriptive test names
|
||||
- Keep tests independent
|
||||
- Test edge cases and error conditions
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
bun run test:feat
|
||||
|
||||
# Run specific test
|
||||
bun run test/test.ts
|
||||
|
||||
# Run with coverage (if available)
|
||||
bun run test:coverage
|
||||
```
|
||||
|
||||
## Documentation Guidelines
|
||||
|
||||
### API Documentation
|
||||
|
||||
- Document all public methods with JSDoc
|
||||
- Include parameter types and descriptions
|
||||
- Provide usage examples
|
||||
- Document error conditions
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Sends a message to a specific thread
|
||||
* @param message - The message object containing content and metadata
|
||||
* @param threadId - The ID of the thread to send the message to
|
||||
* @param threadType - The type of thread (User or Group)
|
||||
* @returns Promise<Message> - The sent message object
|
||||
* @throws {ZaloApiError} When the API request fails
|
||||
* @example
|
||||
* ```typescript
|
||||
* const message = await api.sendMessage(
|
||||
* { msg: "Hello, world!" },
|
||||
* "123456789",
|
||||
* ThreadType.User
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
async sendMessage(message: IMessage, threadId: string, threadType: ThreadType): Promise<Message>
|
||||
```
|
||||
|
||||
### README Updates
|
||||
|
||||
- Update README.md for new features
|
||||
- Add examples for new APIs
|
||||
- Update installation instructions if needed
|
||||
- Keep the table of contents updated
|
||||
|
||||
## Security Guidelines
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
- Never commit sensitive data (tokens, passwords, etc.)
|
||||
- Use environment variables for configuration
|
||||
- Validate all user inputs
|
||||
- Follow the principle of least privilege
|
||||
- Report security issues privately
|
||||
|
||||
### Security Reporting
|
||||
|
||||
If you discover a security vulnerability:
|
||||
|
||||
1. **DO NOT** create a public issue
|
||||
2. Use the [SECURITY.md](SECURITY.md) reporting process
|
||||
3. Create a private issue with `[SECURITY]` label
|
||||
4. Contact team members directly for urgent issues
|
||||
|
||||
### Code Security
|
||||
|
||||
```typescript
|
||||
// Good - Validate inputs
|
||||
function sendMessage(content: string, threadId: string) {
|
||||
if (!content || typeof content !== 'string') {
|
||||
throw new ZaloApiError('Content must be a non-empty string');
|
||||
}
|
||||
if (!threadId || typeof threadId !== 'string') {
|
||||
throw new ZaloApiError('ThreadId must be a non-empty string');
|
||||
}
|
||||
// Implementation
|
||||
}
|
||||
|
||||
// Bad - No validation
|
||||
function sendMessage(content: any, threadId: any) {
|
||||
// Implementation without validation
|
||||
}
|
||||
```
|
||||
|
||||
## Release Process
|
||||
|
||||
### Versioning
|
||||
|
||||
We follow [Semantic Versioning](https://semver.org/):
|
||||
|
||||
- **MAJOR**: Breaking changes
|
||||
- **MINOR**: New features (backward compatible)
|
||||
- **PATCH**: Bug fixes (backward compatible)
|
||||
|
||||
### Release Checklist
|
||||
|
||||
- [ ] All tests pass
|
||||
- [ ] Documentation is updated
|
||||
- [ ] Version is bumped in package.json
|
||||
- [ ] Build is successful
|
||||
- [ ] Release notes are prepared
|
||||
|
||||
### Publishing
|
||||
|
||||
```bash
|
||||
# Build the project
|
||||
bun run build
|
||||
|
||||
# Run tests
|
||||
bun run test:feat
|
||||
|
||||
# Publish to npm
|
||||
npm publish
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Communication Channels
|
||||
|
||||
- **GitHub Issues**: For bug reports and feature requests
|
||||
- **GitHub Discussions**: For questions and general discussion
|
||||
- **Pull Requests**: For code contributions
|
||||
- **Security Issues**: Use `[SECURITY]` label
|
||||
|
||||
### Team Members
|
||||
|
||||
- [@RFS-ADRENO](https://github.com/RFS-ADRENO)
|
||||
- [@truong9c2208](https://github.com/truong9c2208)
|
||||
- [@JustKemForFun](https://github.com/JustKemForFun)
|
||||
|
||||
### Resources
|
||||
|
||||
- [API Documentation](https://zca-js.tdung.com)
|
||||
- [Examples](examples/)
|
||||
- [Security Policy](SECURITY.md)
|
||||
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
## Special Considerations for zca-js
|
||||
|
||||
### Unofficial API Library
|
||||
|
||||
> [!IMPORTANT]
|
||||
> ⚠️ zca-js is an unofficial API library for Zalo. Please be aware of:
|
||||
|
||||
- **Account Risk**: Using this API may result in account suspension
|
||||
- **Terms of Service**: Respect Zalo's ToS in your contributions
|
||||
- **Rate Limiting**: Be mindful of API usage limits
|
||||
- **Privacy**: Protect user privacy and data
|
||||
|
||||
### Responsible Development
|
||||
|
||||
- Test changes thoroughly before submitting
|
||||
- Avoid introducing features that could harm users
|
||||
- Consider the impact on Zalo's infrastructure
|
||||
- Document any risks or limitations
|
||||
|
||||
---
|
||||
|
||||
**Thank you for contributing to zca-js!** 🚀
|
||||
|
||||
Your contributions help make this library better for the entire community.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 - 2025 RFS-ADRENO, truong9c2208, JustKemForFun
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,225 @@
|
||||
# ZCA-JS
|
||||
|
||||
> [!NOTE]
|
||||
> This is an unofficial Zalo API for personal account. It work by simulating the browser to interact with Zalo Web.
|
||||
|
||||
> [!WARNING]
|
||||
> Using this API could get your account locked or banned. We are not responsible for any issues that may happen. Use it at your own risk.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Migrate to V2](#migrate-to-v2)
|
||||
- [Documentation](#documentation)
|
||||
- [Basic Usages](#basic-usages)
|
||||
- [Login](#login)
|
||||
- [Listen for new messages](#listen-for-new-messages)
|
||||
- [Send a message](#send-a-message)
|
||||
- [Get/Send a sticker](#getsend-a-sticker)
|
||||
- [Example](#example)
|
||||
- [Projects & Useful Resources](#projects--useful-resources)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
- [Support Us](#support-us)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add zca-js # or npm install zca-js
|
||||
```
|
||||
|
||||
### Migrate to V2
|
||||
|
||||
Since official version 2.0.0, `zca-js` has removed sharp dependency for image metadata extraction. It now requires users to provide their own `imageMetadataGetter` function when initializing the `Zalo` class if they want to send images/gifs by file path.
|
||||
|
||||
Example of custom `imageMetadataGetter` using `sharp`:
|
||||
|
||||
```bash
|
||||
bun add sharp # or npm install sharp
|
||||
```
|
||||
|
||||
```javascript
|
||||
import { Zalo } from "zca-js";
|
||||
import sharp from "sharp";
|
||||
import fs from "node:fs";
|
||||
|
||||
async function imageMetadataGetter(filePath) {
|
||||
const data = await fs.promises.readFile(filePath);
|
||||
const metadata = await sharp(data).metadata();
|
||||
return {
|
||||
height: metadata.height,
|
||||
width: metadata.width,
|
||||
size: metadata.size || data.length,
|
||||
};
|
||||
}
|
||||
|
||||
const zalo = new Zalo({
|
||||
imageMetadataGetter,
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
See [API Documentation](https://zca-js.tdung.com) for more details.
|
||||
|
||||
---
|
||||
|
||||
## Basic Usages
|
||||
|
||||
### Login
|
||||
|
||||
```javascript
|
||||
import { Zalo } from "zca-js";
|
||||
|
||||
const zalo = new Zalo();
|
||||
const api = await zalo.loginQR();
|
||||
```
|
||||
|
||||
### Listen for new messages
|
||||
|
||||
```javascript
|
||||
import { Zalo, ThreadType } from "zca-js";
|
||||
|
||||
const zalo = new Zalo();
|
||||
const api = await zalo.loginQR();
|
||||
|
||||
api.listener.on("message", (message) => {
|
||||
const isPlainText = typeof message.data.content === "string";
|
||||
|
||||
switch (message.type) {
|
||||
case ThreadType.User: {
|
||||
if (isPlainText) {
|
||||
// received plain text direct message
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ThreadType.Group: {
|
||||
if (isPlainText) {
|
||||
// received plain text group message
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.listener.start();
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Only one web listener can run per account at a time. If you open Zalo in the browser while the listener is active, the listener will be automatically stopped.
|
||||
|
||||
### Send a message
|
||||
|
||||
```javascript
|
||||
import { Zalo, ThreadType } from "zca-js";
|
||||
|
||||
const zalo = new Zalo();
|
||||
const api = await zalo.loginQR();
|
||||
|
||||
// Echo bot
|
||||
api.listener.on("message", (message) => {
|
||||
const isPlainText = typeof message.data.content === "string";
|
||||
if (message.isSelf || !isPlainText) return;
|
||||
|
||||
switch (message.type) {
|
||||
case ThreadType.User: {
|
||||
api.sendMessage(
|
||||
{
|
||||
msg: "echo: " + message.data.content,
|
||||
quote: message.data, // the message to reply to (optional)
|
||||
},
|
||||
message.threadId,
|
||||
message.type, // ThreadType.User
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ThreadType.Group: {
|
||||
api.sendMessage(
|
||||
{
|
||||
msg: "echo: " + message.data.content,
|
||||
quote: message.data, // the message to reply to (optional)
|
||||
},
|
||||
message.threadId,
|
||||
message.type, // ThreadType.Group
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.listener.start();
|
||||
```
|
||||
|
||||
### Get/Send a sticker
|
||||
|
||||
```javascript
|
||||
api.getStickers("hello").then(async (stickerIds) => {
|
||||
// Get the first sticker
|
||||
const stickerObject = await api.getStickersDetail(stickerIds[0]);
|
||||
api.sendMessageSticker(
|
||||
stickerObject,
|
||||
message.threadId,
|
||||
message.type, // ThreadType.User or ThreadType.Group
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example
|
||||
|
||||
See [examples](examples) folder for more details.
|
||||
|
||||
---
|
||||
|
||||
## Projects & Useful Resources
|
||||
|
||||
<div align="center">
|
||||
|
||||
| Repository | Description |
|
||||
| :--- | :--- |
|
||||
| [**ZaloDataExtractor**](https://github.com/JustKemForFun/ZaloDataExtractor) | A browser `Extension` to extract IMEI, cookies, and user agent from Zalo Web. |
|
||||
| [**MultiZlogin**](https://github.com/ChickenAI/multizlogin) | A multi-account Zalo management system that lets you log in to and manage multiple accounts simultaneously, with proxy and webhook integration. |
|
||||
| [**n8n-nodes-zalo-tools**](https://github.com/ChickenAI/zalo-node) | N8N node for personal Zalo account. |
|
||||
| [**Zalo-F12**](https://github.com/ElectroHeavenVN/Zalo-F12) | A collection of JavaScript code snippets to paste into DevTools to change how Zalo Web/PC works. |
|
||||
| [**Zalo-F12-Tools**](https://github.com/JustKemForFun/Zalo-F12-Tools) | Toggle hidden modes for Zalo Web. |
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions from the community! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details on how to:
|
||||
|
||||
- 🐛 Report bugs and issues
|
||||
- ✨ Suggest new features
|
||||
- 🔧 Submit code contributions
|
||||
- 📚 Improve documentation
|
||||
- 🧪 Add or improve tests
|
||||
- 🔒 Report security vulnerabilities
|
||||
|
||||
For more information, please read our [Code of Conduct](CODE_OF_CONDUCT.md) and [Security Policy](SECURITY.md) before participating.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
---
|
||||
|
||||
## **Support Us**
|
||||
|
||||
- ⭐ **Star our repositories** if you find them useful!
|
||||
- 🔄 **Share** with your network to help us grow
|
||||
- 💡 **Contribute** your ideas and code
|
||||
- ☕ **A coffee**:
|
||||
- [Buy Me a Coffee](https://ko-fi.com/grosse)
|
||||
- [Paypal](https://www.paypal.com/paypalme/dungto213)
|
||||
- [VietQR](https://github.com/user-attachments/assets/e1f319d6-9d11-4082-8248-55b55e645caa)
|
||||
- [Momo](https://me.momo.vn/gMIMulsaUqsbf6iAiXt3)
|
||||
@@ -0,0 +1,83 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We actively maintain and provide security updates for the following versions:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 2.0.x | :white_check_mark: |
|
||||
| 1.x.x | :x: |
|
||||
| < 1.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We take security vulnerabilities seriously. If you discover a security vulnerability in zca-js, please follow these steps:
|
||||
|
||||
### 1. **DO NOT** create a public GitHub issue
|
||||
Security vulnerabilities should be reported privately to prevent potential exploitation.
|
||||
|
||||
### 2. Report the vulnerability
|
||||
Send an email to the maintainers with the following information:
|
||||
- **Subject**: `[SECURITY] zca-js vulnerability report`
|
||||
- **Description**: Detailed description of the vulnerability
|
||||
- **Steps to reproduce**: Clear steps to reproduce the issue
|
||||
- **Impact assessment**: Potential impact of the vulnerability
|
||||
- **Suggested fix** (if available): Any suggestions for fixing the issue
|
||||
|
||||
### 3. Response timeline
|
||||
- **Initial response**: Within 48 hours
|
||||
- **Status update**: Within 1 week
|
||||
- **Resolution**: As soon as possible, typically within 30 days
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Important Warnings
|
||||
|
||||
⚠️ **This is an unofficial API library** that simulates browser interactions with Zalo Web. Please be aware of the following security considerations:
|
||||
|
||||
1. **Account Risk**: Using this API may result in your Zalo account being locked or banned. Use at your own risk.
|
||||
|
||||
2. **Authentication**: The library handles sensitive authentication data. Ensure proper security measures when storing or transmitting this information.
|
||||
|
||||
3. **Rate Limiting**: Respect Zalo's rate limits to avoid triggering security measures.
|
||||
|
||||
4. **Data Privacy**: Be mindful of user privacy and comply with relevant data protection regulations.
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Environment Variables**: Store sensitive configuration in environment variables, not in code
|
||||
2. **HTTPS Only**: Always use HTTPS when transmitting data
|
||||
3. **Input Validation**: Validate all inputs before processing
|
||||
4. **Error Handling**: Implement proper error handling to avoid information disclosure
|
||||
5. **Regular Updates**: Keep the library updated to the latest version
|
||||
|
||||
### Known Limitations
|
||||
|
||||
- This library is not officially supported by Zalo
|
||||
- API endpoints and behavior may change without notice
|
||||
- No guarantee of service availability or stability
|
||||
- May break with Zalo Web updates
|
||||
|
||||
## Security Updates
|
||||
|
||||
Security updates will be released as patch versions (e.g., 2.0.1, 2.0.2) and will be clearly marked in the changelog.
|
||||
|
||||
## Contact Information
|
||||
|
||||
For security-related issues, please contact:
|
||||
- **GitHub Issues**: Create a private issue with the `[SECURITY]` label
|
||||
- **GitHub Discussions**: Use the "Security" category for general security questions
|
||||
- **Team Members**:
|
||||
- [@RFS-ADRENO](https://github.com/RFS-ADRENO)
|
||||
- [@truong9c2208](https://github.com/truong9c2208)
|
||||
- [@JustKemForFun](https://github.com/JustKemForFun)
|
||||
- **Alternative**: Contact any team member through GitHub for urgent security matters
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
We appreciate security researchers and community members who responsibly disclose vulnerabilities. Contributors will be acknowledged in our security advisories unless they prefer to remain anonymous.
|
||||
|
||||
---
|
||||
|
||||
**Note**: This security policy is subject to change. Please check back regularly for updates.
|
||||
@@ -0,0 +1,546 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "zca-js",
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.2.0",
|
||||
"form-data": "^4.0.4",
|
||||
"json-bigint": "^1.0.0",
|
||||
"pako": "^2.1.0",
|
||||
"semver": "^7.6.3",
|
||||
"spark-md5": "^3.0.2",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"ws": "^8.18.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.34.0",
|
||||
"@rollup/plugin-typescript": "^12.1.0",
|
||||
"@types/bun": "^1.1.14",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/spark-md5": "^3.0.4",
|
||||
"@types/ws": "^8.5.11",
|
||||
"eslint": "^9.34.0",
|
||||
"globals": "^16.3.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^5.0.10",
|
||||
"rollup": "^4.24.0",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.41.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
|
||||
|
||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||
|
||||
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
|
||||
|
||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||
|
||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||
|
||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
"@rollup/plugin-typescript": ["@rollup/plugin-typescript@12.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.14.0||^3.0.0||^4.0.0", "tslib": "*", "typescript": ">=3.7.0" } }, "sha512-Kzs8KGJofe7cfTRODsnG1jNGxSvU8gVoNNd7Z/QaY25AYwe2LSSUpx/kPxqF38NYkpR8de3m51r9uwJpDlz6dg=="],
|
||||
|
||||
"@rollup/pluginutils": ["@rollup/pluginutils@5.1.2", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^2.3.1" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" } }, "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.24.0", "", { "os": "android", "cpu": "arm" }, "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.24.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.24.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.24.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.24.0", "", { "os": "linux", "cpu": "arm" }, "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.24.0", "", { "os": "linux", "cpu": "arm" }, "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw=="],
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.24.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.24.0", "", { "os": "linux", "cpu": "none" }, "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.24.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.24.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.24.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.24.0", "", { "os": "win32", "cpu": "x64" }, "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.1.14", "", { "dependencies": { "bun-types": "1.1.37" } }, "sha512-opVYiFGtO2af0dnWBdZWlioLBoxSdDO5qokaazLhq8XQtGZbY4pY3/JxY8Zdf/hEwGubbp7ErZXoN1+h2yesxA=="],
|
||||
|
||||
"@types/crypto-js": ["@types/crypto-js@4.2.2", "", {}, "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
|
||||
|
||||
"@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/node": ["@types/node@20.14.10", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ=="],
|
||||
|
||||
"@types/pako": ["@types/pako@2.0.3", "", {}, "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q=="],
|
||||
|
||||
"@types/semver": ["@types/semver@7.5.8", "", {}, "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="],
|
||||
|
||||
"@types/spark-md5": ["@types/spark-md5@3.0.4", "", {}, "sha512-qtOaDz+IXiNndPgYb6t1YoutnGvFRtWSNzpVjkAPCfB2UzTyybuD4Tjgs7VgRawum3JnJNRwNQd4N//SvrHg1Q=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.5.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.41.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.41.0", "@typescript-eslint/type-utils": "8.41.0", "@typescript-eslint/utils": "8.41.0", "@typescript-eslint/visitor-keys": "8.41.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.41.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.41.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.41.0", "@typescript-eslint/types": "8.41.0", "@typescript-eslint/typescript-estree": "8.41.0", "@typescript-eslint/visitor-keys": "8.41.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.41.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.41.0", "@typescript-eslint/types": "^8.41.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.41.0", "", { "dependencies": { "@typescript-eslint/types": "8.41.0", "@typescript-eslint/visitor-keys": "8.41.0" } }, "sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.41.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.41.0", "", { "dependencies": { "@typescript-eslint/types": "8.41.0", "@typescript-eslint/typescript-estree": "8.41.0", "@typescript-eslint/utils": "8.41.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.41.0", "", {}, "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.41.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.41.0", "@typescript-eslint/tsconfig-utils": "8.41.0", "@typescript-eslint/types": "8.41.0", "@typescript-eslint/visitor-keys": "8.41.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.41.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.41.0", "@typescript-eslint/types": "8.41.0", "@typescript-eslint/typescript-estree": "8.41.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.41.0", "", { "dependencies": { "@typescript-eslint/types": "8.41.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"ansi-escapes": ["ansi-escapes@7.0.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"bun-types": ["bun-types@1.1.37", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
|
||||
|
||||
"cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"commander": ["commander@14.0.0", "", {}, "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="],
|
||||
|
||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="],
|
||||
|
||||
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
|
||||
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
|
||||
|
||||
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||
|
||||
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||
|
||||
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||
|
||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg=="],
|
||||
|
||||
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": "dist/esm/bin.mjs" }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"is-core-module": ["is-core-module@2.15.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||
|
||||
"lint-staged": ["lint-staged@16.1.5", "", { "dependencies": { "chalk": "^5.5.0", "commander": "^14.0.0", "debug": "^4.4.1", "lilconfig": "^3.1.3", "listr2": "^9.0.1", "micromatch": "^4.0.8", "nano-spawn": "^1.0.2", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-uAeQQwByI6dfV7wpt/gVqg+jAPaSp8WwOA8kKC/dv1qw14oGpnpAisY65ibGHUGDUv0rYaZ8CAJZ/1U8hUvC2A=="],
|
||||
|
||||
"listr2": ["listr2@9.0.2", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-VVd7cS6W+vLJu2wmq4QmfVj14Iep7cz4r/OWNk36Aq5ZOY7G8/BfCrQFexcwB1OIxB3yERiePfE/REBjEFulag=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
|
||||
|
||||
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"nano-spawn": ["nano-spawn@1.0.2", "", {}, "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
|
||||
|
||||
"pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||
|
||||
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"prettier": ["prettier@3.3.3", "", { "bin": "bin/prettier.cjs" }, "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||
|
||||
"rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": "dist/esm/bin.mjs" }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
|
||||
|
||||
"rollup": ["rollup@4.24.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.24.0", "@rollup/rollup-android-arm64": "4.24.0", "@rollup/rollup-darwin-arm64": "4.24.0", "@rollup/rollup-darwin-x64": "4.24.0", "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", "@rollup/rollup-linux-arm-musleabihf": "4.24.0", "@rollup/rollup-linux-arm64-gnu": "4.24.0", "@rollup/rollup-linux-arm64-musl": "4.24.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", "@rollup/rollup-linux-riscv64-gnu": "4.24.0", "@rollup/rollup-linux-s390x-gnu": "4.24.0", "@rollup/rollup-linux-x64-gnu": "4.24.0", "@rollup/rollup-linux-x64-musl": "4.24.0", "@rollup/rollup-win32-arm64-msvc": "4.24.0", "@rollup/rollup-win32-ia32-msvc": "4.24.0", "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"semver": ["semver@7.6.3", "", { "bin": "bin/semver.js" }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
|
||||
|
||||
"spark-md5": ["spark-md5@3.0.2", "", {}, "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="],
|
||||
|
||||
"string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
|
||||
|
||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
|
||||
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
|
||||
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"tldts": ["tldts@6.1.64", "", { "dependencies": { "tldts-core": "^6.1.64" }, "bin": "bin/cli.js" }, "sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw=="],
|
||||
|
||||
"tldts-core": ["tldts-core@6.1.64", "", {}, "sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"tough-cookie": ["tough-cookie@5.0.0", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q=="],
|
||||
|
||||
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
|
||||
|
||||
"tslib": ["tslib@2.6.3", "", {}, "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
"typescript": ["typescript@5.5.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.41.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.41.0", "@typescript-eslint/parser": "8.41.0", "@typescript-eslint/typescript-estree": "8.41.0", "@typescript-eslint/utils": "8.41.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-n66rzs5OBXW3SFSnZHr2T685q1i4ODm2nulFJhMZBotaTavsS8TrI3d7bDlRSs9yWo7HmyWrN9qDu14Qv7Y0Dw=="],
|
||||
|
||||
"undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="],
|
||||
|
||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
|
||||
|
||||
"yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||
|
||||
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
|
||||
|
||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"bun-types/@types/node": ["@types/node@20.12.14", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"lint-staged/chalk": ["chalk@5.6.0", "", {}, "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ=="],
|
||||
|
||||
"log-update/slice-ansi": ["slice-ansi@7.1.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg=="],
|
||||
|
||||
"slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"string-width-cjs/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.0.0", "", { "dependencies": { "get-east-asian-width": "^1.0.0" } }, "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA=="],
|
||||
|
||||
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
files: ["**/*.{js,ts}"],
|
||||
plugins: { js },
|
||||
extends: ["js/recommended"],
|
||||
languageOptions: { globals: globals.node },
|
||||
},
|
||||
tseslint.configs.recommended,
|
||||
{
|
||||
rules: {
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
"no-extra-boolean-cast": "off",
|
||||
},
|
||||
},
|
||||
globalIgnores(["dist/*"]),
|
||||
]);
|
||||
@@ -0,0 +1,56 @@
|
||||
import fs from "node:fs";
|
||||
import type { API, Credentials} from "../src/index.js";
|
||||
import { ThreadType, Zalo } from "../src/index.js";
|
||||
|
||||
const zalo = new Zalo();
|
||||
|
||||
const credentials: Partial<Credentials> = {
|
||||
cookie: JSON.parse(fs.readFileSync("./examples/cookies.json", "utf-8")),
|
||||
imei: "",
|
||||
userAgent: "", // Same userAgent is recommended
|
||||
};
|
||||
|
||||
const isValid = (credentials: Partial<Credentials>): credentials is Credentials => {
|
||||
return !!credentials.cookie && !!credentials.imei && !!credentials.userAgent;
|
||||
};
|
||||
|
||||
let api: API | undefined;
|
||||
|
||||
if (isValid(credentials)) {
|
||||
api = await zalo.login(credentials);
|
||||
} else {
|
||||
api = await zalo.loginQR({ qrPath: "./qr.png", userAgent: "" }, () => {
|
||||
console.log("QR Code has been generated");
|
||||
});
|
||||
const context = api.getContext();
|
||||
|
||||
// Save credentials for later use
|
||||
credentials.imei = context.imei;
|
||||
credentials.userAgent = context.userAgent;
|
||||
credentials.cookie = context.cookie.toJSON()?.cookies;
|
||||
}
|
||||
|
||||
const { listener } = api;
|
||||
|
||||
listener.on("message", (message) => {
|
||||
const isDirectMessage = message.type === ThreadType.User;
|
||||
|
||||
if (isDirectMessage && !message.isSelf && typeof message.data.content === "string") {
|
||||
console.log("Message:", message.data.content, message.threadId);
|
||||
api.sendMessage(message.data.content, message.threadId, message.type);
|
||||
}
|
||||
});
|
||||
|
||||
listener.onConnected(() => {
|
||||
console.log("Connected");
|
||||
});
|
||||
|
||||
listener.onClosed(() => {
|
||||
console.log("Closed");
|
||||
});
|
||||
|
||||
listener.onError((error) => {
|
||||
console.error("Error:", error);
|
||||
});
|
||||
|
||||
listener.start();
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { Credentials } from "../src";
|
||||
|
||||
import { Zalo } from "../src";
|
||||
import fs from "node:fs";
|
||||
|
||||
const zalo = new Zalo();
|
||||
const credentialsPath = "./examples/credentials.json";
|
||||
|
||||
function validateCredentials(credentials: Partial<Credentials>): credentials is Credentials {
|
||||
return !!credentials.cookie && !!credentials.imei && !!credentials.userAgent;
|
||||
}
|
||||
|
||||
function getCredentials() {
|
||||
if (!fs.existsSync(credentialsPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const raw = fs.readFileSync(credentialsPath, "utf-8") || "{}";
|
||||
const credentials = JSON.parse(raw);
|
||||
return validateCredentials(credentials) ? credentials : null;
|
||||
}
|
||||
|
||||
const credentials = getCredentials();
|
||||
|
||||
const isValidCredentials = credentials !== null;
|
||||
const api = isValidCredentials ? await zalo.login(credentials) : await zalo.loginQR();
|
||||
|
||||
if (!isValidCredentials) {
|
||||
const apiContext = api.getContext();
|
||||
const credentials: Credentials = {
|
||||
cookie: apiContext.cookie.toJSON()?.cookies || [],
|
||||
imei: apiContext.imei,
|
||||
userAgent: apiContext.userAgent,
|
||||
};
|
||||
|
||||
fs.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), "utf-8");
|
||||
}
|
||||
|
||||
const myProfile = await api.fetchAccountInfo();
|
||||
console.log("My profile:", myProfile);
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export * from "./dist";
|
||||
export as namespace Zalo;
|
||||
Generated
+3505
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "zca-js",
|
||||
"version": "2.1.2",
|
||||
"description": "Unofficial Zalo API for JavaScript",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./dist/cjs/index.cjs",
|
||||
"types": "./index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "bun run scripts/buildAPI.js",
|
||||
"build:clean": "rimraf dist",
|
||||
"build:esm": "tsc",
|
||||
"build:cjs": "rollup -c rollup.config.js",
|
||||
"build": "bun run build:clean && bun run build:esm && bun run build:cjs",
|
||||
"test:feat": "bun run test/feat.ts",
|
||||
"prettier": "prettier --write .",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/RFS-ADRENO/zca-js.git"
|
||||
},
|
||||
"homepage": "https://github.com/RFS-ADRENO/zca-js",
|
||||
"bugs": {
|
||||
"url": "https://github.com/RFS-ADRENO/zca-js/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"chatbot",
|
||||
"zalo",
|
||||
"api"
|
||||
],
|
||||
"author": "RFS-ADRENO, truong9c2208, JustKemForFun",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.2.0",
|
||||
"form-data": "^4.0.4",
|
||||
"json-bigint": "^1.0.0",
|
||||
"pako": "^2.1.0",
|
||||
"semver": "^7.6.3",
|
||||
"spark-md5": "^3.0.2",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.34.0",
|
||||
"@rollup/plugin-typescript": "^12.1.0",
|
||||
"@types/bun": "^1.1.14",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/spark-md5": "^3.0.4",
|
||||
"@types/ws": "^8.5.11",
|
||||
"eslint": "^9.34.0",
|
||||
"globals": "^16.3.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^5.0.10",
|
||||
"rollup": "^4.24.0",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.41.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts}": "bunx eslint"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// rollup.config.js
|
||||
|
||||
export default {
|
||||
input: "dist/index.js",
|
||||
output: {
|
||||
dir: "dist/cjs",
|
||||
entryFileNames: "[name].cjs",
|
||||
format: "cjs",
|
||||
preserveModules: true,
|
||||
},
|
||||
external: [
|
||||
"crypto-js",
|
||||
"events",
|
||||
"form-data",
|
||||
"fs",
|
||||
"node:crypto",
|
||||
"node:fs",
|
||||
"node:fs/promises",
|
||||
"node:path",
|
||||
"pako",
|
||||
"semver",
|
||||
"sharp",
|
||||
"spark-md5",
|
||||
"tough-cookie",
|
||||
"ws",
|
||||
"json-bigint"
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const apisDir = path.join(process.cwd(), "src", "apis");
|
||||
const outputFile = path.join(process.cwd(), "src", "apis.ts");
|
||||
|
||||
function getAllApiFiles(dir) {
|
||||
const ignoreFiles = ["listen.ts", "login.ts", "loginQR.ts", "custom.ts"];
|
||||
return fs
|
||||
.readdirSync(dir)
|
||||
.filter((file) => file.endsWith(".ts") && !ignoreFiles.includes(file))
|
||||
.map((file) => {
|
||||
const nonExtension = file.slice(0, -3); // Remove .ts extension
|
||||
|
||||
return {
|
||||
name: nonExtension,
|
||||
factoryName: `${nonExtension}Factory`,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function generateAPIsFile() {
|
||||
const allApiFiles = getAllApiFiles(apisDir);
|
||||
|
||||
const importLines = allApiFiles.map((file) => {
|
||||
return `import { ${file.factoryName} } from "./apis/${file.name}.js";`;
|
||||
});
|
||||
|
||||
const propertyLines = allApiFiles.map((file) => {
|
||||
return ` public ${file.name}: ReturnType<typeof ${file.factoryName}>;`;
|
||||
});
|
||||
|
||||
const constructorLines = allApiFiles.map((file) => {
|
||||
return ` this.${file.name} = ${file.factoryName}(ctx, this);`;
|
||||
});
|
||||
|
||||
const emptyNewLine = "\n";
|
||||
|
||||
const content =
|
||||
"" +
|
||||
'import { Listener } from "./apis/listen.js";\n' +
|
||||
emptyNewLine +
|
||||
importLines.join("\n") +
|
||||
emptyNewLine +
|
||||
'import { customFactory } from "./apis/custom.js";\n' +
|
||||
'import type { ZPWServiceMap, ContextSession } from "./context.js";\n' +
|
||||
emptyNewLine +
|
||||
"export class API {\n" +
|
||||
" public zpwServiceMap: ZPWServiceMap;\n" +
|
||||
" public listener: Listener;\n" +
|
||||
emptyNewLine +
|
||||
propertyLines.join("\n") +
|
||||
emptyNewLine +
|
||||
emptyNewLine +
|
||||
" public custom: ReturnType<typeof customFactory>;\n" +
|
||||
emptyNewLine +
|
||||
" constructor(ctx: ContextSession, zpwServiceMap: ZPWServiceMap, wsUrls: string[]) {\n" +
|
||||
" this.zpwServiceMap = zpwServiceMap;\n" +
|
||||
" this.listener = new Listener(ctx, wsUrls);\n" +
|
||||
emptyNewLine +
|
||||
constructorLines.join("\n") +
|
||||
emptyNewLine +
|
||||
emptyNewLine +
|
||||
" this.custom = customFactory(ctx, this);\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
|
||||
fs.writeFileSync(outputFile, content, "utf-8");
|
||||
console.log(`\nAPIs file generated at ${outputFile}\n`);
|
||||
}
|
||||
|
||||
generateAPIsFile();
|
||||
@@ -0,0 +1,10 @@
|
||||
export class ZaloApiError extends Error {
|
||||
public code: number | null;
|
||||
|
||||
constructor(message: string, code?: number) {
|
||||
super(message);
|
||||
|
||||
this.name = "ZcaApiError";
|
||||
this.code = code || null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ZaloApiError } from "./ZaloApiError.js";
|
||||
|
||||
export class ZaloApiLoginQRAborted extends ZaloApiError {
|
||||
constructor(message: string = "Operation aborted") {
|
||||
super(message);
|
||||
this.name = "ZaloApiLoginQRAborted";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ZaloApiError } from "./ZaloApiError.js";
|
||||
|
||||
export class ZaloApiLoginQRDeclined extends ZaloApiError {
|
||||
constructor(message: string = "Login QR request declined") {
|
||||
super(message);
|
||||
this.name = "ZaloApiLoginQRDeclined";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ZaloApiError } from "./ZaloApiError.js";
|
||||
|
||||
export class ZaloApiMissingImageMetadataGetter extends ZaloApiError {
|
||||
constructor() {
|
||||
super("Missing `imageMetadataGetter`. Please provide it in the Zalo object options.");
|
||||
this.name = "ZaloApiMissingImageMetadataGetter";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./ZaloApiError.js";
|
||||
export * from "./ZaloApiMissingImageMetadataGetter.js";
|
||||
export * from "./ZaloApiLoginQRAborted.js";
|
||||
export * from "./ZaloApiLoginQRDeclined.js";
|
||||
@@ -0,0 +1,455 @@
|
||||
import { Listener } from "./apis/listen.js";
|
||||
|
||||
import { acceptFriendRequestFactory } from "./apis/acceptFriendRequest.js";
|
||||
import { addGroupBlockedMemberFactory } from "./apis/addGroupBlockedMember.js";
|
||||
import { addGroupDeputyFactory } from "./apis/addGroupDeputy.js";
|
||||
import { addPollOptionsFactory } from "./apis/addPollOptions.js";
|
||||
import { addQuickMessageFactory } from "./apis/addQuickMessage.js";
|
||||
import { addReactionFactory } from "./apis/addReaction.js";
|
||||
import { addUnreadMarkFactory } from "./apis/addUnreadMark.js";
|
||||
import { addUserToGroupFactory } from "./apis/addUserToGroup.js";
|
||||
import { blockUserFactory } from "./apis/blockUser.js";
|
||||
import { blockViewFeedFactory } from "./apis/blockViewFeed.js";
|
||||
import { changeAccountAvatarFactory } from "./apis/changeAccountAvatar.js";
|
||||
import { changeFriendAliasFactory } from "./apis/changeFriendAlias.js";
|
||||
import { changeGroupAvatarFactory } from "./apis/changeGroupAvatar.js";
|
||||
import { changeGroupNameFactory } from "./apis/changeGroupName.js";
|
||||
import { changeGroupOwnerFactory } from "./apis/changeGroupOwner.js";
|
||||
import { createAutoReplyFactory } from "./apis/createAutoReply.js";
|
||||
import { createCatalogFactory } from "./apis/createCatalog.js";
|
||||
import { createGroupFactory } from "./apis/createGroup.js";
|
||||
import { createNoteFactory } from "./apis/createNote.js";
|
||||
import { createPollFactory } from "./apis/createPoll.js";
|
||||
import { createProductCatalogFactory } from "./apis/createProductCatalog.js";
|
||||
import { createReminderFactory } from "./apis/createReminder.js";
|
||||
import { deleteAutoReplyFactory } from "./apis/deleteAutoReply.js";
|
||||
import { deleteAvatarFactory } from "./apis/deleteAvatar.js";
|
||||
import { deleteCatalogFactory } from "./apis/deleteCatalog.js";
|
||||
import { deleteChatFactory } from "./apis/deleteChat.js";
|
||||
import { deleteGroupInviteBoxFactory } from "./apis/deleteGroupInviteBox.js";
|
||||
import { deleteMessageFactory } from "./apis/deleteMessage.js";
|
||||
import { deleteProductCatalogFactory } from "./apis/deleteProductCatalog.js";
|
||||
import { disableGroupLinkFactory } from "./apis/disableGroupLink.js";
|
||||
import { disperseGroupFactory } from "./apis/disperseGroup.js";
|
||||
import { editNoteFactory } from "./apis/editNote.js";
|
||||
import { editReminderFactory } from "./apis/editReminder.js";
|
||||
import { enableGroupLinkFactory } from "./apis/enableGroupLink.js";
|
||||
import { fetchAccountInfoFactory } from "./apis/fetchAccountInfo.js";
|
||||
import { findUserFactory } from "./apis/findUser.js";
|
||||
import { findUserByUsernameFactory } from "./apis/findUserByUsername.js";
|
||||
import { forwardMessageFactory } from "./apis/forwardMessage.js";
|
||||
import { getAliasListFactory } from "./apis/getAliasList.js";
|
||||
import { getAllFriendsFactory } from "./apis/getAllFriends.js";
|
||||
import { getAllGroupsFactory } from "./apis/getAllGroups.js";
|
||||
import { getArchivedChatListFactory } from "./apis/getArchivedChatList.js";
|
||||
import { getAutoDeleteChatFactory } from "./apis/getAutoDeleteChat.js";
|
||||
import { getAutoReplyListFactory } from "./apis/getAutoReplyList.js";
|
||||
import { getAvatarListFactory } from "./apis/getAvatarList.js";
|
||||
import { getAvatarUrlProfileFactory } from "./apis/getAvatarUrlProfile.js";
|
||||
import { getBizAccountFactory } from "./apis/getBizAccount.js";
|
||||
import { getCatalogListFactory } from "./apis/getCatalogList.js";
|
||||
import { getCloseFriendsFactory } from "./apis/getCloseFriends.js";
|
||||
import { getContextFactory } from "./apis/getContext.js";
|
||||
import { getCookieFactory } from "./apis/getCookie.js";
|
||||
import { getFriendBoardListFactory } from "./apis/getFriendBoardList.js";
|
||||
import { getFriendOnlinesFactory } from "./apis/getFriendOnlines.js";
|
||||
import { getFriendRecommendationsFactory } from "./apis/getFriendRecommendations.js";
|
||||
import { getFriendRequestStatusFactory } from "./apis/getFriendRequestStatus.js";
|
||||
import { getFullAvatarFactory } from "./apis/getFullAvatar.js";
|
||||
import { getGroupBlockedMemberFactory } from "./apis/getGroupBlockedMember.js";
|
||||
import { getGroupChatHistoryFactory } from "./apis/getGroupChatHistory.js";
|
||||
import { getGroupInfoFactory } from "./apis/getGroupInfo.js";
|
||||
import { getGroupInviteBoxInfoFactory } from "./apis/getGroupInviteBoxInfo.js";
|
||||
import { getGroupInviteBoxListFactory } from "./apis/getGroupInviteBoxList.js";
|
||||
import { getGroupLinkDetailFactory } from "./apis/getGroupLinkDetail.js";
|
||||
import { getGroupLinkInfoFactory } from "./apis/getGroupLinkInfo.js";
|
||||
import { getGroupMembersInfoFactory } from "./apis/getGroupMembersInfo.js";
|
||||
import { getHiddenConversationsFactory } from "./apis/getHiddenConversations.js";
|
||||
import { getLabelsFactory } from "./apis/getLabels.js";
|
||||
import { getListBoardFactory } from "./apis/getListBoard.js";
|
||||
import { getListReminderFactory } from "./apis/getListReminder.js";
|
||||
import { getMultiUsersByPhonesFactory } from "./apis/getMultiUsersByPhones.js";
|
||||
import { getMuteFactory } from "./apis/getMute.js";
|
||||
import { getOwnIdFactory } from "./apis/getOwnId.js";
|
||||
import { getPendingGroupMembersFactory } from "./apis/getPendingGroupMembers.js";
|
||||
import { getPinConversationsFactory } from "./apis/getPinConversations.js";
|
||||
import { getPollDetailFactory } from "./apis/getPollDetail.js";
|
||||
import { getProductCatalogListFactory } from "./apis/getProductCatalogList.js";
|
||||
import { getQRFactory } from "./apis/getQR.js";
|
||||
import { getQuickMessageListFactory } from "./apis/getQuickMessageList.js";
|
||||
import { getRelatedFriendGroupFactory } from "./apis/getRelatedFriendGroup.js";
|
||||
import { getReminderFactory } from "./apis/getReminder.js";
|
||||
import { getReminderResponsesFactory } from "./apis/getReminderResponses.js";
|
||||
import { getSentFriendRequestFactory } from "./apis/getSentFriendRequest.js";
|
||||
import { getSettingsFactory } from "./apis/getSettings.js";
|
||||
import { getStickerCategoryDetailFactory } from "./apis/getStickerCategoryDetail.js";
|
||||
import { getStickersFactory } from "./apis/getStickers.js";
|
||||
import { getStickersDetailFactory } from "./apis/getStickersDetail.js";
|
||||
import { getUnreadMarkFactory } from "./apis/getUnreadMark.js";
|
||||
import { getUserInfoFactory } from "./apis/getUserInfo.js";
|
||||
import { inviteUserToGroupsFactory } from "./apis/inviteUserToGroups.js";
|
||||
import { joinGroupInviteBoxFactory } from "./apis/joinGroupInviteBox.js";
|
||||
import { joinGroupLinkFactory } from "./apis/joinGroupLink.js";
|
||||
import { keepAliveFactory } from "./apis/keepAlive.js";
|
||||
import { lastOnlineFactory } from "./apis/lastOnline.js";
|
||||
import { leaveGroupFactory } from "./apis/leaveGroup.js";
|
||||
import { lockPollFactory } from "./apis/lockPoll.js";
|
||||
import { parseLinkFactory } from "./apis/parseLink.js";
|
||||
import { rejectFriendRequestFactory } from "./apis/rejectFriendRequest.js";
|
||||
import { removeFriendFactory } from "./apis/removeFriend.js";
|
||||
import { removeFriendAliasFactory } from "./apis/removeFriendAlias.js";
|
||||
import { removeGroupBlockedMemberFactory } from "./apis/removeGroupBlockedMember.js";
|
||||
import { removeGroupDeputyFactory } from "./apis/removeGroupDeputy.js";
|
||||
import { removeQuickMessageFactory } from "./apis/removeQuickMessage.js";
|
||||
import { removeReminderFactory } from "./apis/removeReminder.js";
|
||||
import { removeUnreadMarkFactory } from "./apis/removeUnreadMark.js";
|
||||
import { removeUserFromGroupFactory } from "./apis/removeUserFromGroup.js";
|
||||
import { resetHiddenConversPinFactory } from "./apis/resetHiddenConversPin.js";
|
||||
import { reuseAvatarFactory } from "./apis/reuseAvatar.js";
|
||||
import { reviewPendingMemberRequestFactory } from "./apis/reviewPendingMemberRequest.js";
|
||||
import { searchStickerFactory } from "./apis/searchSticker.js";
|
||||
import { sendBankCardFactory } from "./apis/sendBankCard.js";
|
||||
import { sendCardFactory } from "./apis/sendCard.js";
|
||||
import { sendDeliveredEventFactory } from "./apis/sendDeliveredEvent.js";
|
||||
import { sendFriendRequestFactory } from "./apis/sendFriendRequest.js";
|
||||
import { sendLinkFactory } from "./apis/sendLink.js";
|
||||
import { sendMessageFactory } from "./apis/sendMessage.js";
|
||||
import { sendReportFactory } from "./apis/sendReport.js";
|
||||
import { sendSeenEventFactory } from "./apis/sendSeenEvent.js";
|
||||
import { sendStickerFactory } from "./apis/sendSticker.js";
|
||||
import { sendTypingEventFactory } from "./apis/sendTypingEvent.js";
|
||||
import { sendVideoFactory } from "./apis/sendVideo.js";
|
||||
import { sendVoiceFactory } from "./apis/sendVoice.js";
|
||||
import { setHiddenConversationsFactory } from "./apis/setHiddenConversations.js";
|
||||
import { setMuteFactory } from "./apis/setMute.js";
|
||||
import { setPinnedConversationsFactory } from "./apis/setPinnedConversations.js";
|
||||
import { sharePollFactory } from "./apis/sharePoll.js";
|
||||
import { unblockUserFactory } from "./apis/unblockUser.js";
|
||||
import { undoFactory } from "./apis/undo.js";
|
||||
import { undoFriendRequestFactory } from "./apis/undoFriendRequest.js";
|
||||
import { updateActiveStatusFactory } from "./apis/updateActiveStatus.js";
|
||||
import { updateArchivedChatListFactory } from "./apis/updateArchivedChatList.js";
|
||||
import { updateAutoDeleteChatFactory } from "./apis/updateAutoDeleteChat.js";
|
||||
import { updateAutoReplyFactory } from "./apis/updateAutoReply.js";
|
||||
import { updateCatalogFactory } from "./apis/updateCatalog.js";
|
||||
import { updateGroupSettingsFactory } from "./apis/updateGroupSettings.js";
|
||||
import { updateHiddenConversPinFactory } from "./apis/updateHiddenConversPin.js";
|
||||
import { updateLabelsFactory } from "./apis/updateLabels.js";
|
||||
import { updateLangFactory } from "./apis/updateLang.js";
|
||||
import { updateProductCatalogFactory } from "./apis/updateProductCatalog.js";
|
||||
import { updateProfileFactory } from "./apis/updateProfile.js";
|
||||
import { updateProfileBioFactory } from "./apis/updateProfileBio.js";
|
||||
import { updateQuickMessageFactory } from "./apis/updateQuickMessage.js";
|
||||
import { updateSettingsFactory } from "./apis/updateSettings.js";
|
||||
import { upgradeGroupToCommunityFactory } from "./apis/upgradeGroupToCommunity.js";
|
||||
import { uploadAttachmentFactory } from "./apis/uploadAttachment.js";
|
||||
import { uploadProductPhotoFactory } from "./apis/uploadProductPhoto.js";
|
||||
import { votePollFactory } from "./apis/votePoll.js";
|
||||
import { customFactory } from "./apis/custom.js";
|
||||
import type { ZPWServiceMap, ContextSession } from "./context.js";
|
||||
|
||||
export class API {
|
||||
public zpwServiceMap: ZPWServiceMap;
|
||||
public listener: Listener;
|
||||
|
||||
public acceptFriendRequest: ReturnType<typeof acceptFriendRequestFactory>;
|
||||
public addGroupBlockedMember: ReturnType<typeof addGroupBlockedMemberFactory>;
|
||||
public addGroupDeputy: ReturnType<typeof addGroupDeputyFactory>;
|
||||
public addPollOptions: ReturnType<typeof addPollOptionsFactory>;
|
||||
public addQuickMessage: ReturnType<typeof addQuickMessageFactory>;
|
||||
public addReaction: ReturnType<typeof addReactionFactory>;
|
||||
public addUnreadMark: ReturnType<typeof addUnreadMarkFactory>;
|
||||
public addUserToGroup: ReturnType<typeof addUserToGroupFactory>;
|
||||
public blockUser: ReturnType<typeof blockUserFactory>;
|
||||
public blockViewFeed: ReturnType<typeof blockViewFeedFactory>;
|
||||
public changeAccountAvatar: ReturnType<typeof changeAccountAvatarFactory>;
|
||||
public changeFriendAlias: ReturnType<typeof changeFriendAliasFactory>;
|
||||
public changeGroupAvatar: ReturnType<typeof changeGroupAvatarFactory>;
|
||||
public changeGroupName: ReturnType<typeof changeGroupNameFactory>;
|
||||
public changeGroupOwner: ReturnType<typeof changeGroupOwnerFactory>;
|
||||
public createAutoReply: ReturnType<typeof createAutoReplyFactory>;
|
||||
public createCatalog: ReturnType<typeof createCatalogFactory>;
|
||||
public createGroup: ReturnType<typeof createGroupFactory>;
|
||||
public createNote: ReturnType<typeof createNoteFactory>;
|
||||
public createPoll: ReturnType<typeof createPollFactory>;
|
||||
public createProductCatalog: ReturnType<typeof createProductCatalogFactory>;
|
||||
public createReminder: ReturnType<typeof createReminderFactory>;
|
||||
public deleteAutoReply: ReturnType<typeof deleteAutoReplyFactory>;
|
||||
public deleteAvatar: ReturnType<typeof deleteAvatarFactory>;
|
||||
public deleteCatalog: ReturnType<typeof deleteCatalogFactory>;
|
||||
public deleteChat: ReturnType<typeof deleteChatFactory>;
|
||||
public deleteGroupInviteBox: ReturnType<typeof deleteGroupInviteBoxFactory>;
|
||||
public deleteMessage: ReturnType<typeof deleteMessageFactory>;
|
||||
public deleteProductCatalog: ReturnType<typeof deleteProductCatalogFactory>;
|
||||
public disableGroupLink: ReturnType<typeof disableGroupLinkFactory>;
|
||||
public disperseGroup: ReturnType<typeof disperseGroupFactory>;
|
||||
public editNote: ReturnType<typeof editNoteFactory>;
|
||||
public editReminder: ReturnType<typeof editReminderFactory>;
|
||||
public enableGroupLink: ReturnType<typeof enableGroupLinkFactory>;
|
||||
public fetchAccountInfo: ReturnType<typeof fetchAccountInfoFactory>;
|
||||
public findUser: ReturnType<typeof findUserFactory>;
|
||||
public findUserByUsername: ReturnType<typeof findUserByUsernameFactory>;
|
||||
public forwardMessage: ReturnType<typeof forwardMessageFactory>;
|
||||
public getAliasList: ReturnType<typeof getAliasListFactory>;
|
||||
public getAllFriends: ReturnType<typeof getAllFriendsFactory>;
|
||||
public getAllGroups: ReturnType<typeof getAllGroupsFactory>;
|
||||
public getArchivedChatList: ReturnType<typeof getArchivedChatListFactory>;
|
||||
public getAutoDeleteChat: ReturnType<typeof getAutoDeleteChatFactory>;
|
||||
public getAutoReplyList: ReturnType<typeof getAutoReplyListFactory>;
|
||||
public getAvatarList: ReturnType<typeof getAvatarListFactory>;
|
||||
public getAvatarUrlProfile: ReturnType<typeof getAvatarUrlProfileFactory>;
|
||||
public getBizAccount: ReturnType<typeof getBizAccountFactory>;
|
||||
public getCatalogList: ReturnType<typeof getCatalogListFactory>;
|
||||
public getCloseFriends: ReturnType<typeof getCloseFriendsFactory>;
|
||||
public getContext: ReturnType<typeof getContextFactory>;
|
||||
public getCookie: ReturnType<typeof getCookieFactory>;
|
||||
public getFriendBoardList: ReturnType<typeof getFriendBoardListFactory>;
|
||||
public getFriendOnlines: ReturnType<typeof getFriendOnlinesFactory>;
|
||||
public getFriendRecommendations: ReturnType<typeof getFriendRecommendationsFactory>;
|
||||
public getFriendRequestStatus: ReturnType<typeof getFriendRequestStatusFactory>;
|
||||
public getFullAvatar: ReturnType<typeof getFullAvatarFactory>;
|
||||
public getGroupBlockedMember: ReturnType<typeof getGroupBlockedMemberFactory>;
|
||||
public getGroupChatHistory: ReturnType<typeof getGroupChatHistoryFactory>;
|
||||
public getGroupInfo: ReturnType<typeof getGroupInfoFactory>;
|
||||
public getGroupInviteBoxInfo: ReturnType<typeof getGroupInviteBoxInfoFactory>;
|
||||
public getGroupInviteBoxList: ReturnType<typeof getGroupInviteBoxListFactory>;
|
||||
public getGroupLinkDetail: ReturnType<typeof getGroupLinkDetailFactory>;
|
||||
public getGroupLinkInfo: ReturnType<typeof getGroupLinkInfoFactory>;
|
||||
public getGroupMembersInfo: ReturnType<typeof getGroupMembersInfoFactory>;
|
||||
public getHiddenConversations: ReturnType<typeof getHiddenConversationsFactory>;
|
||||
public getLabels: ReturnType<typeof getLabelsFactory>;
|
||||
public getListBoard: ReturnType<typeof getListBoardFactory>;
|
||||
public getListReminder: ReturnType<typeof getListReminderFactory>;
|
||||
public getMultiUsersByPhones: ReturnType<typeof getMultiUsersByPhonesFactory>;
|
||||
public getMute: ReturnType<typeof getMuteFactory>;
|
||||
public getOwnId: ReturnType<typeof getOwnIdFactory>;
|
||||
public getPendingGroupMembers: ReturnType<typeof getPendingGroupMembersFactory>;
|
||||
public getPinConversations: ReturnType<typeof getPinConversationsFactory>;
|
||||
public getPollDetail: ReturnType<typeof getPollDetailFactory>;
|
||||
public getProductCatalogList: ReturnType<typeof getProductCatalogListFactory>;
|
||||
public getQR: ReturnType<typeof getQRFactory>;
|
||||
public getQuickMessageList: ReturnType<typeof getQuickMessageListFactory>;
|
||||
public getRelatedFriendGroup: ReturnType<typeof getRelatedFriendGroupFactory>;
|
||||
public getReminder: ReturnType<typeof getReminderFactory>;
|
||||
public getReminderResponses: ReturnType<typeof getReminderResponsesFactory>;
|
||||
public getSentFriendRequest: ReturnType<typeof getSentFriendRequestFactory>;
|
||||
public getSettings: ReturnType<typeof getSettingsFactory>;
|
||||
public getStickerCategoryDetail: ReturnType<typeof getStickerCategoryDetailFactory>;
|
||||
public getStickers: ReturnType<typeof getStickersFactory>;
|
||||
public getStickersDetail: ReturnType<typeof getStickersDetailFactory>;
|
||||
public getUnreadMark: ReturnType<typeof getUnreadMarkFactory>;
|
||||
public getUserInfo: ReturnType<typeof getUserInfoFactory>;
|
||||
public inviteUserToGroups: ReturnType<typeof inviteUserToGroupsFactory>;
|
||||
public joinGroupInviteBox: ReturnType<typeof joinGroupInviteBoxFactory>;
|
||||
public joinGroupLink: ReturnType<typeof joinGroupLinkFactory>;
|
||||
public keepAlive: ReturnType<typeof keepAliveFactory>;
|
||||
public lastOnline: ReturnType<typeof lastOnlineFactory>;
|
||||
public leaveGroup: ReturnType<typeof leaveGroupFactory>;
|
||||
public lockPoll: ReturnType<typeof lockPollFactory>;
|
||||
public parseLink: ReturnType<typeof parseLinkFactory>;
|
||||
public rejectFriendRequest: ReturnType<typeof rejectFriendRequestFactory>;
|
||||
public removeFriend: ReturnType<typeof removeFriendFactory>;
|
||||
public removeFriendAlias: ReturnType<typeof removeFriendAliasFactory>;
|
||||
public removeGroupBlockedMember: ReturnType<typeof removeGroupBlockedMemberFactory>;
|
||||
public removeGroupDeputy: ReturnType<typeof removeGroupDeputyFactory>;
|
||||
public removeQuickMessage: ReturnType<typeof removeQuickMessageFactory>;
|
||||
public removeReminder: ReturnType<typeof removeReminderFactory>;
|
||||
public removeUnreadMark: ReturnType<typeof removeUnreadMarkFactory>;
|
||||
public removeUserFromGroup: ReturnType<typeof removeUserFromGroupFactory>;
|
||||
public resetHiddenConversPin: ReturnType<typeof resetHiddenConversPinFactory>;
|
||||
public reuseAvatar: ReturnType<typeof reuseAvatarFactory>;
|
||||
public reviewPendingMemberRequest: ReturnType<typeof reviewPendingMemberRequestFactory>;
|
||||
public searchSticker: ReturnType<typeof searchStickerFactory>;
|
||||
public sendBankCard: ReturnType<typeof sendBankCardFactory>;
|
||||
public sendCard: ReturnType<typeof sendCardFactory>;
|
||||
public sendDeliveredEvent: ReturnType<typeof sendDeliveredEventFactory>;
|
||||
public sendFriendRequest: ReturnType<typeof sendFriendRequestFactory>;
|
||||
public sendLink: ReturnType<typeof sendLinkFactory>;
|
||||
public sendMessage: ReturnType<typeof sendMessageFactory>;
|
||||
public sendReport: ReturnType<typeof sendReportFactory>;
|
||||
public sendSeenEvent: ReturnType<typeof sendSeenEventFactory>;
|
||||
public sendSticker: ReturnType<typeof sendStickerFactory>;
|
||||
public sendTypingEvent: ReturnType<typeof sendTypingEventFactory>;
|
||||
public sendVideo: ReturnType<typeof sendVideoFactory>;
|
||||
public sendVoice: ReturnType<typeof sendVoiceFactory>;
|
||||
public setHiddenConversations: ReturnType<typeof setHiddenConversationsFactory>;
|
||||
public setMute: ReturnType<typeof setMuteFactory>;
|
||||
public setPinnedConversations: ReturnType<typeof setPinnedConversationsFactory>;
|
||||
public sharePoll: ReturnType<typeof sharePollFactory>;
|
||||
public unblockUser: ReturnType<typeof unblockUserFactory>;
|
||||
public undo: ReturnType<typeof undoFactory>;
|
||||
public undoFriendRequest: ReturnType<typeof undoFriendRequestFactory>;
|
||||
public updateActiveStatus: ReturnType<typeof updateActiveStatusFactory>;
|
||||
public updateArchivedChatList: ReturnType<typeof updateArchivedChatListFactory>;
|
||||
public updateAutoDeleteChat: ReturnType<typeof updateAutoDeleteChatFactory>;
|
||||
public updateAutoReply: ReturnType<typeof updateAutoReplyFactory>;
|
||||
public updateCatalog: ReturnType<typeof updateCatalogFactory>;
|
||||
public updateGroupSettings: ReturnType<typeof updateGroupSettingsFactory>;
|
||||
public updateHiddenConversPin: ReturnType<typeof updateHiddenConversPinFactory>;
|
||||
public updateLabels: ReturnType<typeof updateLabelsFactory>;
|
||||
public updateLang: ReturnType<typeof updateLangFactory>;
|
||||
public updateProductCatalog: ReturnType<typeof updateProductCatalogFactory>;
|
||||
public updateProfile: ReturnType<typeof updateProfileFactory>;
|
||||
public updateProfileBio: ReturnType<typeof updateProfileBioFactory>;
|
||||
public updateQuickMessage: ReturnType<typeof updateQuickMessageFactory>;
|
||||
public updateSettings: ReturnType<typeof updateSettingsFactory>;
|
||||
public upgradeGroupToCommunity: ReturnType<typeof upgradeGroupToCommunityFactory>;
|
||||
public uploadAttachment: ReturnType<typeof uploadAttachmentFactory>;
|
||||
public uploadProductPhoto: ReturnType<typeof uploadProductPhotoFactory>;
|
||||
public votePoll: ReturnType<typeof votePollFactory>;
|
||||
|
||||
public custom: ReturnType<typeof customFactory>;
|
||||
|
||||
constructor(ctx: ContextSession, zpwServiceMap: ZPWServiceMap, wsUrls: string[]) {
|
||||
this.zpwServiceMap = zpwServiceMap;
|
||||
this.listener = new Listener(ctx, wsUrls);
|
||||
|
||||
this.acceptFriendRequest = acceptFriendRequestFactory(ctx, this);
|
||||
this.addGroupBlockedMember = addGroupBlockedMemberFactory(ctx, this);
|
||||
this.addGroupDeputy = addGroupDeputyFactory(ctx, this);
|
||||
this.addPollOptions = addPollOptionsFactory(ctx, this);
|
||||
this.addQuickMessage = addQuickMessageFactory(ctx, this);
|
||||
this.addReaction = addReactionFactory(ctx, this);
|
||||
this.addUnreadMark = addUnreadMarkFactory(ctx, this);
|
||||
this.addUserToGroup = addUserToGroupFactory(ctx, this);
|
||||
this.blockUser = blockUserFactory(ctx, this);
|
||||
this.blockViewFeed = blockViewFeedFactory(ctx, this);
|
||||
this.changeAccountAvatar = changeAccountAvatarFactory(ctx, this);
|
||||
this.changeFriendAlias = changeFriendAliasFactory(ctx, this);
|
||||
this.changeGroupAvatar = changeGroupAvatarFactory(ctx, this);
|
||||
this.changeGroupName = changeGroupNameFactory(ctx, this);
|
||||
this.changeGroupOwner = changeGroupOwnerFactory(ctx, this);
|
||||
this.createAutoReply = createAutoReplyFactory(ctx, this);
|
||||
this.createCatalog = createCatalogFactory(ctx, this);
|
||||
this.createGroup = createGroupFactory(ctx, this);
|
||||
this.createNote = createNoteFactory(ctx, this);
|
||||
this.createPoll = createPollFactory(ctx, this);
|
||||
this.createProductCatalog = createProductCatalogFactory(ctx, this);
|
||||
this.createReminder = createReminderFactory(ctx, this);
|
||||
this.deleteAutoReply = deleteAutoReplyFactory(ctx, this);
|
||||
this.deleteAvatar = deleteAvatarFactory(ctx, this);
|
||||
this.deleteCatalog = deleteCatalogFactory(ctx, this);
|
||||
this.deleteChat = deleteChatFactory(ctx, this);
|
||||
this.deleteGroupInviteBox = deleteGroupInviteBoxFactory(ctx, this);
|
||||
this.deleteMessage = deleteMessageFactory(ctx, this);
|
||||
this.deleteProductCatalog = deleteProductCatalogFactory(ctx, this);
|
||||
this.disableGroupLink = disableGroupLinkFactory(ctx, this);
|
||||
this.disperseGroup = disperseGroupFactory(ctx, this);
|
||||
this.editNote = editNoteFactory(ctx, this);
|
||||
this.editReminder = editReminderFactory(ctx, this);
|
||||
this.enableGroupLink = enableGroupLinkFactory(ctx, this);
|
||||
this.fetchAccountInfo = fetchAccountInfoFactory(ctx, this);
|
||||
this.findUser = findUserFactory(ctx, this);
|
||||
this.findUserByUsername = findUserByUsernameFactory(ctx, this);
|
||||
this.forwardMessage = forwardMessageFactory(ctx, this);
|
||||
this.getAliasList = getAliasListFactory(ctx, this);
|
||||
this.getAllFriends = getAllFriendsFactory(ctx, this);
|
||||
this.getAllGroups = getAllGroupsFactory(ctx, this);
|
||||
this.getArchivedChatList = getArchivedChatListFactory(ctx, this);
|
||||
this.getAutoDeleteChat = getAutoDeleteChatFactory(ctx, this);
|
||||
this.getAutoReplyList = getAutoReplyListFactory(ctx, this);
|
||||
this.getAvatarList = getAvatarListFactory(ctx, this);
|
||||
this.getAvatarUrlProfile = getAvatarUrlProfileFactory(ctx, this);
|
||||
this.getBizAccount = getBizAccountFactory(ctx, this);
|
||||
this.getCatalogList = getCatalogListFactory(ctx, this);
|
||||
this.getCloseFriends = getCloseFriendsFactory(ctx, this);
|
||||
this.getContext = getContextFactory(ctx, this);
|
||||
this.getCookie = getCookieFactory(ctx, this);
|
||||
this.getFriendBoardList = getFriendBoardListFactory(ctx, this);
|
||||
this.getFriendOnlines = getFriendOnlinesFactory(ctx, this);
|
||||
this.getFriendRecommendations = getFriendRecommendationsFactory(ctx, this);
|
||||
this.getFriendRequestStatus = getFriendRequestStatusFactory(ctx, this);
|
||||
this.getFullAvatar = getFullAvatarFactory(ctx, this);
|
||||
this.getGroupBlockedMember = getGroupBlockedMemberFactory(ctx, this);
|
||||
this.getGroupChatHistory = getGroupChatHistoryFactory(ctx, this);
|
||||
this.getGroupInfo = getGroupInfoFactory(ctx, this);
|
||||
this.getGroupInviteBoxInfo = getGroupInviteBoxInfoFactory(ctx, this);
|
||||
this.getGroupInviteBoxList = getGroupInviteBoxListFactory(ctx, this);
|
||||
this.getGroupLinkDetail = getGroupLinkDetailFactory(ctx, this);
|
||||
this.getGroupLinkInfo = getGroupLinkInfoFactory(ctx, this);
|
||||
this.getGroupMembersInfo = getGroupMembersInfoFactory(ctx, this);
|
||||
this.getHiddenConversations = getHiddenConversationsFactory(ctx, this);
|
||||
this.getLabels = getLabelsFactory(ctx, this);
|
||||
this.getListBoard = getListBoardFactory(ctx, this);
|
||||
this.getListReminder = getListReminderFactory(ctx, this);
|
||||
this.getMultiUsersByPhones = getMultiUsersByPhonesFactory(ctx, this);
|
||||
this.getMute = getMuteFactory(ctx, this);
|
||||
this.getOwnId = getOwnIdFactory(ctx, this);
|
||||
this.getPendingGroupMembers = getPendingGroupMembersFactory(ctx, this);
|
||||
this.getPinConversations = getPinConversationsFactory(ctx, this);
|
||||
this.getPollDetail = getPollDetailFactory(ctx, this);
|
||||
this.getProductCatalogList = getProductCatalogListFactory(ctx, this);
|
||||
this.getQR = getQRFactory(ctx, this);
|
||||
this.getQuickMessageList = getQuickMessageListFactory(ctx, this);
|
||||
this.getRelatedFriendGroup = getRelatedFriendGroupFactory(ctx, this);
|
||||
this.getReminder = getReminderFactory(ctx, this);
|
||||
this.getReminderResponses = getReminderResponsesFactory(ctx, this);
|
||||
this.getSentFriendRequest = getSentFriendRequestFactory(ctx, this);
|
||||
this.getSettings = getSettingsFactory(ctx, this);
|
||||
this.getStickerCategoryDetail = getStickerCategoryDetailFactory(ctx, this);
|
||||
this.getStickers = getStickersFactory(ctx, this);
|
||||
this.getStickersDetail = getStickersDetailFactory(ctx, this);
|
||||
this.getUnreadMark = getUnreadMarkFactory(ctx, this);
|
||||
this.getUserInfo = getUserInfoFactory(ctx, this);
|
||||
this.inviteUserToGroups = inviteUserToGroupsFactory(ctx, this);
|
||||
this.joinGroupInviteBox = joinGroupInviteBoxFactory(ctx, this);
|
||||
this.joinGroupLink = joinGroupLinkFactory(ctx, this);
|
||||
this.keepAlive = keepAliveFactory(ctx, this);
|
||||
this.lastOnline = lastOnlineFactory(ctx, this);
|
||||
this.leaveGroup = leaveGroupFactory(ctx, this);
|
||||
this.lockPoll = lockPollFactory(ctx, this);
|
||||
this.parseLink = parseLinkFactory(ctx, this);
|
||||
this.rejectFriendRequest = rejectFriendRequestFactory(ctx, this);
|
||||
this.removeFriend = removeFriendFactory(ctx, this);
|
||||
this.removeFriendAlias = removeFriendAliasFactory(ctx, this);
|
||||
this.removeGroupBlockedMember = removeGroupBlockedMemberFactory(ctx, this);
|
||||
this.removeGroupDeputy = removeGroupDeputyFactory(ctx, this);
|
||||
this.removeQuickMessage = removeQuickMessageFactory(ctx, this);
|
||||
this.removeReminder = removeReminderFactory(ctx, this);
|
||||
this.removeUnreadMark = removeUnreadMarkFactory(ctx, this);
|
||||
this.removeUserFromGroup = removeUserFromGroupFactory(ctx, this);
|
||||
this.resetHiddenConversPin = resetHiddenConversPinFactory(ctx, this);
|
||||
this.reuseAvatar = reuseAvatarFactory(ctx, this);
|
||||
this.reviewPendingMemberRequest = reviewPendingMemberRequestFactory(ctx, this);
|
||||
this.searchSticker = searchStickerFactory(ctx, this);
|
||||
this.sendBankCard = sendBankCardFactory(ctx, this);
|
||||
this.sendCard = sendCardFactory(ctx, this);
|
||||
this.sendDeliveredEvent = sendDeliveredEventFactory(ctx, this);
|
||||
this.sendFriendRequest = sendFriendRequestFactory(ctx, this);
|
||||
this.sendLink = sendLinkFactory(ctx, this);
|
||||
this.sendMessage = sendMessageFactory(ctx, this);
|
||||
this.sendReport = sendReportFactory(ctx, this);
|
||||
this.sendSeenEvent = sendSeenEventFactory(ctx, this);
|
||||
this.sendSticker = sendStickerFactory(ctx, this);
|
||||
this.sendTypingEvent = sendTypingEventFactory(ctx, this);
|
||||
this.sendVideo = sendVideoFactory(ctx, this);
|
||||
this.sendVoice = sendVoiceFactory(ctx, this);
|
||||
this.setHiddenConversations = setHiddenConversationsFactory(ctx, this);
|
||||
this.setMute = setMuteFactory(ctx, this);
|
||||
this.setPinnedConversations = setPinnedConversationsFactory(ctx, this);
|
||||
this.sharePoll = sharePollFactory(ctx, this);
|
||||
this.unblockUser = unblockUserFactory(ctx, this);
|
||||
this.undo = undoFactory(ctx, this);
|
||||
this.undoFriendRequest = undoFriendRequestFactory(ctx, this);
|
||||
this.updateActiveStatus = updateActiveStatusFactory(ctx, this);
|
||||
this.updateArchivedChatList = updateArchivedChatListFactory(ctx, this);
|
||||
this.updateAutoDeleteChat = updateAutoDeleteChatFactory(ctx, this);
|
||||
this.updateAutoReply = updateAutoReplyFactory(ctx, this);
|
||||
this.updateCatalog = updateCatalogFactory(ctx, this);
|
||||
this.updateGroupSettings = updateGroupSettingsFactory(ctx, this);
|
||||
this.updateHiddenConversPin = updateHiddenConversPinFactory(ctx, this);
|
||||
this.updateLabels = updateLabelsFactory(ctx, this);
|
||||
this.updateLang = updateLangFactory(ctx, this);
|
||||
this.updateProductCatalog = updateProductCatalogFactory(ctx, this);
|
||||
this.updateProfile = updateProfileFactory(ctx, this);
|
||||
this.updateProfileBio = updateProfileBioFactory(ctx, this);
|
||||
this.updateQuickMessage = updateQuickMessageFactory(ctx, this);
|
||||
this.updateSettings = updateSettingsFactory(ctx, this);
|
||||
this.upgradeGroupToCommunity = upgradeGroupToCommunityFactory(ctx, this);
|
||||
this.uploadAttachment = uploadAttachmentFactory(ctx, this);
|
||||
this.uploadProductPhoto = uploadProductPhotoFactory(ctx, this);
|
||||
this.votePoll = votePollFactory(ctx, this);
|
||||
|
||||
this.custom = customFactory(ctx, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AcceptFriendRequestResponse = "";
|
||||
|
||||
export const acceptFriendRequestFactory = apiFactory<AcceptFriendRequestResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/accept`);
|
||||
|
||||
/**
|
||||
* Accept a friend request from a User
|
||||
*
|
||||
* @param friendId The friend ID to user request is accept
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function acceptFriendRequest(friendId: string) {
|
||||
const params = {
|
||||
fid: friendId,
|
||||
language: ctx.language,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddGroupBlockedMemberResponse = "";
|
||||
|
||||
export const addGroupBlockedMemberFactory = apiFactory<AddGroupBlockedMemberResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/blockedmems/add`);
|
||||
|
||||
/**
|
||||
* Add group blocked member
|
||||
*
|
||||
* @param memberId member id(s)
|
||||
* @param groupId group id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addGroupBlockedMember(memberId: string | string[], groupId: string) {
|
||||
if (!Array.isArray(memberId)) memberId = [memberId];
|
||||
|
||||
const params = {
|
||||
grid: groupId,
|
||||
members: memberId,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddGroupDeputyResponse = "";
|
||||
|
||||
export const addGroupDeputyFactory = apiFactory<AddGroupDeputyResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/admins/add`);
|
||||
|
||||
/**
|
||||
* Add group deputy
|
||||
*
|
||||
* @param memberId user Id or list of user Ids
|
||||
* @param groupId group Id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*
|
||||
*/
|
||||
return async function addGroupDeputy(memberId: string | string[], groupId: string) {
|
||||
if (!Array.isArray(memberId)) memberId = [memberId];
|
||||
|
||||
const params = {
|
||||
grid: groupId,
|
||||
members: memberId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { PollOptions } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddPollOptionsOption = {
|
||||
voted: boolean;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AddPollOptionsPayload = {
|
||||
pollId: number;
|
||||
options: AddPollOptionsOption[];
|
||||
votedOptionIds: number[];
|
||||
};
|
||||
|
||||
export type AddPollOptionsResponse = {
|
||||
options: PollOptions[];
|
||||
};
|
||||
|
||||
export const addPollOptionsFactory = apiFactory<AddPollOptionsResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/poll/option/add`);
|
||||
|
||||
/**
|
||||
* Add new option to poll
|
||||
*
|
||||
* @param payload
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addPollOptions(payload: AddPollOptionsPayload) {
|
||||
const params = {
|
||||
poll_id: payload.pollId,
|
||||
new_options: JSON.stringify(payload.options),
|
||||
voted_option_ids: payload.votedOptionIds,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { QuickMessage, AttachmentSource } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddQuickMessagePayload = {
|
||||
keyword: string;
|
||||
title: string;
|
||||
media?: AttachmentSource;
|
||||
};
|
||||
|
||||
export type AddQuickMessageResponse = {
|
||||
item: QuickMessage;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const addQuickMessageFactory = apiFactory<AddQuickMessageResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.quick_message[0]}/api/quickmessage/create`);
|
||||
|
||||
/**
|
||||
* Add quick message
|
||||
*
|
||||
* @param addPayload - The payload containing data to add the quick message
|
||||
*
|
||||
* @note Zalo might throw an error with code 821 if you have reached the limit of quick messages.
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addQuickMessage(addPayload: AddQuickMessagePayload) {
|
||||
const isType = !addPayload.media ? 0 : 1;
|
||||
|
||||
const params: Record<string, unknown> = {
|
||||
keyword: addPayload.keyword,
|
||||
message: {
|
||||
title: addPayload.title,
|
||||
params: "",
|
||||
},
|
||||
type: isType,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
if (isType === 1) {
|
||||
if (!addPayload.media) throw new ZaloApiError("Media is required");
|
||||
const uploadMedia = await api.uploadProductPhoto({
|
||||
file: addPayload.media,
|
||||
});
|
||||
|
||||
const photoId = uploadMedia.photoId;
|
||||
const thumbUrl = uploadMedia.thumbUrl;
|
||||
const normalUrl = uploadMedia.normalUrl;
|
||||
const hdUrl = uploadMedia.hdUrl;
|
||||
|
||||
params.media = {
|
||||
items: [
|
||||
{
|
||||
type: 0,
|
||||
photoId: photoId,
|
||||
title: "",
|
||||
width: "",
|
||||
height: "",
|
||||
previewThumb: thumbUrl,
|
||||
rawUrl: normalUrl || hdUrl,
|
||||
thumbUrl: thumbUrl,
|
||||
normalUrl: normalUrl || hdUrl,
|
||||
hdUrl: hdUrl || normalUrl,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,321 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { ThreadType, Reactions } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddReactionResponse = {
|
||||
msgIds: number[];
|
||||
};
|
||||
|
||||
export type CustomReaction = {
|
||||
rType: number;
|
||||
source: number;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
export type AddReactionDestination = {
|
||||
data: {
|
||||
msgId: string;
|
||||
cliMsgId: string;
|
||||
};
|
||||
threadId: string;
|
||||
type: ThreadType;
|
||||
};
|
||||
|
||||
export const addReactionFactory = apiFactory<AddReactionResponse>()((api, ctx, utils) => {
|
||||
const serviceURLs = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.reaction[0]}/api/message/reaction`),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.reaction[0]}/api/group/reaction`),
|
||||
};
|
||||
|
||||
/**
|
||||
* Add reaction to a message
|
||||
*
|
||||
* @param icon Reaction icon
|
||||
* @param dest Destination data including message IDs and thread information
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addReaction(icon: Reactions | CustomReaction, dest: AddReactionDestination) {
|
||||
const serviceURL = serviceURLs[dest.type];
|
||||
let rType, source;
|
||||
|
||||
if (typeof icon == "object") {
|
||||
rType = icon.rType;
|
||||
source = icon.source;
|
||||
} else
|
||||
switch (icon) {
|
||||
case Reactions.HAHA:
|
||||
rType = 0;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.LIKE:
|
||||
rType = 3;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.HEART:
|
||||
rType = 5;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.WOW:
|
||||
rType = 32;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.CRY:
|
||||
rType = 2;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.ANGRY:
|
||||
rType = 20;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.KISS:
|
||||
rType = 8;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.TEARS_OF_JOY:
|
||||
rType = 7;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SHIT:
|
||||
rType = 66;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.ROSE:
|
||||
rType = 120;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BROKEN_HEART:
|
||||
rType = 65;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.DISLIKE:
|
||||
rType = 4;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.LOVE:
|
||||
rType = 29;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.CONFUSED:
|
||||
rType = 51;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.WINK:
|
||||
rType = 45;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.FADE:
|
||||
rType = 121;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SUN:
|
||||
rType = 67;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BIRTHDAY:
|
||||
rType = 126;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BOMB:
|
||||
rType = 127;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.OK:
|
||||
rType = 68;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.PEACE:
|
||||
rType = 69;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.THANKS:
|
||||
rType = 70;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.PUNCH:
|
||||
rType = 71;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SHARE:
|
||||
rType = 72;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.PRAY:
|
||||
rType = 73;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.NO:
|
||||
rType = 131;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BAD:
|
||||
rType = 132;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.LOVE_YOU:
|
||||
rType = 133;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SAD:
|
||||
rType = 1;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.VERY_SAD:
|
||||
rType = 16;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.COOL:
|
||||
rType = 21;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.NERD:
|
||||
rType = 22;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BIG_SMILE:
|
||||
rType = 23;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SUNGLASSES:
|
||||
rType = 26;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.NEUTRAL:
|
||||
rType = 30;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SAD_FACE:
|
||||
rType = 35;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BYE:
|
||||
rType = 36;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SLEEPY:
|
||||
rType = 38;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.WIPE:
|
||||
rType = 39;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.DIG:
|
||||
rType = 42;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.ANGUISH:
|
||||
rType = 44;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.HANDCLAP:
|
||||
rType = 46;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.ANGRY_FACE:
|
||||
rType = 47;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.F_CHAIR:
|
||||
rType = 48;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.L_CHAIR:
|
||||
rType = 49;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.R_CHAIR:
|
||||
rType = 50;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SILENT:
|
||||
rType = 52;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SURPRISE:
|
||||
rType = 53;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.EMBARRASSED:
|
||||
rType = 54;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.AFRAID:
|
||||
rType = 60;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.SAD2:
|
||||
rType = 61;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BIG_LAUGH:
|
||||
rType = 62;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.RICH:
|
||||
rType = 63;
|
||||
source = 6;
|
||||
break;
|
||||
case Reactions.BEER:
|
||||
rType = 99;
|
||||
source = 6;
|
||||
break;
|
||||
default:
|
||||
rType = -1;
|
||||
source = 6;
|
||||
}
|
||||
|
||||
const rIcon = typeof icon == "object" ? icon.icon : icon;
|
||||
|
||||
if (rType == undefined || source == undefined || rIcon == undefined) {
|
||||
throw new ZaloApiError("Invalid reaction");
|
||||
}
|
||||
|
||||
const params: Record<string, unknown> = {
|
||||
react_list: [
|
||||
{
|
||||
message: JSON.stringify({
|
||||
rMsg: [
|
||||
{
|
||||
gMsgID: parseInt(dest.data.msgId),
|
||||
cMsgID: parseInt(dest.data.cliMsgId),
|
||||
msgType: 1,
|
||||
},
|
||||
],
|
||||
rIcon,
|
||||
rType,
|
||||
source,
|
||||
}),
|
||||
clientId: Date.now(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (dest.type == ThreadType.User) {
|
||||
params.toid = dest.threadId;
|
||||
} else {
|
||||
params.grid = dest.threadId;
|
||||
params.imei = ctx.imei;
|
||||
}
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
if (typeof (result.data as { msgIds: unknown }).msgIds === "string") {
|
||||
return {
|
||||
msgIds: JSON.parse((result.data as { msgIds: string }).msgIds),
|
||||
};
|
||||
}
|
||||
|
||||
return result.data as AddReactionResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddUnreadMarkResponse = {
|
||||
data: {
|
||||
updateId: number;
|
||||
};
|
||||
status: number;
|
||||
};
|
||||
|
||||
export const addUnreadMarkFactory = apiFactory<AddUnreadMarkResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.conversation[0]}/api/conv/addUnreadMark`);
|
||||
|
||||
/**
|
||||
* Add unread mark to conversation
|
||||
*
|
||||
* @param threadId Thread ID
|
||||
* @param type Thread type (User/Group)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addUnreadMark(threadId: string, type: ThreadType = ThreadType.User) {
|
||||
const timestamp = Date.now();
|
||||
const timestampString = timestamp.toString();
|
||||
const isGroup = type === ThreadType.Group;
|
||||
|
||||
const requestParams = {
|
||||
param: JSON.stringify({
|
||||
[isGroup ? "convsGroup" : "convsUser"]: [
|
||||
{
|
||||
id: threadId,
|
||||
cliMsgId: timestampString,
|
||||
fromUid: "0",
|
||||
ts: timestamp,
|
||||
},
|
||||
],
|
||||
[isGroup ? "convsUser" : "convsGroup"]: [],
|
||||
imei: ctx.imei,
|
||||
}),
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(requestParams));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
const data = result.data as { data: unknown; status: number };
|
||||
if (typeof data.data === "string") {
|
||||
return {
|
||||
data: JSON.parse(data.data),
|
||||
status: data.status,
|
||||
};
|
||||
}
|
||||
|
||||
return result.data as AddUnreadMarkResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type AddUserToGroupResponse = {
|
||||
errorMembers: string[];
|
||||
error_data: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export const addUserToGroupFactory = apiFactory<AddUserToGroupResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/invite/v2`);
|
||||
|
||||
/**
|
||||
* Add user to existing group
|
||||
*
|
||||
* @param memberId User ID or list of user IDs to add
|
||||
* @param groupId Group ID
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function addUserToGroup(memberId: string | string[], groupId: string) {
|
||||
if (!Array.isArray(memberId)) memberId = [memberId];
|
||||
|
||||
const params = {
|
||||
grid: groupId,
|
||||
members: memberId,
|
||||
memberTypes: memberId.map(() => -1),
|
||||
imei: ctx.imei,
|
||||
clientLang: ctx.language,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type BlockUserResponse = "";
|
||||
|
||||
export const blockUserFactory = apiFactory<BlockUserResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/block`);
|
||||
|
||||
/**
|
||||
* Block a User
|
||||
*
|
||||
* @param userId The ID of the User to block
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function blockUser(userId: string) {
|
||||
const params = {
|
||||
fid: userId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type BlockViewFeedResponse = "";
|
||||
|
||||
export const blockViewFeedFactory = apiFactory<BlockViewFeedResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/feed/block`);
|
||||
|
||||
/**
|
||||
* Block/Unblock friend view feed by ID
|
||||
*
|
||||
* @param isBlockFeed Boolean to block/unblock view feed
|
||||
* @param userId User ID to block/unblock view feed
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function blockViewFeed(isBlockFeed: boolean, userId: string) {
|
||||
const params = {
|
||||
fid: userId,
|
||||
isBlockFeed: isBlockFeed ? 1 : 0,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import FormData from "form-data";
|
||||
import fs from "node:fs";
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { AttachmentSource } from "../models/index.js";
|
||||
import { apiFactory, formatTime, getImageMetaData } from "../utils.js";
|
||||
|
||||
export type ChangeAccountAvatarResponse = "";
|
||||
|
||||
export const changeAccountAvatarFactory = apiFactory<ChangeAccountAvatarResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.file[0]}/api/profile/upavatar`);
|
||||
|
||||
/**
|
||||
* Change account avatar
|
||||
*
|
||||
* @param avatarSource Attachment source, can be a file path or an Attachment object
|
||||
*
|
||||
* @throws {ZaloApiError | ZaloApiMissingImageMetadataGetter}
|
||||
*/
|
||||
return async function changeAccountAvatar(avatarSource: AttachmentSource) {
|
||||
const isSourceFilePath = typeof avatarSource == "string";
|
||||
const imageMetaData = isSourceFilePath ? await getImageMetaData(ctx, avatarSource) : avatarSource.metadata;
|
||||
|
||||
const fileSize = imageMetaData.totalSize || 0;
|
||||
|
||||
const params = {
|
||||
avatarSize: 120,
|
||||
clientId: String(ctx.uid + formatTime("%H:%M %d/%m/%Y")),
|
||||
language: ctx.language,
|
||||
metaData: JSON.stringify({
|
||||
origin: {
|
||||
width: imageMetaData.width || 1080,
|
||||
height: imageMetaData.height || 1080,
|
||||
},
|
||||
processed: {
|
||||
width: imageMetaData.width || 1080,
|
||||
height: imageMetaData.height || 1080,
|
||||
size: fileSize,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const avatarData = isSourceFilePath ? fs.readFileSync(avatarSource) : avatarSource.data;
|
||||
const formData = new FormData();
|
||||
formData.append("fileContent", avatarData, {
|
||||
filename: "blob",
|
||||
contentType: "image/jpeg",
|
||||
});
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(
|
||||
utils.makeURL(serviceURL, {
|
||||
params: encryptedParams,
|
||||
}),
|
||||
{
|
||||
method: "POST",
|
||||
headers: formData.getHeaders(),
|
||||
body: formData.getBuffer(),
|
||||
},
|
||||
);
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type ChangeFriendAliasResponse = "";
|
||||
|
||||
export const changeFriendAliasFactory = apiFactory<ChangeFriendAliasResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.alias[0]}/api/alias/update`);
|
||||
|
||||
/**
|
||||
* Change friend's alias
|
||||
*
|
||||
* @param alias new alias (nickname - bietdanh)
|
||||
* @param friendId friend id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function changeFriendAlias(alias: string, friendId: string) {
|
||||
const params = {
|
||||
friendId: friendId,
|
||||
alias: alias,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import FormData from "form-data";
|
||||
import fs from "node:fs";
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { AttachmentSource } from "../models/index.js";
|
||||
import { apiFactory, getFullTimeFromMillisecond, getImageMetaData } from "../utils.js";
|
||||
|
||||
export type ChangeGroupAvatarResponse = "";
|
||||
|
||||
export const changeGroupAvatarFactory = apiFactory<ChangeGroupAvatarResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.file[0]}/api/group/upavatar`);
|
||||
|
||||
/**
|
||||
* Change group avatar
|
||||
*
|
||||
* @param avatarSource Attachment source, can be a file path or an Attachment object
|
||||
* @param groupId Group ID
|
||||
*
|
||||
* @throws {ZaloApiError | ZaloApiMissingImageMetadataGetter}
|
||||
*/
|
||||
return async function changeGroupAvatar(avatarSource: AttachmentSource, groupId: string) {
|
||||
const params: Record<string, unknown> = {
|
||||
grid: groupId,
|
||||
avatarSize: 120,
|
||||
clientId: `g${groupId}${getFullTimeFromMillisecond(new Date().getTime())}`,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const isSourceFilePath = typeof avatarSource == "string";
|
||||
const imageMetaData = isSourceFilePath ? await getImageMetaData(ctx, avatarSource) : avatarSource.metadata;
|
||||
|
||||
params.originWidth = imageMetaData.width || 1080;
|
||||
params.originHeight = imageMetaData.height || 1080;
|
||||
|
||||
const avatarData = isSourceFilePath ? fs.readFileSync(avatarSource) : avatarSource.data;
|
||||
const formData = new FormData();
|
||||
formData.append("fileContent", avatarData, {
|
||||
filename: "blob",
|
||||
contentType: "image/jpeg",
|
||||
});
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(
|
||||
utils.makeURL(serviceURL, {
|
||||
params: encryptedParams,
|
||||
}),
|
||||
{
|
||||
method: "POST",
|
||||
headers: formData.getHeaders(),
|
||||
body: formData.getBuffer(),
|
||||
},
|
||||
);
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type ChangeGroupNameResponse = {
|
||||
status: number;
|
||||
};
|
||||
|
||||
export const changeGroupNameFactory = apiFactory<ChangeGroupNameResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/updateinfo`);
|
||||
|
||||
/**
|
||||
* Change group name
|
||||
*
|
||||
* @param name New group name
|
||||
* @param groupId Group ID
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function changeGroupName(name: string, groupId: string) {
|
||||
if (name.length == 0) name = Date.now().toString();
|
||||
|
||||
const params = {
|
||||
grid: groupId,
|
||||
gname: name,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type ChangeGroupOwnerResponse = {
|
||||
time: number;
|
||||
};
|
||||
|
||||
export const changeGroupOwnerFactory = apiFactory<ChangeGroupOwnerResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/change-owner`);
|
||||
|
||||
/**
|
||||
* Change group owner
|
||||
*
|
||||
* @param memberId User Id of new group owner
|
||||
* @param groupId Group Id
|
||||
* @note Be careful when changing the key, as it will result in losing group admin rights
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*
|
||||
*/
|
||||
return async function changeGroupOwner(memberId: string, groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
newAdminId: memberId,
|
||||
imei: ctx.imei,
|
||||
language: ctx.language,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { AutoReplyItem, AutoReplyScope } from "../models/index.js";
|
||||
|
||||
export type CreateAutoReplyPayload = {
|
||||
content: string;
|
||||
isEnable: boolean;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
scope: AutoReplyScope;
|
||||
uids?: string | string[];
|
||||
};
|
||||
|
||||
export type CreateAutoReplyResponse = {
|
||||
item: AutoReplyItem;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const createAutoReplyFactory = apiFactory<CreateAutoReplyResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.auto_reply[0]}/api/autoreply/create`);
|
||||
|
||||
/**
|
||||
* Create auto reply
|
||||
*
|
||||
* @param payload payload
|
||||
*
|
||||
* @note this API used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createAutoReply(payload: CreateAutoReplyPayload) {
|
||||
const uids = Array.isArray(payload.uids) ? payload.uids : [payload.uids];
|
||||
const resultUids = (payload.scope === 2 || payload.scope === 3) ? uids : [];
|
||||
|
||||
const params = {
|
||||
cliLang: ctx.language,
|
||||
enable: payload.isEnable,
|
||||
content: payload.content,
|
||||
startTime: payload.startTime,
|
||||
endTime: payload.endTime,
|
||||
recurrence: ["RRULE:FREQ=DAILY;"],
|
||||
scope: payload.scope,
|
||||
uids: resultUids,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { CatalogItem } from "../models/index.js";
|
||||
|
||||
export type CreateCatalogResponse = {
|
||||
item: CatalogItem;
|
||||
version_ls_catalog: number;
|
||||
version_catalog: number;
|
||||
};
|
||||
|
||||
export const createCatalogFactory = apiFactory<CreateCatalogResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.catalog[0]}/api/prodcatalog/catalog/create`);
|
||||
|
||||
/**
|
||||
* Create catalog?
|
||||
*
|
||||
* @param catalogName catalog name
|
||||
*
|
||||
* @note this API is used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createCatalog(catalogName: string) {
|
||||
const params = {
|
||||
catalog_name: catalogName,
|
||||
catalog_photo: "",
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { AttachmentSource } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type CreateGroupResponse = {
|
||||
groupType: number;
|
||||
sucessMembers: string[];
|
||||
groupId: string;
|
||||
errorMembers: string[];
|
||||
error_data: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type CreateGroupOptions = {
|
||||
/**
|
||||
* Group name
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* List of member IDs to add to the group
|
||||
*/
|
||||
members: string[];
|
||||
/**
|
||||
* Avatar source, can be a file path or an Attachment object
|
||||
*/
|
||||
avatarSource?: AttachmentSource;
|
||||
/**
|
||||
* Path to the avatar image file
|
||||
* @deprecated Use `avatarSource` instead
|
||||
*/
|
||||
avatarPath?: string;
|
||||
};
|
||||
|
||||
export const createGroupFactory = apiFactory<CreateGroupResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/create/v2`);
|
||||
|
||||
/**
|
||||
* Create a new group
|
||||
*
|
||||
* @param options Group options
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createGroup(options: CreateGroupOptions) {
|
||||
if (options.members.length == 0) throw new ZaloApiError("Group must have at least one member");
|
||||
|
||||
const params = {
|
||||
clientId: Date.now(),
|
||||
gname: String(Date.now()),
|
||||
gdesc: null,
|
||||
members: options.members,
|
||||
membersTypes: options.members.map(() => -1),
|
||||
nameChanged: 0,
|
||||
createLink: 1,
|
||||
clientLang: ctx.language,
|
||||
imei: ctx.imei,
|
||||
zsource: 601,
|
||||
};
|
||||
|
||||
if (options.name && options.name.length > 0) {
|
||||
params.gname = options.name;
|
||||
params.nameChanged = 1;
|
||||
}
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const data = await utils.resolve(response);
|
||||
options.avatarSource = options.avatarSource || options.avatarPath;
|
||||
if (options.avatarSource) await api.changeGroupAvatar(options.avatarSource, data.groupId).catch(utils.logger.error);
|
||||
|
||||
return data;
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { NoteDetail } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type CreateNoteOptions = {
|
||||
title: string;
|
||||
pinAct?: boolean;
|
||||
};
|
||||
|
||||
export type CreateNoteResponse = NoteDetail;
|
||||
|
||||
export const createNoteFactory = apiFactory<CreateNoteResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/topic/createv2`);
|
||||
|
||||
/**
|
||||
* Create a note in a group
|
||||
*
|
||||
* @param options note options
|
||||
* @param options.title note title
|
||||
* @param options.pinAct pin action (pin note)
|
||||
* @param groupId group id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createNote(options: CreateNoteOptions, groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
type: 0,
|
||||
color: -16777216,
|
||||
emoji: "",
|
||||
startTime: -1,
|
||||
duration: -1,
|
||||
params: JSON.stringify({
|
||||
title: options.title,
|
||||
}),
|
||||
repeat: 0,
|
||||
src: 1,
|
||||
imei: ctx.imei,
|
||||
pinAct: options.pinAct ? 1 : 0,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
if (typeof (result.data as { params: unknown }).params === "string") {
|
||||
(result.data as CreateNoteResponse).params = JSON.parse(
|
||||
(result.data as { params: string }).params,
|
||||
);
|
||||
}
|
||||
|
||||
return result.data as CreateNoteResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { PollDetail } from "../models/index.js";
|
||||
|
||||
/**
|
||||
* Options for creating a poll.
|
||||
*/
|
||||
export type CreatePollOptions = {
|
||||
/**
|
||||
* Question for the poll.
|
||||
*/
|
||||
question: string;
|
||||
|
||||
/**
|
||||
* List of options for the poll.
|
||||
*/
|
||||
options: string[];
|
||||
|
||||
/**
|
||||
* Poll expiration time in milliseconds (0 = no expiration).
|
||||
*/
|
||||
expiredTime?: number;
|
||||
|
||||
/**
|
||||
* Allows multiple choices in the poll.
|
||||
*/
|
||||
allowMultiChoices?: boolean;
|
||||
|
||||
/**
|
||||
* Allows members to add new options to the poll.
|
||||
*/
|
||||
allowAddNewOption?: boolean;
|
||||
|
||||
/**
|
||||
* Hides voting results until the user has voted.
|
||||
*/
|
||||
hideVotePreview?: boolean;
|
||||
|
||||
/**
|
||||
* Hides poll voters (anonymous poll).
|
||||
*/
|
||||
isAnonymous?: boolean;
|
||||
};
|
||||
|
||||
export type CreatePollResponse = PollDetail;
|
||||
|
||||
export const createPollFactory = apiFactory<CreatePollResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/poll/create`);
|
||||
|
||||
/**
|
||||
* Create a poll in a group.
|
||||
*
|
||||
* @param options Poll options
|
||||
* @param groupId Group ID to create poll from
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createPoll(options: CreatePollOptions, groupId: string) {
|
||||
const params = {
|
||||
group_id: groupId,
|
||||
question: options.question,
|
||||
options: options.options,
|
||||
expired_time: options.expiredTime ?? 0,
|
||||
pinAct: false,
|
||||
allow_multi_choices: !!options.allowMultiChoices,
|
||||
allow_add_new_option: !!options.allowAddNewOption,
|
||||
is_hide_vote_preview: !!options.hideVotePreview,
|
||||
is_anonymous: !!options.isAnonymous,
|
||||
poll_type: 0,
|
||||
src: 1,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { AttachmentSource, ProductCatalogItem } from "../models/index.js";
|
||||
|
||||
export type CreateProductCatalogPayload = {
|
||||
catalogId: string;
|
||||
|
||||
productName: string;
|
||||
price: string;
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Upto 5 media files are allowed, will be ignored if product_photos is provided
|
||||
*/
|
||||
files?: AttachmentSource[];
|
||||
/**
|
||||
* List of product photo URLs, upto 5
|
||||
*
|
||||
* You can manually get the URL using `uploadProductPhoto` api
|
||||
*/
|
||||
product_photos?: string[];
|
||||
};
|
||||
|
||||
export type CreateProductCatalogResponse = {
|
||||
item: ProductCatalogItem;
|
||||
version_ls_catalog: number;
|
||||
version_catalog: number;
|
||||
};
|
||||
|
||||
export const createProductCatalogFactory = apiFactory<CreateProductCatalogResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.catalog[0]}/api/prodcatalog/product/create`);
|
||||
|
||||
/**
|
||||
* Create product catalog?
|
||||
*
|
||||
* @param payload payload
|
||||
*
|
||||
* @note this API is used for zBussiness - Maximum 5 media files are supported
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createProductCatalog(payload: CreateProductCatalogPayload) {
|
||||
const productPhoto = payload.product_photos || [];
|
||||
|
||||
if (payload.files && payload.files.length == 0) {
|
||||
if (payload.files.length > 5) {
|
||||
throw new ZaloApiError("Maximum 5 media files are allowed");
|
||||
}
|
||||
|
||||
for (const mediaFile of payload.files) {
|
||||
const uploadMedia = await api.uploadProductPhoto({
|
||||
file: mediaFile,
|
||||
});
|
||||
|
||||
const url = uploadMedia.normalUrl || uploadMedia.hdUrl;
|
||||
productPhoto.push(url);
|
||||
}
|
||||
}
|
||||
|
||||
if (productPhoto.length > 5) {
|
||||
throw new ZaloApiError("Maximum 5 media files are allowed");
|
||||
}
|
||||
|
||||
const params = {
|
||||
product_name: payload.productName,
|
||||
price: payload.price,
|
||||
description: payload.description,
|
||||
product_photos: productPhoto,
|
||||
catalog_id: payload.catalogId,
|
||||
currency_unit: "₫", // $
|
||||
create_time: Date.now(),
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { ReminderGroup, ReminderUser} from "../models/index.js";
|
||||
import { ReminderRepeatMode, ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type CreateReminderOptions = {
|
||||
title: string;
|
||||
emoji?: string;
|
||||
startTime?: number;
|
||||
repeat?: ReminderRepeatMode;
|
||||
};
|
||||
|
||||
export type CreateReminderUser = ReminderUser;
|
||||
export type CreateReminderGroup = Omit<ReminderGroup, "responseMem">;
|
||||
|
||||
export type CreateReminderResponse = CreateReminderUser | CreateReminderGroup;
|
||||
|
||||
export const createReminderFactory = apiFactory<CreateReminderResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/oneone/create`),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/topic/createv2`),
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a reminder in a group
|
||||
*
|
||||
* @param options reminder options
|
||||
* @param threadId Group ID to create note from
|
||||
* @param type Thread type (User or Group)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function createReminder(
|
||||
options: CreateReminderOptions,
|
||||
threadId: string,
|
||||
type: ThreadType = ThreadType.User,
|
||||
): Promise<CreateReminderResponse> {
|
||||
const params =
|
||||
type === ThreadType.User
|
||||
? {
|
||||
objectData: JSON.stringify({
|
||||
toUid: threadId,
|
||||
type: 0,
|
||||
color: -16245706,
|
||||
emoji: options.emoji ?? "⏰",
|
||||
startTime: options.startTime ?? Date.now(),
|
||||
duration: -1,
|
||||
params: { title: options.title },
|
||||
needPin: false,
|
||||
repeat: options.repeat ?? ReminderRepeatMode.None,
|
||||
creatorUid: ctx.uid, // Note: for some reason, you can put any valid UID here instead of your own and it still works, atleast for mobile
|
||||
src: 1,
|
||||
}),
|
||||
imei: ctx.imei,
|
||||
}
|
||||
: {
|
||||
grid: threadId,
|
||||
type: 0,
|
||||
color: -16245706,
|
||||
emoji: options.emoji ?? "⏰",
|
||||
startTime: options.startTime ?? Date.now(),
|
||||
duration: -1,
|
||||
params: JSON.stringify({
|
||||
title: options.title,
|
||||
}),
|
||||
repeat: options.repeat ?? ReminderRepeatMode.None,
|
||||
src: 1,
|
||||
imei: ctx.imei,
|
||||
pinAct: 0,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL[type], {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { type ContextSession } from "../context.js";
|
||||
import { apiFactory, type FactoryUtils } from "../utils.js";
|
||||
|
||||
export type CustomAPIProps<T, K> = { ctx: ContextSession; utils: FactoryUtils<T>; props: K };
|
||||
export type CustomAPICallback<T, K> = (props: CustomAPIProps<T, K>) => T | Promise<T>;
|
||||
|
||||
/* eslint-disable */
|
||||
export const customFactory = apiFactory<any>()((api, ctx, utils) => {
|
||||
return function custom<T, K = any>(name: string, callback: CustomAPICallback<T, K>) {
|
||||
Object.defineProperty(api, name, {
|
||||
value: function (props: K) {
|
||||
return callback({ ctx, utils, props });
|
||||
},
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteAutoReplyResponse = {
|
||||
item: number;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const deleteAutoReplyFactory = apiFactory<DeleteAutoReplyResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.auto_reply[0]}/api/autoreply/delete`);
|
||||
|
||||
/**
|
||||
* Delete auto reply
|
||||
*
|
||||
* @param id id of auto reply
|
||||
*
|
||||
* @note this API used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteAutoReply(id: number) {
|
||||
const params = {
|
||||
cliLang: ctx.language,
|
||||
id: id,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteAvatarResponse = {
|
||||
delPhotoIds: string[];
|
||||
errMap: {
|
||||
[key: string]: {
|
||||
err: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteAvatarFactory = apiFactory<DeleteAvatarResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/del-avatars`);
|
||||
|
||||
/**
|
||||
* Delete avatar from avatar list
|
||||
*
|
||||
* @param photoId avatar photo ID(s) to delete - can be a single string or array of strings
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteAvatar(photoId: string | string[]) {
|
||||
const photoIds = Array.isArray(photoId) ? photoId : [photoId];
|
||||
const delPhotos = photoIds.map((id) => ({ photoId: id }));
|
||||
|
||||
const params = {
|
||||
delPhotos: JSON.stringify(delPhotos),
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteCatalogResponse = "";
|
||||
|
||||
export const deleteCatalogFactory = apiFactory<DeleteCatalogResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.catalog[0]}/api/prodcatalog/catalog/delete`);
|
||||
|
||||
/**
|
||||
* Delete catalog?
|
||||
*
|
||||
* @param catalogId catalog id
|
||||
*
|
||||
* @note this API is used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteCatalog(catalogId: string) {
|
||||
const params = {
|
||||
catalog_id: catalogId,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteChatResponse = {
|
||||
status: number;
|
||||
};
|
||||
|
||||
export type DeleteChatLastMessage = {
|
||||
/**
|
||||
* Last message owner ID to delete backwards
|
||||
*/
|
||||
ownerId: string;
|
||||
/**
|
||||
* Last message client ID to delete backwards
|
||||
*/
|
||||
cliMsgId: string;
|
||||
/**
|
||||
* Last message global ID to delete backwards
|
||||
*/
|
||||
globalMsgId: string;
|
||||
};
|
||||
|
||||
export const deleteChatFactory = apiFactory<DeleteChatResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.chat[0]}/api/message/deleteconver`, {
|
||||
nretry: 0,
|
||||
}),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/deleteconver`, {
|
||||
nretry: 0,
|
||||
}),
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete chat
|
||||
*
|
||||
* @param lastMessage Last message info
|
||||
* @param threadId Thread ID
|
||||
* @param type Thread type
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteChat(
|
||||
lastMessage: DeleteChatLastMessage,
|
||||
threadId: string,
|
||||
type: ThreadType = ThreadType.User,
|
||||
) {
|
||||
const timestampString = Date.now().toString();
|
||||
|
||||
const params =
|
||||
type === ThreadType.User
|
||||
? {
|
||||
toid: threadId,
|
||||
cliMsgId: timestampString,
|
||||
conver: lastMessage,
|
||||
onlyMe: 1,
|
||||
imei: ctx.imei,
|
||||
}
|
||||
: {
|
||||
grid: threadId,
|
||||
cliMsgId: timestampString,
|
||||
conver: lastMessage,
|
||||
onlyMe: 1,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL[type], {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteGroupInviteBoxResponse = {
|
||||
delInvitaionIds: string[];
|
||||
errMap: {
|
||||
[groupId: string]: {
|
||||
err: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteGroupInviteBoxFactory = apiFactory<DeleteGroupInviteBoxResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/inv-box/mdel-inv`);
|
||||
|
||||
/**
|
||||
* Delete group invite box
|
||||
*
|
||||
* @param groupId - The group id
|
||||
* @param blockFutureInvite - Whether to block future invites from this group
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteGroupInviteBox(groupId: string | string[], blockFutureInvite: boolean = false) {
|
||||
const grids = Array.isArray(groupId) ? groupId : [groupId];
|
||||
|
||||
const params = {
|
||||
invitations: JSON.stringify(grids.map((grid) => ({ grid }))),
|
||||
block: blockFutureInvite ? 1 : 0,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteMessageResponse = {
|
||||
status: number;
|
||||
};
|
||||
|
||||
export type DeleteMessageDestination = {
|
||||
data: {
|
||||
cliMsgId: string;
|
||||
msgId: string;
|
||||
uidFrom: string;
|
||||
};
|
||||
threadId: string;
|
||||
type?: ThreadType;
|
||||
};
|
||||
|
||||
export const deleteMessageFactory = apiFactory<DeleteMessageResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.chat[0]}/api/message/delete`),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/deletemsg`),
|
||||
};
|
||||
/**
|
||||
* Delete a message
|
||||
*
|
||||
* @param dest Delete target
|
||||
* @param onlyMe Delete message for only you
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteMessage(dest: DeleteMessageDestination, onlyMe = false) {
|
||||
const { threadId, type = ThreadType.User, data } = dest;
|
||||
const isGroup = type === ThreadType.Group;
|
||||
const isSelf = ctx.uid == data.uidFrom;
|
||||
|
||||
if (isSelf && onlyMe === false)
|
||||
throw new ZaloApiError("To delete your message for everyone, use undo api instead");
|
||||
|
||||
if (!isGroup && onlyMe === false) throw new ZaloApiError("Can't delete message for everyone in a private chat");
|
||||
|
||||
const params = {
|
||||
[isGroup ? "grid" : "toid"]: threadId,
|
||||
cliMsgId: Date.now(),
|
||||
msgs: [
|
||||
{
|
||||
cliMsgId: data.cliMsgId,
|
||||
globalMsgId: data.msgId,
|
||||
ownerId: data.uidFrom,
|
||||
destId: threadId,
|
||||
},
|
||||
],
|
||||
onlyMe: onlyMe ? 1 : 0,
|
||||
};
|
||||
|
||||
if (!isGroup) {
|
||||
params.imei = ctx.imei;
|
||||
}
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const response = await utils.request(serviceURL[type], {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DeleteProductCatalogPayload = {
|
||||
productIds: string | string[];
|
||||
catalogId: string;
|
||||
};
|
||||
|
||||
export type DeleteProductCatalogResponse = {
|
||||
item: number[];
|
||||
version_ls_catalog: number;
|
||||
version_catalog: number;
|
||||
};
|
||||
|
||||
export const deleteProductCatalogFactory = apiFactory<DeleteProductCatalogResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.catalog[0]}/api/prodcatalog/product/mdelete`);
|
||||
|
||||
/**
|
||||
* Delete product catalog?
|
||||
*
|
||||
* @param payload payload
|
||||
*
|
||||
* @note this API is used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function deleteProductCatalog(payload: DeleteProductCatalogPayload) {
|
||||
if (!Array.isArray(payload.productIds)) payload.productIds = [payload.productIds];
|
||||
|
||||
const params = {
|
||||
product_ids: payload.productIds,
|
||||
catalog_id: payload.catalogId,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DisableGroupLinkResponse = "";
|
||||
|
||||
export const disableGroupLinkFactory = apiFactory<DisableGroupLinkResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/link/disable`);
|
||||
|
||||
/**
|
||||
* Disable group link
|
||||
*
|
||||
* @param groupId The group id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function disableGroupLink(groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type DisperseGroupResponse = "";
|
||||
|
||||
export const disperseGroupFactory = apiFactory<DisperseGroupResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/disperse`);
|
||||
|
||||
/**
|
||||
* Disperse Group
|
||||
*
|
||||
* @param groupId Group ID to disperse Group from
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function disperseGroup(groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { NoteDetail } from "../models/index.js";
|
||||
|
||||
export type EditNoteOptions = {
|
||||
/**
|
||||
* New note title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* Topic ID to edit note from
|
||||
*/
|
||||
topicId: string;
|
||||
/**
|
||||
* Should the note be pinned?
|
||||
*/
|
||||
pinAct?: boolean;
|
||||
};
|
||||
|
||||
export type EditNoteResponse = NoteDetail;
|
||||
|
||||
export const editNoteFactory = apiFactory<EditNoteResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/topic/updatev2`);
|
||||
|
||||
/**
|
||||
* Edit an existing note in a group
|
||||
*
|
||||
* @param options Options for editing the note
|
||||
* @param groupId Group ID to create note from
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function editNote(options: EditNoteOptions, groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
type: 0,
|
||||
color: -16777216,
|
||||
emoji: "",
|
||||
startTime: -1,
|
||||
duration: -1,
|
||||
params: JSON.stringify({
|
||||
title: options.title,
|
||||
}),
|
||||
topicId: options.topicId,
|
||||
repeat: 0,
|
||||
imei: ctx.imei,
|
||||
pinAct: options.pinAct ? 1 : 2,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
const data = result.data as Omit<NoteDetail, "params"> & { params: unknown };
|
||||
if (typeof data.params == "string") {
|
||||
data.params = JSON.parse(data.params);
|
||||
}
|
||||
|
||||
return data as NoteDetail;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { ReminderRepeatMode, ReminderGroup, ReminderUser} from "../models/index.js";
|
||||
import { ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type EditReminderOptions = {
|
||||
title: string;
|
||||
topicId: string;
|
||||
emoji?: string;
|
||||
startTime?: number;
|
||||
repeat?: ReminderRepeatMode;
|
||||
};
|
||||
|
||||
export type EditReminderUser = ReminderUser;
|
||||
export type EditReminderGroup = Omit<ReminderGroup, "responseMem">;
|
||||
|
||||
export type EditReminderResponse = EditReminderUser | EditReminderGroup;
|
||||
|
||||
export const editReminderFactory = apiFactory<EditReminderResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/oneone/update`),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.group_board[0]}/api/board/topic/updatev2`),
|
||||
};
|
||||
|
||||
/**
|
||||
* Edit an existing reminder
|
||||
*
|
||||
* @param options Reminder parameters
|
||||
* @param threadId Thread ID
|
||||
* @param type Thread type (User/Group)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function editReminder(
|
||||
options: EditReminderOptions,
|
||||
threadId: string,
|
||||
type: ThreadType = ThreadType.User,
|
||||
) {
|
||||
const requestParams =
|
||||
type === ThreadType.User
|
||||
? {
|
||||
objectData: JSON.stringify({
|
||||
toUid: threadId,
|
||||
type: 0,
|
||||
color: -16777216,
|
||||
emoji: options.emoji ?? "",
|
||||
startTime: options.startTime ?? Date.now(),
|
||||
duration: -1,
|
||||
params: { title: options.title },
|
||||
needPin: false,
|
||||
reminderId: options.topicId,
|
||||
repeat: options.repeat ?? 0,
|
||||
}),
|
||||
}
|
||||
: {
|
||||
grid: threadId,
|
||||
type: 0,
|
||||
color: -16777216,
|
||||
emoji: options.emoji ?? "",
|
||||
startTime: options.startTime ?? Date.now(),
|
||||
duration: -1,
|
||||
params: JSON.stringify({
|
||||
title: options.title,
|
||||
}),
|
||||
topicId: options.topicId,
|
||||
repeat: options.repeat ?? 0,
|
||||
imei: ctx.imei,
|
||||
pinAct: 2,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(requestParams));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL[type], {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type EnableGroupLinkResponse = {
|
||||
link: string;
|
||||
expiration_date: number;
|
||||
enabled: number;
|
||||
};
|
||||
|
||||
export const enableGroupLinkFactory = apiFactory<EnableGroupLinkResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/link/new`);
|
||||
|
||||
/**
|
||||
* Enable and create new group link
|
||||
*
|
||||
* @param groupId The group id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function enableGroupLink(groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { User } from "../models/index.js";
|
||||
|
||||
export type FetchAccountInfoResponse = { profile: User };
|
||||
|
||||
export const fetchAccountInfoFactory = apiFactory<FetchAccountInfoResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/profile/me-v2`);
|
||||
|
||||
return async function fetchAccountInfo() {
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import { AvatarSize, type UserBasic } from "../models/index.js";
|
||||
|
||||
export type FindUserResponse = UserBasic;
|
||||
|
||||
export const findUserFactory = apiFactory<FindUserResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/profile/get`);
|
||||
|
||||
/**
|
||||
* Find user by phone number
|
||||
*
|
||||
* @param phoneNumber Phone number
|
||||
* @param avatarSize Avatar size (default: AvatarSize.Large)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function findUser(phoneNumber: string, avatarSize: AvatarSize = AvatarSize.Large) {
|
||||
if (!phoneNumber) throw new ZaloApiError("Missing phoneNumber");
|
||||
if (phoneNumber.startsWith("0")) {
|
||||
if (ctx.language == "vi") phoneNumber = "84" + phoneNumber.slice(1);
|
||||
}
|
||||
|
||||
const params = {
|
||||
phone: phoneNumber,
|
||||
avatar_size: avatarSize,
|
||||
language: ctx.language,
|
||||
imei: ctx.imei,
|
||||
reqSrc: 40,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const finalServiceUrl = new URL(serviceURL);
|
||||
finalServiceUrl.searchParams.append("params", encryptedParams);
|
||||
|
||||
const response = await utils.request(
|
||||
utils.makeURL(finalServiceUrl.toString(), {
|
||||
params: encryptedParams,
|
||||
}),
|
||||
);
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
if (result.error && result.error.code != 216)
|
||||
throw new ZaloApiError(result.error.message, result.error.code);
|
||||
|
||||
return result.data as FindUserResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import { AvatarSize, type UserBasic } from "../models/index.js";
|
||||
|
||||
export type FindUserByUsernameResponse = UserBasic;
|
||||
|
||||
export const findUserByUsernameFactory = apiFactory<FindUserByUsernameResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/search/by-user-name`);
|
||||
|
||||
/**
|
||||
* Find user by username
|
||||
*
|
||||
* @param username username for find
|
||||
* @param avatarSize Avatar size (default: AvatarSize.Large)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function findUserByUsername(username: string, avatarSize: AvatarSize = AvatarSize.Large) {
|
||||
const params = {
|
||||
user_name: username,
|
||||
avatar_size: avatarSize,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,127 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { ThreadType } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type ForwardMessagePayload = {
|
||||
message: string;
|
||||
ttl?: number;
|
||||
reference?: {
|
||||
id: string;
|
||||
ts: number;
|
||||
logSrcType: number;
|
||||
fwLvl: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type ForwardMessageSuccess = {
|
||||
clientId: string;
|
||||
msgId: string;
|
||||
};
|
||||
|
||||
export type ForwardMessageFail = {
|
||||
clientId: string;
|
||||
error_code: string;
|
||||
};
|
||||
|
||||
export type ForwardMessageResponse = {
|
||||
success: ForwardMessageSuccess[];
|
||||
fail: ForwardMessageFail[];
|
||||
};
|
||||
|
||||
export const forwardMessageFactory = apiFactory<ForwardMessageResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = {
|
||||
[ThreadType.User]: utils.makeURL(`${api.zpwServiceMap.file[0]}/api/message/mforward`),
|
||||
[ThreadType.Group]: utils.makeURL(`${api.zpwServiceMap.file[0]}/api/group/mforward`),
|
||||
};
|
||||
|
||||
/**
|
||||
* Forward message to multiple threads
|
||||
*
|
||||
* @param payload Forward message payload
|
||||
* @param threadId Thread ID(s)
|
||||
* @param type Thread type (User/Group)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function forwardMessage(
|
||||
payload: ForwardMessagePayload,
|
||||
threadIds: string[],
|
||||
type: ThreadType = ThreadType.User,
|
||||
) {
|
||||
if (!payload.message) throw new ZaloApiError("Missing message content");
|
||||
if (!threadIds || threadIds.length === 0) throw new ZaloApiError("Missing thread IDs");
|
||||
|
||||
const timestamp = Date.now();
|
||||
const clientId = timestamp.toString();
|
||||
|
||||
const msgInfo = {
|
||||
message: payload.message,
|
||||
reference: payload.reference
|
||||
? JSON.stringify({
|
||||
type: 3,
|
||||
data: JSON.stringify(payload.reference),
|
||||
})
|
||||
: undefined,
|
||||
};
|
||||
|
||||
const decorLog = payload.reference
|
||||
? {
|
||||
fw: {
|
||||
pmsg: {
|
||||
st: 1,
|
||||
ts: payload.reference.ts,
|
||||
id: payload.reference.id,
|
||||
},
|
||||
rmsg: {
|
||||
st: 1,
|
||||
ts: payload.reference.ts,
|
||||
id: payload.reference.id,
|
||||
},
|
||||
fwLvl: payload.reference.fwLvl,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
|
||||
let params;
|
||||
if (type === ThreadType.User) {
|
||||
params = {
|
||||
toIds: threadIds.map((threadId) => ({
|
||||
clientId,
|
||||
toUid: threadId,
|
||||
ttl: payload.ttl ?? 0,
|
||||
})),
|
||||
imei: ctx.imei,
|
||||
ttl: payload.ttl ?? 0,
|
||||
msgType: "1",
|
||||
totalIds: threadIds.length,
|
||||
msgInfo: JSON.stringify(msgInfo),
|
||||
decorLog: JSON.stringify(decorLog),
|
||||
};
|
||||
} else {
|
||||
params = {
|
||||
grids: threadIds.map((threadId) => ({
|
||||
clientId,
|
||||
grid: threadId,
|
||||
ttl: payload.ttl ?? 0,
|
||||
})),
|
||||
ttl: payload.ttl ?? 0,
|
||||
msgType: "1",
|
||||
totalIds: threadIds.length,
|
||||
msgInfo: JSON.stringify(msgInfo),
|
||||
decorLog: JSON.stringify(decorLog),
|
||||
};
|
||||
}
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL[type], {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetAliasListResponse = {
|
||||
items: {
|
||||
userId: string;
|
||||
alias: string;
|
||||
}[];
|
||||
updateTime: string;
|
||||
};
|
||||
|
||||
export const getAliasListFactory = apiFactory<GetAliasListResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.alias[0]}/api/alias/list`);
|
||||
|
||||
/**
|
||||
* Get alias list
|
||||
*
|
||||
* @param count Page size (default: 100)
|
||||
* @param page Page number (default: 1)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getAliasList(count: number = 100, page: number = 1) {
|
||||
const params = {
|
||||
page,
|
||||
count,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import { AvatarSize, type User } from "../models/index.js";
|
||||
|
||||
export type GetAllFriendsResponse = User[];
|
||||
|
||||
export const getAllFriendsFactory = apiFactory<GetAllFriendsResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/getfriends`);
|
||||
|
||||
/**
|
||||
* Get all friends
|
||||
*
|
||||
* @param count Page size (default: 20000)
|
||||
* @param page Page number (default: 1)
|
||||
* @param avatarSize Avatar size (default: AvatarSize.Small)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getAllFriends(count: number = 20000, page: number = 1, avatarSize: AvatarSize = AvatarSize.Small) {
|
||||
const params = {
|
||||
incInvalid: 1,
|
||||
page,
|
||||
count,
|
||||
avatar_size: avatarSize,
|
||||
actiontime: 0,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const response = await utils.request(
|
||||
utils.makeURL(serviceURL, {
|
||||
params: encryptedParams,
|
||||
}),
|
||||
{
|
||||
method: "GET",
|
||||
},
|
||||
);
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetAllGroupsResponse = {
|
||||
version: string;
|
||||
gridVerMap: {
|
||||
[groupId: string]: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const getAllGroupsFactory = apiFactory<GetAllGroupsResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group_poll[0]}/api/group/getlg/v4`);
|
||||
|
||||
return async function getAllGroups() {
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetArchivedChatListResponse = {
|
||||
items: unknown[]; // @TODO: check type
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const getArchivedChatListFactory = apiFactory<GetArchivedChatListResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.label[0]}/api/archivedchat/list`);
|
||||
|
||||
/**
|
||||
* Get arcnived chat list
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getArchivedChatList() {
|
||||
const params = {
|
||||
version: 1,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetAutoDeleteChatResponse = {
|
||||
convers: {
|
||||
destId: string;
|
||||
isGroup: boolean;
|
||||
ttl: number;
|
||||
createdAt: number;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const getAutoDeleteChatFactory = apiFactory<GetAutoDeleteChatResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.conversation[0]}/api/conv/autodelete/getConvers`);
|
||||
|
||||
/**
|
||||
* Get auto delete chat
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*
|
||||
*/
|
||||
return async function getAutoDeleteChat() {
|
||||
const params = {};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { AutoReplyItem } from "../models/index.js";
|
||||
|
||||
export type GetAutoReplyListResponse = {
|
||||
item: AutoReplyItem[];
|
||||
version: number;
|
||||
};
|
||||
export const getAutoReplyListFactory = apiFactory<GetAutoReplyListResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.auto_reply[0]}/api/autoreply/list`);
|
||||
|
||||
/**
|
||||
* Get auto reply list
|
||||
*
|
||||
* @note this API used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getAutoReplyList() {
|
||||
const params = {
|
||||
version: 0,
|
||||
cliLang: ctx.language,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetAvatarListResponse = {
|
||||
albumId: string;
|
||||
nextPhotoId: string;
|
||||
hasMore: number;
|
||||
photos: {
|
||||
photoId: string;
|
||||
thumbnail: string;
|
||||
url: string;
|
||||
bkUrl: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const getAvatarListFactory = apiFactory<GetAvatarListResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/avatar-list`);
|
||||
|
||||
/**
|
||||
* Get avatar list
|
||||
*
|
||||
* @param count The number of avatars to fetch (default: 50)
|
||||
* @param page The page number to fetch (default: 1)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getAvatarList(count: number = 50, page: number = 1) {
|
||||
const params = {
|
||||
page,
|
||||
albumId: "0",
|
||||
count,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { AvatarSize } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetAvatarUrlProfileResponse = {
|
||||
[userId: string]: {
|
||||
avatar: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const getAvatarUrlProfileFactory = apiFactory<GetAvatarUrlProfileResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/profile/avatar-url`);
|
||||
|
||||
/**
|
||||
* Get avatar url profile
|
||||
*
|
||||
* @param friendId friend id(s)
|
||||
* @param avatarSize Avatar size (default: AvatarSize.Large)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getAvatarUrlProfile(friendIds: string | string[], avatarSize: AvatarSize = AvatarSize.Large) {
|
||||
if (!Array.isArray(friendIds)) friendIds = [friendIds];
|
||||
|
||||
const params = {
|
||||
friend_ids: friendIds,
|
||||
avatar_size: avatarSize,
|
||||
srcReq: -1,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { BusinessCategory } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetBizAccountResponse = {
|
||||
biz?: {
|
||||
desc: string | null;
|
||||
cate: BusinessCategory;
|
||||
addr: string;
|
||||
website: string;
|
||||
email: string;
|
||||
};
|
||||
setting_start_page?: {
|
||||
enable_biz_label: number;
|
||||
enable_cate: number;
|
||||
enable_add: number;
|
||||
cta_profile: number;
|
||||
/**
|
||||
* Relative path used to build the catalog URL.
|
||||
*
|
||||
* Example: https://catalog.zalo.me/${cta_catalog}
|
||||
*/
|
||||
cta_catalog: string | null;
|
||||
} | null;
|
||||
pkgId: number;
|
||||
};
|
||||
|
||||
export const getBizAccountFactory = apiFactory<GetBizAccountResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/get-bizacc`);
|
||||
|
||||
/**
|
||||
* Get biz account
|
||||
*
|
||||
* @param friendId The friend ID to get biz account
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getBizAccount(friendId: string) {
|
||||
const params = {
|
||||
fid: friendId,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { CatalogItem } from "../models/index.js";
|
||||
|
||||
export type GetCatalogListPayload = {
|
||||
/**
|
||||
* Number of items to retrieve (default: 20)
|
||||
*/
|
||||
limit?: number;
|
||||
lastProductId?: number;
|
||||
/**
|
||||
* Page number (default: 0)
|
||||
*/
|
||||
page?: number;
|
||||
};
|
||||
|
||||
export type GetCatalogListResponse = {
|
||||
items: CatalogItem[];
|
||||
version: number;
|
||||
has_more: number;
|
||||
};
|
||||
|
||||
export const getCatalogListFactory = apiFactory<GetCatalogListResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.catalog[0]}/api/prodcatalog/catalog/list`);
|
||||
|
||||
/**
|
||||
* Get catalog list?
|
||||
*
|
||||
* @param payload payload
|
||||
*
|
||||
* @note this API is used for zBusiness
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getCatalogList(payload?: GetCatalogListPayload) {
|
||||
const params = {
|
||||
version_list_catalog: 0,
|
||||
limit: payload?.limit ?? 20,
|
||||
last_product_id: payload?.lastProductId ?? -1,
|
||||
page: payload?.page ?? 0,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { User } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetCloseFriendsResponse = User[];
|
||||
|
||||
export const getCloseFriendsFactory = apiFactory<GetCloseFriendsResponse>()((api, _ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/getclosedfriends`);
|
||||
|
||||
/**
|
||||
* Get close friends
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getCloseFriends() {
|
||||
const params = {};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export const getContextFactory = apiFactory()((_, ctx) => {
|
||||
return () => ctx;
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export const getCookieFactory = apiFactory()((_, ctx) => {
|
||||
/**
|
||||
* Get the current cookie string
|
||||
*/
|
||||
return function getCookie() {
|
||||
return ctx.cookie;
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetFriendBoardListResponse = {
|
||||
data: string[];
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const getFriendBoardListFactory = apiFactory<GetFriendBoardListResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend_board[0]}/api/friendboard/list`);
|
||||
|
||||
/**
|
||||
* Get friend board list
|
||||
*
|
||||
* @param conversationId conversation id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getFriendBoardList(conversationId: string) {
|
||||
const params = {
|
||||
conversationId: conversationId,
|
||||
version: 0,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetFriendOnlinesStatus = {
|
||||
userId: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
|
||||
export type GetFriendOnlinesResponse = {
|
||||
predefine: string[];
|
||||
ownerStatus: string;
|
||||
onlines: GetFriendOnlinesStatus[];
|
||||
};
|
||||
|
||||
export const getFriendOnlinesFactory = apiFactory<GetFriendOnlinesResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/onlines`);
|
||||
|
||||
/**
|
||||
* Get friend onlines?
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getFriendOnlines() {
|
||||
const params = {
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
const data = result.data as GetFriendOnlinesResponse;
|
||||
|
||||
if (Array.isArray(data.onlines)) {
|
||||
for (const online of data.onlines) {
|
||||
if (typeof online.status === "string") {
|
||||
const parsed = JSON.parse(online.status);
|
||||
if (parsed && typeof (parsed as { status?: unknown }).status === "string") {
|
||||
online.status = (parsed as { status: string }).status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data as GetFriendOnlinesResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { Gender, ZBusinessPackage } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export enum FriendRecommendationsType {
|
||||
RecommendedFriend = 1,
|
||||
ReceivedFriendRequest = 2,
|
||||
}
|
||||
|
||||
export type FriendRecommendationsCollapseMsgListConfig = {
|
||||
collapseId: number;
|
||||
collapseXItem: number;
|
||||
collapseYItem: number;
|
||||
};
|
||||
|
||||
export type FriendRecommendationsDataInfo = {
|
||||
userId: string;
|
||||
zaloName: string;
|
||||
displayName: string;
|
||||
avatar: string;
|
||||
phoneNumber: string;
|
||||
status: string;
|
||||
gender: Gender;
|
||||
dob: number;
|
||||
type: number;
|
||||
recommType: FriendRecommendationsType;
|
||||
recommSrc: number;
|
||||
recommTime: number;
|
||||
recommInfo: {
|
||||
suggestWay: number;
|
||||
source: number;
|
||||
message: string;
|
||||
customText: string | null;
|
||||
};
|
||||
bizPkg: ZBusinessPackage;
|
||||
isSeenFriendReq: boolean;
|
||||
};
|
||||
|
||||
export type FriendRecommendationsRecommItem = {
|
||||
recommItemType: number;
|
||||
dataInfo: FriendRecommendationsDataInfo;
|
||||
};
|
||||
|
||||
export type GetFriendRecommendationsResponse = {
|
||||
expiredDuration: number;
|
||||
collapseMsgListConfig: FriendRecommendationsCollapseMsgListConfig;
|
||||
recommItems: FriendRecommendationsRecommItem[];
|
||||
};
|
||||
|
||||
export const getFriendRecommendationsFactory = apiFactory<GetFriendRecommendationsResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/recommendsv2/list`);
|
||||
|
||||
/**
|
||||
* Get friend recommendations/received friend requests
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getFriendRecommendations() {
|
||||
const params = {
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetFriendRequestStatusResponse = {
|
||||
addFriendPrivacy: number;
|
||||
isSeenFriendReq: boolean;
|
||||
is_friend: number;
|
||||
is_requested: number;
|
||||
is_requesting: number;
|
||||
};
|
||||
|
||||
export const getFriendRequestStatusFactory = apiFactory<GetFriendRequestStatusResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/reqstatus`);
|
||||
|
||||
/**
|
||||
* Get friend request status
|
||||
*
|
||||
* @param friendId friend id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getFriendRequestStatus(friendId: string) {
|
||||
const params = {
|
||||
fid: friendId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetFullAvatarResponse = {
|
||||
bk_full_avatar: string;
|
||||
full_avatar: string;
|
||||
};
|
||||
|
||||
export const getFullAvatarFactory = apiFactory<GetFullAvatarResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/profile/avatar`);
|
||||
|
||||
/**
|
||||
* Get full avatar
|
||||
*
|
||||
* @param friendId friend id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getFullAvatar(friendId: string) {
|
||||
const params = {
|
||||
fid: friendId,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GetGroupBlockedMemberPayload = {
|
||||
/**
|
||||
* Page number (default: 1)
|
||||
*/
|
||||
page?: number;
|
||||
/**
|
||||
* Number of items to retrieve (default: 50)
|
||||
*/
|
||||
count?: number;
|
||||
};
|
||||
|
||||
export type GetGroupBlockedMemberResponse = {
|
||||
blocked_members: {
|
||||
id: string;
|
||||
dName: string;
|
||||
zaloName: string;
|
||||
avatar: string;
|
||||
avatar_25: string;
|
||||
accountStatus: number;
|
||||
type: number;
|
||||
}[];
|
||||
has_more: number;
|
||||
};
|
||||
|
||||
export const getGroupBlockedMemberFactory = apiFactory<GetGroupBlockedMemberResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/blockedmems/list`);
|
||||
|
||||
/**
|
||||
* Get group blocked member
|
||||
*
|
||||
* @param payload payload
|
||||
* @param groupId group id
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getGroupBlockedMember(payload: GetGroupBlockedMemberPayload, groupId: string) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
page: payload.page ?? 1,
|
||||
count: payload.count ?? 50,
|
||||
imei: ctx.imei,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import { GroupMessage, type TGroupMessage } from "../models/index.js";
|
||||
|
||||
export type GetGroupChatHistoryResponse = {
|
||||
lastActionId: string;
|
||||
lastActionIdOther: string;
|
||||
more: number;
|
||||
groupMsgs: GroupMessage[];
|
||||
};
|
||||
|
||||
export const getGroupChatHistoryFactory = apiFactory<GetGroupChatHistoryResponse>()((api, ctx, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/history`);
|
||||
|
||||
/**
|
||||
* Get group chat history
|
||||
*
|
||||
* @param groupId group id
|
||||
* @param count count of messages to return (default: 50)
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getGroupChatHistory(groupId: string, count: number = 50) {
|
||||
const params = {
|
||||
grid: groupId,
|
||||
count: count,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
let data = result.data as unknown as GetGroupChatHistoryResponse | string;
|
||||
|
||||
if (typeof data === "string") {
|
||||
data = JSON.parse(data) as GetGroupChatHistoryResponse;
|
||||
}
|
||||
|
||||
for (let i = 0; i < data.groupMsgs.length; i++) {
|
||||
data.groupMsgs[i] = new GroupMessage(ctx.uid, data.groupMsgs[i] as unknown as TGroupMessage);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import type { GroupInfo } from "../models/index.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
export type GroupInfoResponse = {
|
||||
removedsGroup: string[];
|
||||
unchangedsGroup: string[];
|
||||
gridInfoMap: {
|
||||
[groupId: string]: GroupInfo & {
|
||||
memVerList: string[];
|
||||
pendingApprove: GroupInfoPendingApprove;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export type GroupInfoPendingApprove = {
|
||||
time: number;
|
||||
uids: string[] | null;
|
||||
};
|
||||
|
||||
export const getGroupInfoFactory = apiFactory<GroupInfoResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/getmg-v2`);
|
||||
|
||||
/**
|
||||
* Get group information
|
||||
*
|
||||
* @param groupId Group ID or list of group IDs
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getGroupInfo(groupId: string | string[]) {
|
||||
if (!Array.isArray(groupId)) groupId = [groupId];
|
||||
|
||||
const params = {
|
||||
gridVerMap: JSON.stringify(
|
||||
groupId.reduce<Record<string, number>>((acc, id) => {
|
||||
acc[id] = 0;
|
||||
return acc;
|
||||
}, {}),
|
||||
),
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt message");
|
||||
|
||||
const response = await utils.request(serviceURL, {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
params: encryptedParams,
|
||||
}),
|
||||
});
|
||||
|
||||
return utils.resolve(response);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ZaloApiError } from "../Errors/ZaloApiError.js";
|
||||
import { apiFactory } from "../utils.js";
|
||||
|
||||
import type { GroupInfo, GroupTopic } from "../models/index.js";
|
||||
|
||||
export type GetGroupInviteBoxInfoPayload = {
|
||||
groupId: string;
|
||||
mpage?: number;
|
||||
mcount?: number;
|
||||
};
|
||||
|
||||
export type GetGroupInviteBoxInfoResponse = {
|
||||
groupInfo: GroupInfo & {
|
||||
topic?: Omit<GroupTopic, "action">;
|
||||
};
|
||||
inviterInfo: {
|
||||
id: string;
|
||||
dName: string;
|
||||
zaloName: string;
|
||||
avatar: string;
|
||||
avatar_25: string;
|
||||
accountStatus: number;
|
||||
type: number;
|
||||
};
|
||||
grCreatorInfo: {
|
||||
id: string;
|
||||
dName: string;
|
||||
zaloName: string;
|
||||
avatar: string;
|
||||
avatar_25: string;
|
||||
accountStatus: number;
|
||||
type: number;
|
||||
};
|
||||
expiredTs: string;
|
||||
type: number;
|
||||
};
|
||||
|
||||
export const getGroupInviteBoxInfoFactory = apiFactory<GetGroupInviteBoxInfoResponse>()((api, _, utils) => {
|
||||
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/inv-box/inv-info`);
|
||||
|
||||
/**
|
||||
* Get group invite box info
|
||||
*
|
||||
* @param payload - The payload of the request
|
||||
*
|
||||
* @throws {ZaloApiError}
|
||||
*/
|
||||
return async function getGroupInviteBoxInfo(payload: GetGroupInviteBoxInfoPayload) {
|
||||
const params = {
|
||||
grId: payload.groupId,
|
||||
mcount: payload.mcount ?? 10,
|
||||
mpage: payload.mpage ?? 1,
|
||||
};
|
||||
|
||||
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
||||
if (!encryptedParams) throw new ZaloApiError("Failed to encrypt params");
|
||||
|
||||
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
return utils.resolve(response, (result) => {
|
||||
const data = result.data as GetGroupInviteBoxInfoResponse;
|
||||
const topic = data.groupInfo.topic as GetGroupInviteBoxInfoResponse["groupInfo"]["topic"] & {
|
||||
params: unknown;
|
||||
};
|
||||
if (typeof topic.params == "string") {
|
||||
const params = JSON.parse(topic.params);
|
||||
if (typeof params.extra == "string") {
|
||||
params.extra = JSON.parse(params.extra);
|
||||
}
|
||||
|
||||
topic.params = params;
|
||||
}
|
||||
|
||||
return data as GetGroupInviteBoxInfoResponse;
|
||||
});
|
||||
};
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user