├── zlapi ├── simple │ ├── __init__.py │ └── _state.py ├── _threads.py ├── _package.py ├── Async │ ├── __init__.py │ └── _state.py ├── _core.py ├── __init__.py ├── _aevents.py ├── models.py ├── _objects.py ├── _exception.py ├── logging.py ├── _state.py ├── _message.py ├── _util.py └── _parse_message.py ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── LICENSE ├── setup.py ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── README.md /zlapi/simple/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | from ._async import ZaloAPI 4 | 5 | -------------------------------------------------------------------------------- /zlapi/_threads.py: -------------------------------------------------------------------------------- 1 | from ._core import Enum 2 | 3 | class ThreadType(Enum): 4 | """Used to specify what type of Zalo thread is being used.""" 5 | 6 | USER = 0 7 | GROUP = 1 -------------------------------------------------------------------------------- /zlapi/_package.py: -------------------------------------------------------------------------------- 1 | import time 2 | import signal 3 | import os, json 4 | import threading 5 | import asyncio, aiohttp 6 | import pkgutil, hashlib 7 | import inspect, importlib, functools 8 | 9 | -------------------------------------------------------------------------------- /zlapi/Async/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """Zalo API for Python 3 | 4 | :copyright: (c) 2024 by Lê Quốc Việt (Vexx). 5 | """ 6 | from ._async import ZaloAPI 7 | 8 | __all__ = ["ZaloAPI"] 9 | -------------------------------------------------------------------------------- /zlapi/_core.py: -------------------------------------------------------------------------------- 1 | import enum 2 | 3 | class Enum(enum.Enum): 4 | """Used internally by to support enumerations""" 5 | 6 | def __repr__(self): 7 | # For documentation: 8 | return "{}.{}".format(type(self).__name__, self.name) -------------------------------------------------------------------------------- /zlapi/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """Zalo API for Python 3 | 4 | :copyright: (c) 2024 by Lê Quốc Việt (Vexx). 5 | """ 6 | from .models import * 7 | from ._client import ZaloAPI 8 | 9 | __title__ = "zlapi" 10 | __version__ = "1.0.2" 11 | __description__ = "Zalo API (Website) for Python" 12 | 13 | __copyright__ = "Copyright 2024 by Vexx" 14 | 15 | __author__ = "Lê Quốc Việt" 16 | __email__ = "vrxxdev@gmail.com" 17 | 18 | __all__ = ["ZaloAPI"] 19 | -------------------------------------------------------------------------------- /zlapi/_aevents.py: -------------------------------------------------------------------------------- 1 | from ._core import Enum 2 | 3 | class GroupEventType(Enum): 4 | """Used to specify which type of Zalo group event is being used.""" 5 | 6 | JOIN = "join" 7 | LEAVE = "leave" 8 | UPDATE = "update" 9 | UNKNOWN = "unknown" 10 | REACTION = "reaction" 11 | NEW_LINK = "new_link" 12 | ADD_ADMIN = "add_admin" 13 | REMOVE_ADMIN = "remove_admin" 14 | JOIN_REQUEST = "join_request" 15 | BLOCK_MEMBER = "block_member" 16 | REMOVE_MEMBER = "remove_member" 17 | UPDATE_SETTING = "update_setting" 18 | 19 | 20 | class EventType(Enum): 21 | """Used to specify which type of Zalo user event is being used.""" 22 | 23 | REACTION = "reaction" 24 | -------------------------------------------------------------------------------- /zlapi/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import traceback 3 | 4 | from ._util import now, urllib 5 | from ._core import Enum 6 | from ._exception import ( 7 | ZaloAPIException, 8 | ZaloUserError, 9 | ZaloLoginError, 10 | LoginMethodNotSupport, 11 | EncodePayloadError, 12 | DecodePayloadError 13 | ) 14 | from ._threads import ThreadType 15 | from ._aevents import GroupEventType, EventType 16 | from ._message import MessageReaction, MessageStyle, MultiMsgStyle, Message, Mention, MultiMention 17 | from ._objects import User, Group, MessageObject, ContextObject, EventObject 18 | 19 | from .logging import Logging 20 | 21 | logger = Logging(theme="catppuccin-mocha", log_text_color="black") -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | --- 11 | 12 | ## Description of the problem 13 | Example: Logging in fails when the character `#` is in the password. A specific password that fails is `password_with_#_char` 14 | 15 | ## Code to reproduce 16 | ```py 17 | # Example code 18 | from zlapi import ZaloAPI 19 | 20 | client = ZaloAPI("phone", "password_with_#_char") 21 | ``` 22 | 23 | ## Traceback 24 | ``` 25 | # Traceback Login Error 26 | ``` 27 | 28 | ## Environment information 29 | - Python version 30 | - `zlapi` version 31 | - If relevant, output from `python -m pip list` 32 | 33 | If you have done any research, include that. 34 | Make sure to redact all personal information. 35 | -------------------------------------------------------------------------------- /zlapi/_objects.py: -------------------------------------------------------------------------------- 1 | from munch import DefaultMunch 2 | from dataclasses import dataclass 3 | 4 | class User(DefaultMunch): 5 | def __repr__(self): 6 | attrs = [f"{key}={value!r}" for key, value in self.__dict__.items()] 7 | return f"User({', '.join(attrs)})" 8 | 9 | 10 | class Group(DefaultMunch): 11 | def __repr__(self): 12 | attrs = [f"{key}={value!r}" for key, value in self.__dict__.items()] 13 | return f"Group({', '.join(attrs)})" 14 | 15 | 16 | class ContextObject(DefaultMunch): 17 | def __repr__(self): 18 | attrs = [f"{key}={value!r}" for key, value in self.__dict__.items()] 19 | return f"Context({', '.join(attrs)})" 20 | 21 | 22 | class MessageObject(DefaultMunch): 23 | def __repr__(self): 24 | attrs = [f"{key}={value!r}" for key, value in self.__dict__.items()] 25 | return f"Message({', '.join(attrs)})" 26 | 27 | 28 | class EventObject(DefaultMunch): 29 | def __repr__(self): 30 | attrs = [f"{key}={value!r}" for key, value in self.__dict__.items()] 31 | return f"GroupEvent({', '.join(attrs)})" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Lê Quốc Việt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | from pathlib import Path 3 | 4 | VERSION = '1.0.2' 5 | DESCRIPTION = 'zlapi: Zalo API for Python' 6 | this_directory = Path(__file__).parent 7 | LONG_DESCRIPTION = (this_directory / "README.md").read_text() 8 | 9 | # Setting up 10 | setup( 11 | name="zlapi", 12 | version=VERSION, 13 | author="Lê Quốc Việt (Vexx)", 14 | author_email="", 15 | description=DESCRIPTION, 16 | long_description_content_type="text/markdown", 17 | long_description=LONG_DESCRIPTION, 18 | packages=find_packages(), 19 | install_requires=['requests', 'aiohttp', 'aenum', 'attr', 'pycryptodome', 'datetime', 'munch', 'websockets'], 20 | keywords=['python', 'zalo', 'api', 'zalo api', 'zalo chat', 'requests'], 21 | classifiers=[ 22 | "Development Status :: 3 - Alpha", 23 | "Intended Audience :: Developers", 24 | "License :: OSI Approved :: MIT License", 25 | "Operating System :: OS Independent", 26 | "Natural Language :: English", 27 | "Programming Language :: Python", 28 | "Programming Language :: Python :: 3", 29 | "Programming Language :: Python :: Implementation :: CPython", 30 | "Programming Language :: Python :: Implementation :: PyPy", 31 | "Topic :: Communications :: Chat", 32 | "Topic :: Internet :: WWW/HTTP", 33 | "Topic :: Internet :: WWW/HTTP :: Dynamic Content", 34 | "Topic :: Software Development :: Libraries", 35 | "Topic :: Software Development :: Libraries :: Python Modules" 36 | ] 37 | ) 38 | -------------------------------------------------------------------------------- /zlapi/_exception.py: -------------------------------------------------------------------------------- 1 | class ZaloAPIException(Exception): 2 | """Custom exception thrown by ``zaoapi``. 3 | 4 | All exceptions in the ``zaloapi`` module inherits this. 5 | """ 6 | 7 | class LoginMethodNotSupport(ZaloAPIException): 8 | """Raised by zaloapi if: 9 | 10 | - Using an unsupported login method. 11 | """ 12 | def __init__(self, message=None): 13 | self.message = message 14 | super().__init__(message) 15 | 16 | 17 | class ZaloLoginError(ZaloAPIException): 18 | def __init__(self, message=None): 19 | self.message = message 20 | super().__init__(message) 21 | 22 | 23 | class ZaloUserError(ZaloAPIException): 24 | """Thrown by ``zaloapi`` when wrong values are entered.""" 25 | def __init__(self, message=None): 26 | self.message = message 27 | super().__init__(message) 28 | 29 | 30 | class EncodePayloadError(ZaloAPIException): 31 | """Raised by ``zaloapi`` if: 32 | 33 | - The secret key is not correct to encode the payload 34 | - Payload data does not match. 35 | - A conflict occurred when encoding the payload. 36 | """ 37 | def __init__(self, message=None): 38 | self.message = message 39 | super().__init__(message) 40 | 41 | 42 | class DecodePayloadError(ZaloAPIException): 43 | """Raised by ``zaloapi`` if: 44 | 45 | - The secret key is not correct to decode the payload 46 | - Payload data does not match. 47 | - A conflict occurred when decoding the payload. 48 | """ 49 | def __init__(self, message=None): 50 | self.message = message 51 | super().__init__(message) 52 | 53 | -------------------------------------------------------------------------------- /zlapi/logging.py: -------------------------------------------------------------------------------- 1 | class Logging: 2 | def __init__(self, theme="default", text_color="white", log_text_color="black"): 3 | self.reset = "\x1b[0m" 4 | 5 | self.red = None 6 | self.blue = None 7 | self.green = None 8 | self.white = None 9 | self.black = None 10 | self.orange = None 11 | self.yellow = None 12 | self.magenta = None 13 | self.theme = str(theme).lower() 14 | 15 | self.load_color_scheme() 16 | 17 | self.textcolor = ( 18 | "\x1b[30m" if text_color.lower() == "black" else 19 | "\x1b[37m" if text_color.lower() == "white" else 20 | text_color 21 | ) 22 | self.log_text_color = ( 23 | self.black if log_text_color.lower() == "black" else 24 | self.white if log_text_color.lower() == "white" else 25 | log_text_color 26 | ) 27 | 28 | def load_color_scheme(self): 29 | if self.theme == "default": 30 | 31 | self.red = "\x1b[41m" 32 | self.blue = "\x1b[44m" 33 | self.green = "\x1b[42m" 34 | self.white = "\x1b[37m" 35 | self.black = "\x1b[30m" 36 | self.orange = None 37 | self.yellow = "\x1b[43m" 38 | self.magenta = "\x1b[45m" 39 | 40 | elif self.theme == "catppuccin" or "catppuccin-mocha": 41 | 42 | self.red = "\x1b[48;2;243;139;168m" 43 | self.blue = "\x1b[48;2;137;180;250m" 44 | self.green = "\x1b[48;2;166;227;161m" 45 | self.white = "\x1b[38;2;205;214;244m" 46 | self.black = "\x1b[38;2;17;17;27m" 47 | self.orange = "\x1b[48;2;250;179;135m" 48 | self.yellow = "\x1b[48;2;249;226;175m" 49 | self.magenta = "\x1b[48;2;203;166;247m" 50 | 51 | else: 52 | self.theme = "default" 53 | self.load_color_scheme() 54 | self.info("Theme not supported yet! Switch to default theme.") 55 | 56 | def info(self, text: str) -> None: 57 | text = str(text) 58 | print(f"{self.blue} {self.log_text_color}INFO {self.reset} {self.textcolor}{text}") 59 | 60 | def debug(self, text: str) -> None: 61 | text = str(text) 62 | print(f"{self.magenta} {self.log_text_color}DEBUG {self.reset} {self.textcolor}{text}") 63 | 64 | def success(self, text: str) -> None: 65 | text = str(text) 66 | print(f"{self.green} {self.log_text_color}SUCCESS {self.reset} {self.textcolor}{text}") 67 | 68 | def login(self, text: str) -> None: 69 | text = str(text) 70 | print(f"{self.green} {self.log_text_color}LOGIN {self.reset} {self.textcolor}{text}") 71 | 72 | def error(self, text: str) -> None: 73 | text = str(text) 74 | print(f"{self.red} {self.log_text_color}ERROR {self.reset} {self.textcolor}{text}") 75 | 76 | def warning(self, text: str) -> None: 77 | text = str(text) 78 | print(f"{self.orange or self.yellow} {self.log_text_color}WARN {self.reset} {self.textcolor}{text}") -------------------------------------------------------------------------------- /zlapi/simple/_state.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import attr 3 | import random 4 | import asyncio 5 | import aiohttp 6 | 7 | from .. import _util, _exception 8 | 9 | class State(object): 10 | def __init__(cls): 11 | cls._config = {} 12 | cls._headers = _util.HEADERS 13 | cls._cookies = _util.COOKIES 14 | cls.user_id = None 15 | cls.user_imei = None 16 | cls._loggedin = False 17 | 18 | def is_logged_in(cls): 19 | return cls._loggedin 20 | 21 | def set_cookies(cls, cookies): 22 | cls._cookies = cookies 23 | 24 | def set_secret_key(cls, secret_key): 25 | cls._config["secret_key"] = secret_key 26 | 27 | async def get_cookies(cls): 28 | return cls._cookies 29 | 30 | async def get_secret_key(cls): 31 | return cls._config.get("secret_key") 32 | 33 | async def _get(cls, *args, **kwargs): 34 | async with aiohttp.ClientSession() as session: 35 | async with session.get(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) as response: 36 | return await response.json(content_type=None) 37 | 38 | async def _post(cls, *args, **kwargs): 39 | async with aiohttp.ClientSession() as session: 40 | async with session.post(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) as response: 41 | return await response.json(content_type=None) 42 | 43 | async def login(cls, phone, password, imei, session_cookies=None, user_agent=None): 44 | if cls._cookies and cls._config.get("secret_key"): 45 | cls._loggedin = True 46 | return 47 | 48 | if user_agent: 49 | cls._headers["User-Agent"] = user_agent 50 | 51 | if cls._cookies: 52 | params = { 53 | "imei": imei, 54 | } 55 | try: 56 | data = await cls._get("https://vrxx1337.vercel.app/zalo/api/login", params=params) 57 | 58 | if data.get("error_code") == 0: 59 | cls._config = data.get("data") 60 | 61 | if cls._config.get("secret_key"): 62 | cls._loggedin = True 63 | cls.user_id = cls._config.get("send2me_id") 64 | cls.user_imei = imei 65 | 66 | else: 67 | cls._loggedin = False 68 | raise _exception.ZaloLoginError("Unable to get `secret key`.") 69 | 70 | else: 71 | error = data.get("error_code") 72 | content = data.get("error_message") 73 | raise _exception.ZaloLoginError(f"Error #{error} when logging in: {content}") 74 | 75 | except _exception.ZaloLoginError as e: 76 | raise _exception.ZaloLoginError(str(e)) 77 | 78 | except Exception as e: 79 | raise _exception.ZaloLoginError(f"An error occurred while logging in! {str(e)}") 80 | 81 | else: 82 | raise _exception.LoginMethodNotSupport("Login method is not supported yet") 83 | 84 | 85 | -------------------------------------------------------------------------------- /zlapi/Async/_state.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import attr 3 | import random 4 | import asyncio 5 | import aiohttp 6 | 7 | from .. import _util, _exception 8 | 9 | class State(object): 10 | def __init__(cls): 11 | cls._config = {} 12 | cls._headers = _util.HEADERS 13 | cls._cookies = _util.COOKIES 14 | cls.user_id = None 15 | cls.user_imei = None 16 | cls._loggedin = False 17 | 18 | def is_logged_in(cls): 19 | return cls._loggedin 20 | 21 | def set_cookies(cls, cookies): 22 | cls._cookies = cookies 23 | 24 | def set_secret_key(cls, secret_key): 25 | cls._config["secret_key"] = secret_key 26 | 27 | async def get_cookies(cls): 28 | return cls._cookies 29 | 30 | async def get_secret_key(cls): 31 | return cls._config.get("secret_key") 32 | 33 | async def _get(cls, *args, **kwargs): 34 | async with aiohttp.ClientSession() as session: 35 | async with session.get(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) as response: 36 | return await response.json(content_type=None) 37 | 38 | async def _post(cls, *args, **kwargs): 39 | async with aiohttp.ClientSession() as session: 40 | async with session.post(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) as response: 41 | return await response.json(content_type=None) 42 | 43 | async def login(cls, phone, password, imei, session_cookies=None, user_agent=None): 44 | if cls._cookies and cls._config.get("secret_key"): 45 | cls._loggedin = True 46 | return 47 | 48 | if user_agent: 49 | cls._headers["User-Agent"] = user_agent 50 | 51 | if cls._cookies: 52 | params = { 53 | "zpw_ver": 647, 54 | "type": 30, 55 | "imei": imei, 56 | "computer_name": "Web", 57 | "ts": _util.now(), 58 | "nretry": 0 59 | } 60 | try: 61 | data = await cls._get("https://wpa.chat.zalo.me/api/login/getLoginInfo", params=params) 62 | 63 | if data.get("error_code") == 0: 64 | cls._config = data.get("data") 65 | 66 | if cls._config.get("zpw_enk"): 67 | cls.user_imei = imei 68 | cls.user_id = cls._config.get("send2me_id") 69 | cls._config["secret_key"] = cls._config.get("zpw_enk") 70 | 71 | else: 72 | cls._loggedin = False 73 | raise _exception.ZaloLoginError("Unable to get `secret key`.") 74 | 75 | else: 76 | error = data.get("error_code") 77 | content = data.get("error_message") 78 | raise _exception.ZaloLoginError(f"Error #{error} when logging in: {content}") 79 | 80 | except _exception.ZaloLoginError as e: 81 | raise _exception.ZaloLoginError(str(e)) 82 | 83 | except Exception as e: 84 | raise _exception.ZaloLoginError(f"An error occurred while logging in! {str(e)}") 85 | 86 | else: 87 | raise _exception.LoginMethodNotSupport("Login method is not supported yet") 88 | 89 | 90 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct - zlapi 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to a positive environment for our 15 | community include: 16 | 17 | * Demonstrating empathy and kindness toward other people 18 | * Being respectful of differing opinions, viewpoints, and experiences 19 | * Giving and gracefully accepting constructive feedback 20 | * Accepting responsibility and apologizing to those affected by our mistakes, 21 | and learning from the experience 22 | * Focusing on what is best not just for us as individuals, but for the 23 | overall community 24 | 25 | Examples of unacceptable behavior include: 26 | 27 | * The use of sexualized language or imagery, and sexual attention or 28 | advances 29 | * Trolling, insulting or derogatory comments, and personal or political attacks 30 | * Public or private harassment 31 | * Publishing others' private information, such as a physical or email 32 | address, without their explicit permission 33 | * Other conduct which could reasonably be considered inappropriate in a 34 | professional setting 35 | 36 | ## Our Responsibilities 37 | 38 | Project maintainers are responsible for clarifying and enforcing our standards of 39 | acceptable behavior and will take appropriate and fair corrective action in 40 | response to any instances of unacceptable behavior. 41 | 42 | Project maintainers have the right and responsibility to remove, edit, or reject 43 | comments, commits, code, wiki edits, issues, and other contributions that are 44 | not aligned to this Code of Conduct, or to ban 45 | temporarily or permanently any contributor for other behaviors that they deem 46 | inappropriate, threatening, offensive, or harmful. 47 | 48 | ## Scope 49 | 50 | This Code of Conduct applies within all community spaces, and also applies when 51 | an individual is officially representing the community in public spaces. 52 | Examples of representing our community include using an official e-mail address, 53 | posting via an official social media account, or acting as an appointed 54 | representative at an online or offline event. 55 | 56 | ## Enforcement 57 | 58 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 59 | reported to the community leaders responsible for enforcement at . 60 | All complaints will be reviewed and investigated promptly and fairly. 61 | 62 | All community leaders are obligated to respect the privacy and security of the 63 | reporter of any incident. 64 | 65 | ## Attribution 66 | 67 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version 68 | [1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and 69 | [2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md), 70 | and was generated by [contributing-gen](https://github.com/bttger/contributing-gen). -------------------------------------------------------------------------------- /zlapi/_state.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import attr 3 | import random 4 | import requests, json 5 | 6 | from . import _util, _exception 7 | 8 | headers = { 9 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", 10 | "Accept": "application/json, text/plain, */*", 11 | "sec-ch-ua": "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"", 12 | "sec-ch-ua-mobile": "?0", 13 | "sec-ch-ua-platform": "\"Linux\"", 14 | "origin": "https://chat.zalo.me", 15 | "sec-fetch-site": "same-site", 16 | "sec-fetch-mode": "cors", 17 | "sec-fetch-dest": "empty", 18 | "Accept-Encoding": "gzip", 19 | "referer": "https://chat.zalo.me/", 20 | "accept-language": "vi-VN,vi;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5", 21 | } 22 | class State(object): 23 | def __init__(cls): 24 | cls._config = {} 25 | cls._headers = _util.HEADERS 26 | cls._cookies = _util.COOKIES 27 | cls._session = requests.Session() 28 | cls.user_id = None 29 | cls.user_imei = None 30 | cls._loggedin = False 31 | 32 | def get_cookies(cls): 33 | return cls._cookies 34 | 35 | def set_cookies(cls, cookies): 36 | cls._cookies = cookies 37 | 38 | def get_secret_key(cls): 39 | return cls._config.get("secret_key") 40 | 41 | def set_secret_key(cls, secret_key): 42 | cls._config["secret_key"] = secret_key 43 | 44 | def _get(cls, *args, **kwargs): 45 | sessionObj = cls._session.get(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) 46 | 47 | return sessionObj 48 | 49 | def _post(cls, *args, **kwargs): 50 | sessionObj = cls._session.post(*args, **kwargs, headers=cls._headers, cookies=cls._cookies) 51 | return sessionObj 52 | 53 | def is_logged_in(cls): 54 | return cls._loggedin 55 | 56 | def login(cls, phone, password, imei, session_cookies=None, user_agent=None): 57 | if cls._cookies and cls._config.get("secret_key"): 58 | cls._loggedin = True 59 | return 60 | 61 | if user_agent: 62 | cls._headers["User-Agent"] = user_agent 63 | 64 | if cls._cookies: 65 | params = { 66 | "imei": imei, 67 | } 68 | try: 69 | url = f"https://wpa.chat.zalo.me/api/login/getLoginInfo?imei={imei}&type=30&client_version=645&computer_name=Web&ts={_util.now()}" 70 | response = requests.get(url, headers=headers, cookies=cls._cookies) 71 | data = response.json() 72 | zpw = data["data"]["zpw_ws"] 73 | uid = data["data"]["uid"] 74 | phone = data["data"]["phone_number"] 75 | key = data["data"]["zpw_enk"] 76 | 77 | content = { 78 | "data": { 79 | "phone_number": str(phone), 80 | "secret_key": str(key), 81 | "send2me_id": str(uid), 82 | "zpw_ws": zpw, 83 | }, 84 | "error_code": 0 85 | } 86 | 87 | if content.get("error_code") == 0: 88 | cls._config = content.get("data") 89 | 90 | if cls._config.get("secret_key"): 91 | cls._loggedin = True 92 | cls.user_id = cls._config.get("send2me_id") 93 | cls.user_imei = imei 94 | 95 | else: 96 | cls._loggedin = False 97 | raise _exception.ZaloLoginError("Unable to get `secret key`.") 98 | 99 | else: 100 | error = data.get("error_code") 101 | content = data.get("error_message") 102 | raise _exception.ZaloLoginError(f"Error #{error} when logging in: {content}") 103 | 104 | except _exception.ZaloLoginError as e: 105 | raise _exception.ZaloLoginError(str(e)) 106 | 107 | except Exception as e: 108 | raise _exception.ZaloLoginError(f"An error occurred while logging in! {str(e)}") 109 | 110 | else: 111 | raise _exception.LoginMethodNotSupport("Login method is not supported yet") 112 | 113 | 114 | -------------------------------------------------------------------------------- /zlapi/_message.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from . import _util 4 | from ._core import Enum 5 | from ._parse_message import Parse 6 | 7 | class Message: 8 | def __init__(self, text=None, style=None, mention=None, parse_mode=None): 9 | self.text = text 10 | self.style = str(style) if style else None 11 | self.mention = str(mention) if mention else None 12 | self.parse_mode = str(parse_mode) if parse_mode else None 13 | 14 | 15 | if parse_mode: 16 | styles = json.loads(self.style)["styles"] if self.style else [] 17 | if self.parse_mode == "Markdown": 18 | 19 | self.text, self.parse_list = Parse(self.text, self.style, "Markdown") 20 | 21 | elif self.parse_mode == "HTML": 22 | 23 | self.text, self.parse_list = Parse(self.text, self.style, "HTML") 24 | 25 | else: 26 | raise ValueError("Invalid Parse Mode, Only Support `Markdown` & `HTML`") 27 | 28 | if len(self.parse_list) == 1 and not styles: 29 | 30 | element = self.parse_list[0] 31 | self.style = MessageStyle( 32 | offset=element["start"], 33 | length=element["length"], 34 | style=element["type"] 35 | ) 36 | 37 | elif len(self.parse_list) < 1: 38 | pass 39 | 40 | else: 41 | 42 | for element in self.parse_list: 43 | style = MessageStyle( 44 | offset=element["start"], 45 | length=element["length"], 46 | style=element["type"], 47 | auto_format=False 48 | ) 49 | styles.append(style) 50 | 51 | self.style = MultiMsgStyle(styles) 52 | 53 | self.style = str(self.style) if self.style else None 54 | 55 | 56 | 57 | def __repr__(self): 58 | return f"Message(text={self.text!r}, style={self.style!r}, mention={self.mention!r}, parse_mode={self.parse_mode!r})" 59 | 60 | 61 | class MessageStyle: 62 | def __new__(self, offset=0, length=1, style="font", color="ffffff", size="18", auto_format=True): 63 | self.offset = offset 64 | self.length = length 65 | self.style = style 66 | if type(offset) != int and type(length) != int: 67 | raise ValueError("Invalid Length, Offset! Length and Offset must be integers") 68 | 69 | if style == "bold": 70 | self.style = "b" 71 | elif style == "italic": 72 | self.style = "i" 73 | elif style == "underline": 74 | self.style = "u" 75 | elif style == "strike": 76 | self.style = "s" 77 | elif style == "color": 78 | self.style = "c_" + str(color).replace("#", "") 79 | elif style == "font": 80 | self.style = "f_" + str(size) 81 | else: 82 | self.style = "f_18" 83 | 84 | if auto_format: 85 | self.styleFormat = json.dumps({ 86 | "styles": [{ 87 | "start": self.offset, 88 | "len": self.length, 89 | "st": self.style 90 | }], 91 | "ver": 0 92 | }) 93 | else: 94 | self.styleFormat = { 95 | "start": self.offset, 96 | "len": self.length, 97 | "st": self.style 98 | } 99 | 100 | return self.styleFormat 101 | 102 | 103 | class MultiMsgStyle: 104 | def __init__(self, listStyle): 105 | styles = [] 106 | for style in listStyle: 107 | styles.append(style) 108 | 109 | self.styleFormat = json.dumps({ 110 | "styles": styles, 111 | "ver": 0 112 | }) 113 | 114 | def __str__(self): 115 | return self.styleFormat 116 | 117 | 118 | class MessageReaction: 119 | def __new__(self, messageObject, auto_format=True): 120 | self.msgId = messageObject.msgId 121 | self.cliMsgId = messageObject.cliMsgId 122 | self.msgType = _util.getClientMessageType(messageObject.msgType) 123 | if not isinstance(msgType, int): 124 | raise ValueError("Msg Type must be int") 125 | 126 | if auto_format: 127 | self.reactionFormat = [{ 128 | "gMsgID": int(self.msgId), 129 | "cMsgID": int(self.cliMsgId), 130 | "msgType": int(self.msgType) 131 | }] 132 | 133 | else: 134 | self.reactionFormat = { 135 | "gMsgID": int(self.msgId), 136 | "cMsgID": int(self.cliMsgId), 137 | "msgType": int(self.msgType) 138 | } 139 | 140 | return self.reactionFormat 141 | 142 | 143 | class Mention: 144 | def __new__(self, uid, length=1, offset=0, auto_format=True): 145 | self.user_id = uid 146 | self.offset = offset 147 | self.length = length 148 | self.type = 1 if uid == "-1" else 0 149 | if type(offset) != int and type(length) != int: 150 | raise ValueError("Invalid Length, Offset! Length and Offset must be integers") 151 | 152 | if auto_format: 153 | self.mentionFormat = json.dumps([{ 154 | "pos": self.offset, 155 | "len": self.length, 156 | "uid": self.user_id, 157 | "type": self.type 158 | }]) 159 | else: 160 | self.mentionFormat = { 161 | "pos": self.offset, 162 | "len": self.length, 163 | "uid": self.user_id, 164 | "type": self.type 165 | } 166 | 167 | return self.mentionFormat 168 | 169 | 170 | class MultiMention: 171 | def __init__(self, listMention): 172 | mentions = [] 173 | for mention in listMention: 174 | mentions.append(mention) 175 | 176 | self.mentionFormat = json.dumps(mentions) 177 | 178 | def __str__(self): 179 | return self.mentionFormat -------------------------------------------------------------------------------- /zlapi/_util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | import time, datetime 4 | import urllib.parse, json 5 | import gzip, base64, zlib 6 | 7 | from . import _exception 8 | from Crypto.Cipher import AES 9 | from ._aevents import GroupEventType 10 | 11 | #: Default headers 12 | HEADERS = { 13 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", 14 | "Accept": "application/json, text/plain, */*", 15 | "sec-ch-ua": "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"", 16 | "sec-ch-ua-mobile": "?0", 17 | "sec-ch-ua-platform": "\"Linux\"", 18 | "origin": "https://chat.zalo.me", 19 | "sec-fetch-site": "same-site", 20 | "sec-fetch-mode": "cors", 21 | "sec-fetch-dest": "empty", 22 | "Accept-Encoding": "gzip", 23 | "referer": "https://chat.zalo.me/", 24 | "accept-language": "vi-VN,vi;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5", 25 | } 26 | 27 | #: Default cookies 28 | COOKIES = {} 29 | 30 | 31 | def now(): 32 | return int(time.time() * 1000) 33 | 34 | def formatTime(format, ftime=now()): 35 | dt = datetime.datetime.fromtimestamp(ftime / 1000) 36 | # vietnam_tz = pytz.timezone('Asia/Ho_Chi_Minh') 37 | # dt_vietnam = vietnam_tz.fromutc(dt) 38 | 39 | formatted_time = dt.strftime(format) 40 | 41 | return formatted_time 42 | 43 | 44 | def getHeader(buffer): 45 | if len(buffer) < 4: 46 | raise ValueError("Invalid header") 47 | 48 | return [buffer[0], int.from_bytes(buffer[1:3], "little"), buffer[3]] 49 | 50 | 51 | def getClientMessageType(msgType): 52 | if (msgType == "webchat"): return 1 53 | if (msgType == "chat.voice"): return 31 54 | if (msgType == "chat.photo"): return 32 55 | if (msgType == "chat.sticker"): return 36 56 | if (msgType == "chat.doodle"): return 37 57 | if (msgType == "chat.recommended"): return 38 58 | if (msgType == "chat.link"): return 38 59 | if (msgType == "chat.location.new"): return 43 60 | if (msgType == "chat.video.msg"): return 44 61 | if (msgType == "share.file"): return 46 62 | if (msgType == "chat.gif"): return 49 63 | 64 | return 1 65 | 66 | 67 | def getGroupEventType(act): 68 | if (act == "join_request"): return GroupEventType.JOIN_REQUEST 69 | if (act == "join"): return GroupEventType.JOIN 70 | if (act == "leave"): return GroupEventType.LEAVE 71 | if (act == "remove_member"): return GroupEventType.REMOVE_MEMBER 72 | if (act == "block_member"): return GroupEventType.BLOCK_MEMBER 73 | if (act == "update_setting"): return GroupEventType.UPDATE_SETTING 74 | if (act == "update"): return GroupEventType.UPDATE 75 | if (act == "new_link"): return GroupEventType.NEW_LINK 76 | if (act == "add_admin"): return GroupEventType.ADD_ADMIN 77 | if (act == "remove_admin"): return GroupEventType.REMOVE_ADMIN 78 | 79 | return GroupEventType.UNKNOWN 80 | 81 | 82 | def dict_to_raw_cookies(cookies_dict): 83 | try: 84 | cookie_string = "; ".join(f"{key}={value}" for key, value in cookies_dict.items()) 85 | if not cookie_string: 86 | return None 87 | 88 | return cookie_string 89 | 90 | except: 91 | return None 92 | 93 | 94 | def _pad(s, block_size): 95 | padding_length = block_size - len(s) % block_size 96 | 97 | return s + bytes([padding_length]) * padding_length 98 | 99 | 100 | def _unpad(s, block_size): 101 | padding_length = s[-1] 102 | 103 | return s[:-padding_length] 104 | 105 | 106 | def zalo_encode(params, key): 107 | try: 108 | key = base64.b64decode(key) 109 | iv = bytes.fromhex("00000000000000000000000000000000") 110 | cipher = AES.new(key, AES.MODE_CBC, iv) 111 | plaintext = json.dumps(params).encode() 112 | padded_plaintext = _pad(plaintext, AES.block_size) 113 | ciphertext = cipher.encrypt(padded_plaintext) 114 | 115 | return base64.b64encode(ciphertext).decode() 116 | 117 | except Exception as e: 118 | raise _exception.EncodePayloadError(f"Unable to encode payload! Error: {e}") 119 | 120 | 121 | def zalo_decode(params, key): 122 | try: 123 | params = urllib.parse.unquote(params) 124 | key = base64.b64decode(key) 125 | iv = bytes.fromhex("00000000000000000000000000000000") 126 | cipher = AES.new(key, AES.MODE_CBC, iv) 127 | ciphertext = base64.b64decode(params.encode()) 128 | padded_plaintext = cipher.decrypt(ciphertext) 129 | plaintext = _unpad(padded_plaintext, AES.block_size) 130 | plaintext = plaintext.decode("utf-8") 131 | 132 | if isinstance(plaintext, str): 133 | plaintext = json.loads(plaintext) 134 | 135 | return plaintext 136 | 137 | except Exception as e: 138 | raise _exception.DecodePayloadError(f"Unable to decode payload! Error: {e}") 139 | 140 | 141 | def zws_decode(parsed, key): 142 | payload = parsed.get("data") 143 | encrypt_type = parsed.get("encrypt") 144 | if not payload or not key: 145 | return 146 | 147 | try: 148 | if encrypt_type == 0: 149 | 150 | decoded_data = payload 151 | 152 | elif encrypt_type == 1: 153 | 154 | decrypted_data = base64.b64decode(payload) 155 | decompressed_data = gzip.decompress(decrypted_data) 156 | decoded_data = decompressed_data.decode("utf-8") 157 | 158 | elif encrypt_type == 2: 159 | 160 | data_bytes = base64.b64decode(urllib.parse.unquote(payload)) 161 | if len(data_bytes) >= 48: 162 | 163 | iv = data_bytes[:16] 164 | additional_data = data_bytes[16:32] 165 | data_source = data_bytes[32:] 166 | decryptor = AES.new(base64.b64decode(key), AES.MODE_GCM, nonce=iv) 167 | decryptor.update(additional_data) 168 | decrypted_data = decryptor.decrypt(data_source)[:-16] 169 | decompressed_data = zlib.decompress(decrypted_data, wbits=16) 170 | decoded_data = decompressed_data.decode("utf-8") 171 | 172 | else: 173 | 174 | decoded_data = None 175 | 176 | if not decoded_data: 177 | return 178 | 179 | return json.loads(decoded_data) 180 | 181 | except Exception as e: 182 | # return 183 | raise _exception.DecodePayloadError(f"Unable to decode payload! Error: {e}") -------------------------------------------------------------------------------- /zlapi/_parse_message.py: -------------------------------------------------------------------------------- 1 | def Parse(text, styles=None, parse_mode=None): 2 | styles = styles or [] 3 | if parse_mode == "Markdown": 4 | new_text, parse_list = parse_markdown(text) 5 | else: 6 | new_text, parse_list = markdown_message(text) 7 | 8 | return new_text, parse_list 9 | 10 | 11 | def parse_markdown(text): 12 | """Parses Markdown text and returns a list of Markdown elements. 13 | 14 | Args: 15 | text (str): The Markdown text to parse. 16 | 17 | Returns: 18 | list: A list of dictionaries, each representing a Markdown element. 19 | Each dictionary has the following keys: 20 | - 'start': The starting index of the element in the text. 21 | - 'end': The ending index of the element in the text. 22 | - 'length': The length of the element in the text. 23 | - 'text': The text content of the element. 24 | - 'char_len': The length of the Markdown character used for the element. 25 | - 'type': The type of Markdown element (e.g., 'bold', 'italic'). 26 | """ 27 | 28 | markdown_elements = [] 29 | markdown = { 30 | "**": "bold", 31 | "__": "underline", 32 | "_": "italic", 33 | "~~": "strike" 34 | } 35 | 36 | temp_text = text 37 | while any(temp_text.count(char) >= 2 for char in markdown.keys()): 38 | 39 | markup_start_positions = { 40 | char: temp_text.find(char) 41 | for char in markdown.keys() 42 | } 43 | 44 | 45 | sorted_markup_start_positions = dict(sorted(markup_start_positions.items(), key=lambda item: item[1])) 46 | 47 | for char, start in sorted_markup_start_positions.items(): 48 | if start < 0: 49 | continue 50 | 51 | end = temp_text.rfind(char, start + len(char)) 52 | 53 | if temp_text[start + len(char):end].count(char) >= 2: 54 | end = temp_text.find(char, start + len(char)) 55 | 56 | if end < 0: 57 | continue 58 | 59 | element = { 60 | "start": start, 61 | "end": end, 62 | "length": end - start - len(char) + 1, 63 | "text": temp_text[start + len(char):end], 64 | "char_len": len(char), 65 | "type": markdown[char] 66 | } 67 | markdown_elements.append(element) 68 | 69 | temp_text = temp_text[:start] + temp_text[start + len(char):end] + temp_text[end + len(char):] 70 | break 71 | 72 | markdown_elements = sorted(markdown_elements, key=lambda x: x['start']) 73 | 74 | for element in markdown_elements: 75 | text = text[:element["start"]] + text[element["start"] + element["char_len"]:element["end"]] + text[element["end"] + element["char_len"]:] 76 | element["start"] -= 1 77 | element["end"] += 2 78 | 79 | return text, markdown_elements 80 | 81 | 82 | def markdown_message(text): 83 | except_list = [] 84 | markdown_list = [] 85 | markdown_chars = { 86 | "": "bold", 87 | "": "italic", 88 | "": "underline", 89 | "": "strike", 90 | } 91 | for char, name in markdown_chars.items(): 92 | start = 0 93 | while True: 94 | start = text.find(char, start) 95 | if start == -1: 96 | break 97 | 98 | end = text.find("": "bold", 152 | "": "underline", 153 | "": "italic", 154 | "": "strike" 155 | } 156 | 157 | temp_text = text 158 | while any(temp_text.count(char) >= 1 and temp_text.count("= 1 for char in markdown.keys()): 159 | 160 | markup_start_positions = { 161 | char: temp_text.find(char) 162 | for char in markdown.keys() 163 | } 164 | 165 | 166 | sorted_markup_start_positions = dict(sorted(markup_start_positions.items(), key=lambda item: item[1])) 167 | 168 | for char, start in sorted_markup_start_positions.items(): 169 | if start < 0: 170 | continue 171 | 172 | end = temp_text.rfind("= 1: 175 | end = temp_text.find(" 2 | # Contributing to zlapi 3 | 4 | First off, thanks for taking the time to contribute! ❤️ 5 | 6 | All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉 7 | 8 | > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: 9 | > - Star the project 10 | > - Tweet about it 11 | > - Refer this project in your project's readme 12 | > - Mention the project at local meetups and tell your friends/colleagues 13 | 14 | 15 | ## Table of Contents 16 | 17 | - [Code of Conduct](#code-of-conduct) 18 | - [I Have a Question](#i-have-a-question) 19 | - [I Want To Contribute](#i-want-to-contribute) 20 | - [Reporting Bugs](#reporting-bugs) 21 | - [Suggesting Enhancements](#suggesting-enhancements) 22 | - [Your First Code Contribution](#your-first-code-contribution) 23 | - [Improving The Documentation](#improving-the-documentation) 24 | - [Styleguides](#styleguides) 25 | - [Commit Messages](#commit-messages) 26 | - [Join The Project Team](#join-the-project-team) 27 | 28 | 29 | ## Code of Conduct 30 | 31 | This project and everyone participating in it is governed by the 32 | [zlapi Code of Conduct](https://github.com/Its-VrxxDev/zlapiblob/master/CODE_OF_CONDUCT.md). 33 | By participating, you are expected to uphold this code. Please report unacceptable behavior 34 | to . 35 | 36 | 37 | ## I Have a Question 38 | 39 | > If you want to ask a question, we assume that you have read the available [Documentation](https://vrxx1337.dev/zlapi/docs/lastest). 40 | 41 | Before you ask a question, it is best to search for existing [Issues](https://github.com/Its-VrxxDev/zlapi/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. 42 | 43 | If you then still feel the need to ask a question and need clarification, we recommend the following: 44 | 45 | - Open an [Issue](https://github.com/Its-VrxxDev/zlapi/issues/new). 46 | - Provide as much context as you can about what you're running into. 47 | - Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. 48 | 49 | We will then take care of the issue as soon as possible. 50 | 51 | 65 | 66 | ## I Want To Contribute 67 | 68 | > ### Legal Notice 69 | > When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. 70 | 71 | ### Reporting Bugs 72 | 73 | 74 | #### Before Submitting a Bug Report 75 | 76 | A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. 77 | 78 | - Make sure that you are using the latest version. 79 | - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://vrxx1337.dev/zlapi/docs/lastest). If you are looking for support, you might want to check [this section](#i-have-a-question)). 80 | - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/Its-VrxxDev/zlapiissues?q=label%3Abug). 81 | - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. 82 | - Collect information about the bug: 83 | - Stack trace (Traceback) 84 | - OS, Platform and Version (Windows, Linux, macOS, x86, ARM) 85 | - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. 86 | - Possibly your input and the output 87 | - Can you reliably reproduce the issue? And can you also reproduce it with older versions? 88 | 89 | 90 | #### How Do I Submit a Good Bug Report? 91 | 92 | > You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to . 93 | 94 | 95 | We use GitHub issues to track bugs and errors. If you run into an issue with the project: 96 | 97 | - Open an [Issue](https://github.com/Its-VrxxDev/zlapi/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) 98 | - Explain the behavior you would expect and the actual behavior. 99 | - Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. 100 | - Provide the information you collected in the previous section. 101 | 102 | Once it's filed: 103 | 104 | - The project team will label the issue accordingly. 105 | - A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced. 106 | - If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). 107 | 108 | 109 | 110 | 111 | ### Suggesting Enhancements 112 | 113 | This section guides you through submitting an enhancement suggestion for zlapi, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. 114 | 115 | 116 | #### Before Submitting an Enhancement 117 | 118 | - Make sure that you are using the latest version. 119 | - Read the [documentation](https://vrxx1337.dev/zlapi/docs/lastest) carefully and find out if the functionality is already covered, maybe by an individual configuration. 120 | - Perform a [search](https://github.com/Its-VrxxDev/zlapi/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. 121 | - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. 122 | 123 | 124 | #### How Do I Submit a Good Enhancement Suggestion? 125 | 126 | Enhancement suggestions are tracked as [GitHub issues](https://github.com/Its-VrxxDev/zlapi/issues). 127 | 128 | - Use a **clear and descriptive title** for the issue to identify the suggestion. 129 | - Provide a **step-by-step description of the suggested enhancement** in as many details as possible. 130 | - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. 131 | - You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. 132 | - **Explain why this enhancement would be useful** to most zlapi users. You may also want to point out the other projects that solved it better and which could serve as inspiration. 133 | 134 | 135 | 136 | ### Your First Code Contribution 137 | 141 | 142 | ### Improving The Documentation 143 | 147 | 148 | ## Styleguides 149 | ### Commit Messages 150 | 153 | 154 | ## Join The Project Team 155 | 156 | 157 | 158 | ## Attribution 159 | This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)! 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](https://i.imgur.com/CMnA5Sh.jpeg "Logo") 2 | 3 | ## ``zlapi`` - Zalo API (Unofficial) for Python 4 | 5 | [![Project version](https://img.shields.io/badge/pypi-v1.0.2-blue.svg "Project version")](https://pypi.org/project/zlapi/1.0.2) 6 | [![Supported python versions: >= 3. and pypy](https://badgen.net/badge/python/>=3.,pypy?list=| "Supported python versions: >= 3. and pypy")](zlapi) 7 | [![License: MIT License](https://img.shields.io/badge/license-MIT-lightgreen.svg "License: MIT License")](https://github.com/Its-VrxxDev/zlapi/blob/master/LICENSE) 8 | [![Documentation](https://img.shields.io/badge/docs-stop_updating-red.svg "Documentation")](https://vrxx1337.vercel.app/zlapi/docs/lastest) 9 | 10 | ### Language 11 | 12 | - Sẽ hỗ trợ tài liệu Tiếng Việt sớm nhất có thể. Sài tạm google dịch nhé :) 13 | 14 | ### What is ``zlapi``? 15 | 16 | A powerful and efficient library to interact with Zalo Website. 17 | This is *not* an official API, Zalo has that [over here](https://developers.zalo.me/docs) for chat bots. This library differs by using a normal Zalo account instead (More flexible). 18 | 19 | ``zlapi`` currently support: 20 | 21 | - Custom style for message. 22 | - Sending many types of messages, with files, stickers, mentions, etc. 23 | - Fetching messages, threads and users info. 24 | - Creating groups, setting the group, creating polls, etc. 25 | - Listening for, an reacting to messages and other events in real-time. 26 | - And there are many other things. 27 | - ``async``/``await`` (Updated). 28 | 29 | Essentially, everything you need to make an amazing Zalo Bot! 30 | 31 | 32 | ### Caveats 33 | 34 | ``zlapi`` works by imitating what the browser does, and thereby tricking Zalo into thinking it's accessing the website normally. 35 | 36 | However, there's a catch! **Using this library may not comply with Zalo's Terms Of Service**, so be! We are not responsible if your account gets banned or disabled! 37 | 38 | 39 | ### What's New? 40 | 41 | This is an updated version for ``zlapi`` to improve features and fix bugs (v1.0.2) 42 | 43 | **Improvements** 44 | 45 | - Various typo fixes and doc improvements. 46 | - Add simple code style for module. Like ``telebot``, ``discord``, ... 47 | - Add ``async``/``await`` for module. 48 | - Add ``websocket`` type to listen function. 49 | - Add ``run forever`` for listen function. 50 | - Add send ``gif``, ``video``, ``voice``, ``business card``, ``multi image``. 51 | - Add ``Block/Unblock`` members when kicked out of group. 52 | - Add ``Pin/Unpin`` message in group. 53 | - Add ``On Event`` function to handle group and user events. 54 | - Add ``Parse Mode`` for [Message](#messages). 55 | 56 | **Bugfixes** 57 | 58 | - Fixed bug of the ``replyMessage`` function, only replying to normal messages. 59 | 60 | - Fixed payload in function ``addUsersToGroup``. 61 | 62 |
63 | 64 | ## Installation 65 | 66 | ```bash 67 | pip install zlapi 68 | ``` 69 | 70 | If you don't have [pip](https://pip.pypa.io/), [this guide](http://docs.python-guide.org/en/latest/starting/installation/) can guide you through the process. 71 | 72 | You can also install directly from source, provided you have ``pip>=19.0``: 73 | 74 | ```bash 75 | pip install git+https://github.com/Its-VrxxDev/zlapi.git 76 | ``` 77 | 78 |
79 | 80 | ## How to get IMEI and Cookies? 81 | 82 | ### Download Extension 83 | 84 | - [Click Here](https://drive.google.com/file/d/18_-8ruYOVa89JkHdr3muGj3kGWxwt6mc/view?usp=drive_link) to download the extension support getting IMEI & Cookies more conveniently. 85 | 86 | ### Extension Usage Tutorial 87 | 88 | 1. Enable the extension downloaded above. 89 | 2. Go to [https://chat.zalo.me](https://chat.zalo.me), Sign in to your account. 90 | 3. After successfully logging in, go back to extension and get IMEI, Cookies. 91 | 92 | > [!TIP] 93 | If you have opened the website ``chat.zalo.me`` but the extension does not have IMEI & Cookies, please click ``Refresh Page``. 94 | 95 | #### Windows 96 | 97 | [![](https://previews.jumpshare.com/thumb/815bc01b796dd6f1733c957c5af19493968eb06ccf48b6a5036cf7916c0a83965899fb056fe88c29f2bcb2f9f0f5ed5832801eede43aa22e94d5c7bc545ef9448bfbfd14044e807555841b406fdf069aa3acda441ff8675390fa0ff601ff0bcd)](https://jumpshare.com/embed/8SjFyd3EQlCMx1V7N1UQ) 98 | 99 |
100 | 101 | #### Android 102 | 103 | > - Use ``kiwibrowser`` instead of ``chrome`` to be able to use the extension. 104 | > - If you are redirect when accessing ``https://chat.zalo.me``. [Watch this video](https://jumpshare.com/embed/l3LLjAWSAR8KQxvh9dzz) 105 | 106 | [![](https://previews.jumpshare.com/thumb/815bc01b796dd6f1733c957c5af194938966297dbb29c75d038ac93e0691be4c741e5e2cbb689c41b8dfebde4ded3316844e23ec82425f377c248f1a57861470e76e9fe268bdf0803c7c14a61c9dc50769f92efb3803e5ae68c46d260d3407db)](https://jumpshare.com/embed/n56jtVQ7pwZDfR5ZtPft) 107 | 108 |
109 | 110 | ## Basic Usage 111 | 112 | ### Login Account Using Cookies 113 | 114 | * ``Normal``/``Async`` code style 115 | 116 | ```py 117 | # > Normal 118 | # from zlapi import ZaloAPI 119 | 120 | # > Async 121 | # from zlapi.Async import ZaloAPI 122 | 123 | from zlapi import ZaloAPI 124 | from zlapi.models import * 125 | 126 | imei = "" 127 | cookies = {} # Cookies Dict 128 | bot = ZaloAPI("", "", imei=imei, session_cookies=cookies) 129 | ``` 130 | 131 |
132 | 133 | * ``Simple`` code style 134 | 135 | ```py 136 | from zlapi.simple import ZaloAPI 137 | from zlapi.models import * 138 | 139 | imei = "" 140 | cookies = {} # Cookies Dict 141 | bot = ZaloAPI("", "", imei, cookies, prefix="") 142 | ``` 143 | 144 |
145 | 146 | ### Listen Message, Event, ... 147 | 148 | * You can enable thread mode for [On Message](#on-message) function (work with ``requests`` type) with ``thread=True``. 149 | 150 | ```py 151 | bot.listen(thread=True) 152 | ``` 153 | 154 | * You can change the listen mode with ``type=""``. Current module support ``websocket``, ``requests`` type (default type is **websocket**) 155 | 156 | ```py 157 | bot.listen(type="") 158 | ``` 159 | 160 | * If you don't want to have to rerun the bot script when something goes wrong in the **listen** function you can use ``run_forever=True``. 161 | 162 | ```py 163 | bot.listen(run_forever=True) 164 | ``` 165 | 166 |
167 | 168 | * ``Normal``/``Async`` code style 169 | 170 | ```py 171 | # > Normal 172 | # from zlapi import ZaloAPI 173 | 174 | # > Async 175 | # from zlapi.Async import ZaloAPI 176 | 177 | from zlapi import ZaloAPI 178 | from zlapi.models import * 179 | 180 | imei = "" 181 | cookies = {} # Cookies Dict 182 | 183 | bot = ZaloAPI("", "", imei=imei, session_cookies=cookies) 184 | # bot.listen(type="...") 185 | bot.listen() 186 | ``` 187 | 188 |
189 | 190 | * ``Simple`` code style 191 | 192 | ```py 193 | from zlapi.simple import ZaloAPI 194 | from zlapi.models import * 195 | 196 | imei = "" 197 | cookies = {} # Cookies Dict 198 | 199 | bot = ZaloAPI("", "", imei, cookies, prefix="") 200 | bot.listen() 201 | ``` 202 | 203 |
204 | 205 | ### Custom On Message Function 206 | 207 | ``onMessage`` function will be called when receiving a message from ``listen`` function. **So we can handle that message here.** 208 | 209 | * ``Normal`` code style 210 | 211 | ```py 212 | from zlapi import ZaloAPI 213 | from zlapi.models import * 214 | 215 | imei = "" 216 | cookies = {} # Cookies Dict 217 | 218 | class CustomBot(ZaloAPI): 219 | def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 220 | # Handle Message Here 221 | pass 222 | 223 | 224 | bot = CustomBot("", "", imei=imei, session_cookies=cookies) 225 | bot.listen() 226 | ``` 227 | 228 |
229 | 230 | * ``Async`` code style 231 | 232 | ```py 233 | from zlapi.Async import ZaloAPI 234 | from zlapi.models import * 235 | 236 | imei = "" 237 | cookies = {} # Cookies Dict 238 | 239 | class CustomBot(ZaloAPI): 240 | async def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 241 | # Handle Message Here 242 | pass 243 | 244 | 245 | bot = CustomBot("", "", imei=imei, session_cookies=cookies) 246 | bot.listen() 247 | ``` 248 | 249 |
250 | 251 | * ``Simple`` code style 252 | 253 | ```py 254 | from zlapi.simple import ZaloAPI 255 | from zlapi.models import * 256 | 257 | imei = "" 258 | cookies = {} # Cookies Dict 259 | bot = ZaloAPI("", "", imei, cookies, prefix="") 260 | 261 | 262 | @bot.event 263 | async def on_message(ctx): 264 | # Handle Message Here 265 | pass 266 | 267 | 268 | bot.listen() 269 | ``` 270 | 271 |
272 | 273 | ### Example Handle Message 274 | 275 |
276 | Normal code style 277 | 278 | ```py 279 | from zlapi import ZaloAPI 280 | from zlapi.models import * 281 | 282 | imei = "" 283 | cookies = {} # Cookies Dict 284 | 285 | class CustomBot(ZaloAPI): 286 | def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 287 | if not isinstance(message, str): 288 | return 289 | 290 | if message == ".hi": 291 | print(f"{author_id} sent message .hi") 292 | 293 | 294 | bot = CustomBot("", "", imei=imei, session_cookies=cookies) 295 | bot.listen() 296 | ``` 297 | 298 | > - If the message is not ``string`` do not process this message. 299 | > - If the message is ``.hi`` will print author id of message to terminal. 300 | 301 |
302 | 303 |
304 | 305 |
306 | Async code style 307 | 308 | ```py 309 | from zlapi.Async import ZaloAPI 310 | from zlapi.models import * 311 | 312 | imei = "" 313 | cookies = {} # Cookies Dict 314 | 315 | class CustomBot(ZaloAPI): 316 | async def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 317 | if not isinstance(message, str): 318 | return 319 | 320 | if message == ".hi": 321 | print(f"{author_id} sent message .hi") 322 | 323 | 324 | bot = CustomBot("", "", imei=imei, session_cookies=cookies) 325 | bot.listen() 326 | ``` 327 | 328 | > - If the message is not ``string`` do not process this message. 329 | > - If the message is ``.hi`` will print author id of message to terminal. 330 | 331 |
332 | 333 |
334 | 335 |
336 | Simple code style 337 | 338 | - Method 1 339 | 340 | ```py 341 | from zlapi.simple import ZaloAPI 342 | from zlapi.models import * 343 | 344 | imei = "" 345 | cookies = {} # Cookies Dict 346 | bot = ZaloAPI("", "", imei, cookies, prefix="") 347 | 348 | 349 | @bot.event 350 | async def on_message(ctx): 351 | if ctx.message == ".hi": 352 | print(f"{ctx.author_id} sent message .hi") 353 | 354 | 355 | bot.listen() 356 | ``` 357 | 358 |
359 | 360 | - Method 2 361 | 362 | ```py 363 | from zlapi.simple import ZaloAPI 364 | from zlapi.models import * 365 | 366 | imei = "" 367 | cookies = {} # Cookies Dict 368 | bot = ZaloAPI("", "", imei, cookies, prefix=".") 369 | 370 | 371 | @bot.register_handler(commands=["hi"]) 372 | async def handle_hi(ctx): 373 | print(f"{ctx.author_id} sent message .hi") 374 | 375 | 376 | bot.listen() 377 | ``` 378 | 379 | > - ``@bot.register_handler(commands=["hi"])`` is a decoration class used to register a command. When an incoming message matches the bot prefix + registered commands, the message will be processed. 380 | 381 |
382 | 383 |
384 | 385 | 386 | 387 | ### Fetch Account Information 388 | 389 | This function will get the account information you are using in ``zlapi``. 390 | 391 |
392 | Normal code style 393 | 394 | - Outside Module Function 395 | 396 | ```py 397 | bot.fetchAccountInfo() 398 | ``` 399 | 400 |
401 | 402 | - Inside Module Function 403 | 404 | ```py 405 | self.fetchAccountInfo() 406 | ``` 407 | 408 |
409 | 410 |
411 | Async code style 412 | 413 | - Outside Module Function 414 | 415 | ```py 416 | asyncio.run(bot.fetchAccountInfo()) 417 | ``` 418 | 419 |
420 | 421 | - Inside Module Function (You can use ``await`` instead.) 422 | 423 | ```py 424 | await self.fetchAccountInfo() 425 | ``` 426 | 427 |
428 | 429 |
430 | Simple code style 431 | 432 | - Outside Module Function 433 | 434 | ```py 435 | asyncio.run(bot.fetch_account_info()) 436 | ``` 437 | 438 |
439 | 440 | - Inside Module Function (You can use ``await`` instead.) 441 | 442 | ```py 443 | await bot.fetch_account_info() 444 | ``` 445 | 446 |
447 | 448 | 449 | 450 |
451 | 452 | 453 | 454 | ### Fetch Phone Number 455 | 456 | This function will get user information using that user phone number. 457 | 458 | > [!NOTE] 459 | Can't get information of **hidden phone number** or **locked account** 460 | 461 |
462 | Normal code style 463 | 464 | - Outside Module Function 465 | 466 | ```py 467 | bot.fetchPhoneNumber("") 468 | ``` 469 | 470 |
471 | 472 | - Inside Module Function 473 | 474 | ```py 475 | self.fetchPhoneNumber("") 476 | ``` 477 | 478 |
479 | 480 |
481 | Async code style 482 | 483 | - Outside Module Function 484 | 485 | ```py 486 | asyncio.run(bot.fetchPhoneNumber("")) 487 | ``` 488 | 489 |
490 | 491 | - Inside Module Function (You can use ``await`` instead.) 492 | 493 | ```py 494 | await self.fetchPhoneNumber("") 495 | ``` 496 | 497 |
498 | 499 |
500 | Simple code style 501 | 502 | - Outside Module Function 503 | 504 | ```py 505 | asyncio.run(bot.fetch_phone_number("")) 506 | ``` 507 | 508 |
509 | 510 | - Inside Module Function (You can use ``await`` instead.) 511 | 512 | ```py 513 | await bot.fetch_phone_number("") 514 | ``` 515 | 516 |
517 | 518 | 519 | 520 |
521 | 522 | 523 | 524 | ### Fetch User Info 525 | 526 | This function will get user information using that user ID. 527 | 528 | > - In ``Normal``/``Async`` code style you can get user id with author_id argument 529 | > - In ``Simple`` code style you can get user id with ctx.author_id argument 530 | > - Or you can use user id if you already have one 531 | 532 |
533 | Normal code style 534 | 535 | - Outside Module Function 536 | 537 | ```py 538 | bot.fetchUserInfo() 539 | ``` 540 | 541 |
542 | 543 | - Inside Module Function 544 | 545 | ```py 546 | self.fetchUserInfo() 547 | ``` 548 | 549 |
550 | 551 |
552 | Async code style 553 | 554 | - Outside Module Function 555 | 556 | ```py 557 | asyncio.run(bot.fetchUserInfo()) 558 | ``` 559 | 560 |
561 | 562 | - Inside Module Function (You can use ``await`` instead.) 563 | 564 | ```py 565 | await self.fetchUserInfo() 566 | ``` 567 | 568 |
569 | 570 |
571 | Simple code style 572 | 573 | - Outside Module Function 574 | 575 | ```py 576 | asyncio.run(bot.fetch_user_info()) 577 | ``` 578 | 579 |
580 | 581 | - Inside Module Function (You can use ``await`` instead.) 582 | 583 | ```py 584 | await bot.fetch_user_info() 585 | ``` 586 | 587 |
588 | 589 | 590 | 591 |
592 | 593 | 594 | 595 | ### Fetch Group Info 596 | 597 | This function will get group information using that group ID. 598 | 599 | > - In ``Normal``/``Async`` code style you can get user id with thread_id argument 600 | > - In ``Simple`` code style you can get user id with ctx.thread_id argument 601 | > - Or you can use group id if you already have one 602 | 603 |
604 | Normal code style 605 | 606 | - Outside Module Function 607 | 608 | ```py 609 | bot.fetchGroupInfo() 610 | ``` 611 | 612 |
613 | 614 | - Inside Module Function 615 | 616 | ```py 617 | self.fetchGroupInfo() 618 | ``` 619 | 620 |
621 | 622 |
623 | Async code style 624 | 625 | - Outside Module Function 626 | 627 | ```py 628 | asyncio.run(bot.fetchGroupInfo()) 629 | ``` 630 | 631 |
632 | 633 | - Inside Module Function (You can use ``await`` instead.) 634 | 635 | ```py 636 | await self.fetchGroupInfo() 637 | ``` 638 | 639 |
640 | 641 |
642 | Simple code style 643 | 644 | - Outside Module Function 645 | 646 | ```py 647 | asyncio.run(bot.fetch_group_info()) 648 | ``` 649 | 650 |
651 | 652 | - Inside Module Function (You can use ``await`` instead.) 653 | 654 | ```py 655 | await bot.fetch_group_info() 656 | ``` 657 | 658 |
659 | 660 | 661 | 662 |
663 | 664 | 665 | 666 | ### Fetch All Friends 667 | 668 | This function will get all the friends information of the account currently using the ``zlapi``. 669 | 670 |
671 | Normal code style 672 | 673 | - Outside Module Function 674 | 675 | ```py 676 | bot.fetchAllFriends() 677 | ``` 678 | 679 |
680 | 681 | - Inside Module Function 682 | 683 | ```py 684 | self.fetchAllFriends() 685 | ``` 686 | 687 |
688 | 689 |
690 | Async code style 691 | 692 | - Outside Module Function 693 | 694 | ```py 695 | asyncio.run(bot.fetchAllFriends()) 696 | ``` 697 | 698 |
699 | 700 | - Inside Module Function (You can use ``await`` instead.) 701 | 702 | ```py 703 | await self.fetchAllFriends() 704 | ``` 705 | 706 |
707 | 708 |
709 | Simple code style 710 | 711 | - Outside Module Function 712 | 713 | ```py 714 | asyncio.run(bot.fetch_all_friends()) 715 | ``` 716 | 717 |
718 | 719 | - Inside Module Function (You can use ``await`` instead.) 720 | 721 | ```py 722 | await bot.fetch_all_friends() 723 | ``` 724 | 725 |
726 | 727 | 728 | 729 |
730 | 731 | 732 | 733 | ### Fetch All Groups 734 | 735 | This function will get all the groups id of the account currently using the ``zlapi``. 736 | 737 |
738 | Normal code style 739 | 740 | - Outside Module Function 741 | 742 | ```py 743 | bot.fetchAllGroups() 744 | ``` 745 | 746 |
747 | 748 | - Inside Module Function 749 | 750 | ```py 751 | self.fetchAllGroups() 752 | ``` 753 | 754 |
755 | 756 |
757 | Async code style 758 | 759 | - Outside Module Function 760 | 761 | ```py 762 | asyncio.run(bot.fetchAllGroups()) 763 | ``` 764 | 765 |
766 | 767 | - Inside Module Function (You can use ``await`` instead.) 768 | 769 | ```py 770 | await self.fetchAllGroups() 771 | ``` 772 | 773 |
774 | 775 |
776 | Simple code style 777 | 778 | - Outside Module Function 779 | 780 | ```py 781 | asyncio.run(bot.fetch_all_groups()) 782 | ``` 783 | 784 |
785 | 786 | - Inside Module Function (You can use ``await`` instead.) 787 | 788 | ```py 789 | await bot.fetch_all_groups() 790 | ``` 791 | 792 |
793 | 794 | 795 | 796 |
797 | 798 | 799 | 800 | ### Change Account Setting 801 | 802 | This function will change setting of the account currently using the ``zlapi``. 803 | 804 | > - Args: 805 | > - name (str): The new account name 806 | > - dob (str): Date of birth wants to change (format: year-month-day) 807 | > - gender (int | str): Gender wants to change (0 = Male, 1 = Female) 808 | 809 |
810 | Normal code style 811 | 812 | - Outside Module Function 813 | 814 | ```py 815 | bot.changeAccountSetting(, , ) 816 | ``` 817 | 818 |
819 | 820 | - Inside Module Function 821 | 822 | ```py 823 | self.changeAccountSetting(, , ) 824 | ``` 825 | 826 |
827 | 828 |
829 | Async code style 830 | 831 | - Outside Module Function 832 | 833 | ```py 834 | asyncio.run(bot.changeAccountSetting(, , )) 835 | ``` 836 | 837 |
838 | 839 | - Inside Module Function (You can use ``await`` instead.) 840 | 841 | ```py 842 | await self.changeAccountSetting(, , ) 843 | ``` 844 | 845 |
846 | 847 |
848 | Simple code style 849 | 850 | - Outside Module Function 851 | 852 | ```py 853 | asyncio.run(bot.change_account_setting(, , )) 854 | ``` 855 | 856 |
857 | 858 | - Inside Module Function (You can use ``await`` instead.) 859 | 860 | ```py 861 | await bot.change_account_setting(, , ) 862 | ``` 863 | 864 |
865 | 866 | 867 | 868 |
869 | 870 | 871 | 872 | ### Change Account Avatar 873 | 874 | This function will upload/change avatar of the account currently using the ``zlapi``. 875 | 876 | > - Args: 877 | > - filePath (str): A path to the image to upload/change avatar 878 | > - size (int): Avatar image size (default = auto) 879 | > - width (int): Width of avatar image 880 | > - height (int): height of avatar image 881 | > - language (int | str): Zalo Website language ? (idk) 882 | 883 |
884 | Normal code style 885 | 886 | - Outside Module Function 887 | 888 | ```py 889 | bot.changeAccountAvatar() 890 | ``` 891 | 892 |
893 | 894 | - Inside Module Function 895 | 896 | ```py 897 | self.changeAccountAvatar() 898 | ``` 899 | 900 |
901 | 902 |
903 | Async code style 904 | 905 | - Outside Module Function 906 | 907 | ```py 908 | asyncio.run(bot.changeAccountAvatar()) 909 | ``` 910 | 911 |
912 | 913 | - Inside Module Function (You can use ``await`` instead.) 914 | 915 | ```py 916 | await self.changeAccountAvatar() 917 | ``` 918 | 919 |
920 | 921 |
922 | Simple code style 923 | 924 | - Outside Module Function 925 | 926 | ```py 927 | asyncio.run(bot.change_account_avatar()) 928 | ``` 929 | 930 |
931 | 932 | - Inside Module Function (You can use ``await`` instead.) 933 | 934 | ```py 935 | await bot.change_account_avatar() 936 | ``` 937 | 938 |
939 | 940 | 941 | 942 |
943 | 944 | 945 | 946 | ### Send Friend Request 947 | 948 | This function will send friend request to a user by ID. 949 | 950 | > - Args: 951 | > - userId (int | str): User ID to send friend request 952 | > - msg (str): Friend request message 953 | > - language (str): Response language or Zalo interface language 954 | 955 |
956 | Normal code style 957 | 958 | - Outside Module Function 959 | 960 | ```py 961 | bot.sendFriendRequest(, ) 962 | ``` 963 | 964 |
965 | 966 | - Inside Module Function 967 | 968 | ```py 969 | self.sendFriendRequest(, ) 970 | ``` 971 | 972 |
973 | 974 |
975 | Async code style 976 | 977 | - Outside Module Function 978 | 979 | ```py 980 | asyncio.run(bot.sendFriendRequest(, )) 981 | ``` 982 | 983 |
984 | 985 | - Inside Module Function (You can use ``await`` instead.) 986 | 987 | ```py 988 | await self.sendFriendRequest(, ) 989 | ``` 990 | 991 |
992 | 993 |
994 | Simple code style 995 | 996 | - Outside Module Function 997 | 998 | ```py 999 | asyncio.run(bot.send_friend_request(, )) 1000 | ``` 1001 | 1002 |
1003 | 1004 | - Inside Module Function (You can use ``await`` instead.) 1005 | 1006 | ```py 1007 | await bot.send_friend_request(, ) 1008 | ``` 1009 | 1010 |
1011 | 1012 | 1013 | 1014 |
1015 | 1016 | 1017 | 1018 | ### Accept Friend Request 1019 | 1020 | This function will accept friend request from user by ID. 1021 | 1022 | > - Args: 1023 | > - userId (int | str): User ID to accept friend request 1024 | > - language (str): Response language or Zalo interface language 1025 | 1026 |
1027 | Normal code style 1028 | 1029 | - Outside Module Function 1030 | 1031 | ```py 1032 | bot.acceptFriendRequest() 1033 | ``` 1034 | 1035 |
1036 | 1037 | - Inside Module Function 1038 | 1039 | ```py 1040 | self.acceptFriendRequest() 1041 | ``` 1042 | 1043 |
1044 | 1045 |
1046 | Async code style 1047 | 1048 | - Outside Module Function 1049 | 1050 | ```py 1051 | asyncio.run(bot.acceptFriendRequest()) 1052 | ``` 1053 | 1054 |
1055 | 1056 | - Inside Module Function (You can use ``await`` instead.) 1057 | 1058 | ```py 1059 | await self.acceptFriendRequest() 1060 | ``` 1061 | 1062 |
1063 | 1064 |
1065 | Simple code style 1066 | 1067 | - Outside Module Function 1068 | 1069 | ```py 1070 | asyncio.run(bot.accept_friend_request()) 1071 | ``` 1072 | 1073 |
1074 | 1075 | - Inside Module Function (You can use ``await`` instead.) 1076 | 1077 | ```py 1078 | await bot.accept_friend_request() 1079 | ``` 1080 | 1081 |
1082 | 1083 | 1084 | 1085 |
1086 | 1087 | 1088 | 1089 | ### Block View Feed 1090 | 1091 | This function will Block/Unblock friend view feed by ID. 1092 | 1093 | > - Args: 1094 | > - userId (int | str): User ID to block/unblock view feed 1095 | > - isBlockFeed (int): Block/Unblock friend view feed (1 = True | 0 = False) 1096 | 1097 |
1098 | Normal code style 1099 | 1100 | - Outside Module Function 1101 | 1102 | ```py 1103 | bot.blockViewFeed(, ) 1104 | ``` 1105 | 1106 |
1107 | 1108 | - Inside Module Function 1109 | 1110 | ```py 1111 | self.blockViewFeed(, ) 1112 | ``` 1113 | 1114 |
1115 | 1116 |
1117 | Async code style 1118 | 1119 | - Outside Module Function 1120 | 1121 | ```py 1122 | asyncio.run(bot.blockViewFeed(, )) 1123 | ``` 1124 | 1125 |
1126 | 1127 | - Inside Module Function (You can use ``await`` instead.) 1128 | 1129 | ```py 1130 | await self.blockViewFeed(, ) 1131 | ``` 1132 | 1133 |
1134 | 1135 |
1136 | Simple code style 1137 | 1138 | - Outside Module Function 1139 | 1140 | ```py 1141 | asyncio.run(bot.block_view_feed(, )) 1142 | ``` 1143 | 1144 |
1145 | 1146 | - Inside Module Function (You can use ``await`` instead.) 1147 | 1148 | ```py 1149 | await bot.block_view_feed(, ) 1150 | ``` 1151 | 1152 |
1153 | 1154 | 1155 | 1156 |
1157 | 1158 | 1159 | 1160 | ### Block User 1161 | 1162 | This function will block user by ID. 1163 | 1164 | > - Args: 1165 | > - userId (int | str): User ID to block 1166 | 1167 |
1168 | Normal code style 1169 | 1170 | - Outside Module Function 1171 | 1172 | ```py 1173 | bot.blockUser() 1174 | ``` 1175 | 1176 |
1177 | 1178 | - Inside Module Function 1179 | 1180 | ```py 1181 | self.blockUser() 1182 | ``` 1183 | 1184 |
1185 | 1186 |
1187 | Async code style 1188 | 1189 | - Outside Module Function 1190 | 1191 | ```py 1192 | asyncio.run(bot.blockUser()) 1193 | ``` 1194 | 1195 |
1196 | 1197 | - Inside Module Function (You can use ``await`` instead.) 1198 | 1199 | ```py 1200 | await self.blockUser() 1201 | ``` 1202 | 1203 |
1204 | 1205 |
1206 | Simple code style 1207 | 1208 | - Outside Module Function 1209 | 1210 | ```py 1211 | asyncio.run(bot.block_user()) 1212 | ``` 1213 | 1214 |
1215 | 1216 | - Inside Module Function (You can use ``await`` instead.) 1217 | 1218 | ```py 1219 | await bot.block_user() 1220 | ``` 1221 | 1222 |
1223 | 1224 | 1225 | 1226 |
1227 | 1228 | 1229 | 1230 | ### Unblock User 1231 | 1232 | This function will unblock user by ID. 1233 | 1234 | > - Args: 1235 | > - userId (int | str): User ID to unblock 1236 | 1237 |
1238 | Normal code style 1239 | 1240 | - Outside Module Function 1241 | 1242 | ```py 1243 | bot.unblockUser() 1244 | ``` 1245 | 1246 |
1247 | 1248 | - Inside Module Function 1249 | 1250 | ```py 1251 | self.unblockUser() 1252 | ``` 1253 | 1254 |
1255 | 1256 |
1257 | Async code style 1258 | 1259 | - Outside Module Function 1260 | 1261 | ```py 1262 | asyncio.run(bot.unblockUser()) 1263 | ``` 1264 | 1265 |
1266 | 1267 | - Inside Module Function (You can use ``await`` instead.) 1268 | 1269 | ```py 1270 | await self.unblockUser() 1271 | ``` 1272 | 1273 |
1274 | 1275 |
1276 | Simple code style 1277 | 1278 | - Outside Module Function 1279 | 1280 | ```py 1281 | asyncio.run(bot.unblock_user()) 1282 | ``` 1283 | 1284 |
1285 | 1286 | - Inside Module Function (You can use ``await`` instead.) 1287 | 1288 | ```py 1289 | await bot.unblock_user() 1290 | ``` 1291 | 1292 |
1293 | 1294 | 1295 | 1296 |
1297 | 1298 | 1299 | 1300 | ### Create Group 1301 | 1302 | This function will Create a new group. 1303 | 1304 | > - Args: 1305 | > - name (str): The new group name 1306 | > - description (str): Description of the new group 1307 | > - members (str | list): List/String member IDs add to new group 1308 | > - nameChanged (int - auto): Will use default name if disabled (0), else (1) 1309 | > - createLink (int - default): Create a group link? Default = 1 (True) 1310 | 1311 | 1312 |
1313 | Normal code style 1314 | 1315 | - Outside Module Function 1316 | 1317 | ```py 1318 | bot.createGroup(, , ) 1319 | ``` 1320 | 1321 |
1322 | 1323 | - Inside Module Function 1324 | 1325 | ```py 1326 | self.createGroup(, , ) 1327 | ``` 1328 | 1329 |
1330 | 1331 |
1332 | Async code style 1333 | 1334 | - Outside Module Function 1335 | 1336 | ```py 1337 | asyncio.run(bot.createGroup(, , )) 1338 | ``` 1339 | 1340 |
1341 | 1342 | - Inside Module Function (You can use ``await`` instead.) 1343 | 1344 | ```py 1345 | await self.createGroup(, , ) 1346 | ``` 1347 | 1348 |
1349 | 1350 |
1351 | Simple code style 1352 | 1353 | - Outside Module Function 1354 | 1355 | ```py 1356 | asyncio.run(bot.create_group(, , )) 1357 | ``` 1358 | 1359 |
1360 | 1361 | - Inside Module Function (You can use ``await`` instead.) 1362 | 1363 | ```py 1364 | await bot.create_group(, , ) 1365 | ``` 1366 | 1367 |
1368 | 1369 | 1370 | 1371 |
1372 | 1373 | 1374 | 1375 | ### Change Group Avatar 1376 | 1377 | This function will Upload/Change group avatar by ID. 1378 | 1379 | > - Args: 1380 | > - filePath (str): A path to the image to upload/change avatar 1381 | > - groupId (int | str): Group ID to upload/change avatar 1382 | 1383 |
1384 | Normal code style 1385 | 1386 | - Outside Module Function 1387 | 1388 | ```py 1389 | bot.changeGroupAvatar(, ) 1390 | ``` 1391 | 1392 |
1393 | 1394 | - Inside Module Function 1395 | 1396 | ```py 1397 | self.changeGroupAvatar(, ) 1398 | ``` 1399 | 1400 |
1401 | 1402 |
1403 | Async code style 1404 | 1405 | - Outside Module Function 1406 | 1407 | ```py 1408 | asyncio.run(bot.changeGroupAvatar(, )) 1409 | ``` 1410 | 1411 |
1412 | 1413 | - Inside Module Function (You can use ``await`` instead.) 1414 | 1415 | ```py 1416 | await self.changeGroupAvatar(, ) 1417 | ``` 1418 | 1419 |
1420 | 1421 |
1422 | Simple code style 1423 | 1424 | - Outside Module Function 1425 | 1426 | ```py 1427 | asyncio.run(bot.change_group_avatar(, )) 1428 | ``` 1429 | 1430 |
1431 | 1432 | - Inside Module Function (You can use ``await`` instead.) 1433 | 1434 | ```py 1435 | await bot.change_group_avatar(, ) 1436 | ``` 1437 | 1438 |
1439 | 1440 | > [!NOTE] 1441 | Client must be the Owner of the group 1442 | (If the group does not allow members to upload/change) 1443 | 1444 | 1445 | 1446 |
1447 | 1448 | 1449 | 1450 | ### Change Group Name 1451 | 1452 | This function will Set/Change group name by ID. 1453 | 1454 | > - Args: 1455 | > - groupName (str): Group name to change 1456 | > - groupId (int | str): Group ID to change name 1457 | 1458 |
1459 | Normal code style 1460 | 1461 | - Outside Module Function 1462 | 1463 | ```py 1464 | bot.changeGroupName(, ) 1465 | ``` 1466 | 1467 |
1468 | 1469 | - Inside Module Function 1470 | 1471 | ```py 1472 | self.changeGroupName(, ) 1473 | ``` 1474 | 1475 |
1476 | 1477 |
1478 | Async code style 1479 | 1480 | - Outside Module Function 1481 | 1482 | ```py 1483 | asyncio.run(bot.changeGroupName(, )) 1484 | ``` 1485 | 1486 |
1487 | 1488 | - Inside Module Function (You can use ``await`` instead.) 1489 | 1490 | ```py 1491 | await self.changeGroupName(, ) 1492 | ``` 1493 | 1494 |
1495 | 1496 |
1497 | Simple code style 1498 | 1499 | - Outside Module Function 1500 | 1501 | ```py 1502 | asyncio.run(bot.change_group_name(, )) 1503 | ``` 1504 | 1505 |
1506 | 1507 | - Inside Module Function (You can use ``await`` instead.) 1508 | 1509 | ```py 1510 | await bot.change_group_name(, ) 1511 | ``` 1512 | 1513 |
1514 | 1515 | > [!NOTE] 1516 | Client must be the Owner of the group 1517 | (If the group does not allow members to upload/change) 1518 | 1519 | 1520 | 1521 |
1522 | 1523 | 1524 | 1525 | ### Change Group Setting 1526 | 1527 | This function will Update group settings by ID. 1528 | 1529 | > - Args: 1530 | > - groupId (int | str): Group ID to update settings 1531 | > - defaultMode (str): Default mode of settings 1532 | > 1533 | > - default: Group default settings 1534 | > - anti-raid: Group default settings for anti-raid 1535 | > 1536 | > - **kwargs: Group settings kwargs, Value: (1 = True, 0 = False) 1537 | > 1538 | > - blockName: Không cho phép user đổi tên & ảnh đại diện nhóm 1539 | > - signAdminMsg: Đánh dấu tin nhắn từ chủ/phó nhóm 1540 | > - addMemberOnly: Chỉ thêm members (Khi tắt link tham gia nhóm) 1541 | > - setTopicOnly: Cho phép members ghim (tin nhắn, ghi chú, bình chọn) 1542 | > - enableMsgHistory: Cho phép new members đọc tin nhắn gần nhất 1543 | > - lockCreatePost: Không cho phép members tạo ghi chú, nhắc hẹn 1544 | > - lockCreatePoll: Không cho phép members tạo bình chọn 1545 | > - joinAppr: Chế độ phê duyệt thành viên 1546 | > - bannFeature: Default (No description) 1547 | > - dirtyMedia: Default (No description) 1548 | > - banDuration: Default (No description) 1549 | > - lockSendMsg: Không cho phép members gửi tin nhắn 1550 | > - lockViewMember: Không cho phép members xem thành viên nhóm 1551 | > - blocked_members: Danh sách members bị chặn 1552 | 1553 |
1554 | Normal code style 1555 | 1556 | - Outside Module Function 1557 | 1558 | ```py 1559 | bot.changeGroupSetting(, **kwargs) 1560 | ``` 1561 | 1562 |
1563 | 1564 | - Inside Module Function 1565 | 1566 | ```py 1567 | self.changeGroupSetting(, **kwargs) 1568 | ``` 1569 | 1570 |
1571 | 1572 |
1573 | Async code style 1574 | 1575 | - Outside Module Function 1576 | 1577 | ```py 1578 | asyncio.run(bot.changeGroupSetting(, **kwargs)) 1579 | ``` 1580 | 1581 |
1582 | 1583 | - Inside Module Function (You can use ``await`` instead.) 1584 | 1585 | ```py 1586 | await self.changeGroupSetting(, **kwargs) 1587 | ``` 1588 | 1589 |
1590 | 1591 |
1592 | Simple code style 1593 | 1594 | - Outside Module Function 1595 | 1596 | ```py 1597 | asyncio.run(bot.change_group_setting(, **kwargs)) 1598 | ``` 1599 | 1600 |
1601 | 1602 | - Inside Module Function (You can use ``await`` instead.) 1603 | 1604 | ```py 1605 | await bot.change_group_setting(, **kwargs) 1606 | ``` 1607 | 1608 |
1609 | 1610 | > [!WARNING] 1611 | Other settings will default value if not set. See `defaultMode` 1612 | 1613 | 1614 | 1615 |
1616 | 1617 | 1618 | 1619 | ### Change Group Owner 1620 | 1621 | This function will Change group owner by ID. 1622 | 1623 | > - Args: 1624 | > - newAdminId (int | str): members ID to changer owner 1625 | > - groupId (int | str): ID of the group to changer owner 1626 | 1627 |
1628 | Normal code style 1629 | 1630 | - Outside Module Function 1631 | 1632 | ```py 1633 | bot.changeGroupOwner(, ) 1634 | ``` 1635 | 1636 |
1637 | 1638 | - Inside Module Function 1639 | 1640 | ```py 1641 | self.changeGroupOwner(, ) 1642 | ``` 1643 | 1644 |
1645 | 1646 |
1647 | Async code style 1648 | 1649 | - Outside Module Function 1650 | 1651 | ```py 1652 | asyncio.run(bot.changeGroupOwner(, )) 1653 | ``` 1654 | 1655 |
1656 | 1657 | - Inside Module Function (You can use ``await`` instead.) 1658 | 1659 | ```py 1660 | await self.changeGroupOwner(, ) 1661 | ``` 1662 | 1663 |
1664 | 1665 |
1666 | Simple code style 1667 | 1668 | - Outside Module Function 1669 | 1670 | ```py 1671 | asyncio.run(bot.change_group_owner(, )) 1672 | ``` 1673 | 1674 |
1675 | 1676 | - Inside Module Function (You can use ``await`` instead.) 1677 | 1678 | ```py 1679 | await bot.change_group_owner(, ) 1680 | ``` 1681 | 1682 |
1683 | 1684 | > [!NOTE] 1685 | Client must be the Owner of the group. 1686 | 1687 | 1688 | 1689 |
1690 | 1691 | 1692 | 1693 | ### Add Users To Group 1694 | 1695 | This function will Add friends/users to a group. 1696 | 1697 | > - Args: 1698 | > - user_ids (str | list): One or more friend/user IDs to add 1699 | > - groupId (int | str): Group ID to add friend/user to 1700 | 1701 |
1702 | Normal code style 1703 | 1704 | - Outside Module Function 1705 | 1706 | ```py 1707 | bot.addUsersToGroup(, ) 1708 | ``` 1709 | 1710 |
1711 | 1712 | - Inside Module Function 1713 | 1714 | ```py 1715 | self.addUsersToGroup(, ) 1716 | ``` 1717 | 1718 |
1719 | 1720 |
1721 | Async code style 1722 | 1723 | - Outside Module Function 1724 | 1725 | ```py 1726 | asyncio.run(bot.addUsersToGroup(, )) 1727 | ``` 1728 | 1729 |
1730 | 1731 | - Inside Module Function (You can use ``await`` instead.) 1732 | 1733 | ```py 1734 | await self.addUsersToGroup(, ) 1735 | ``` 1736 | 1737 |
1738 | 1739 |
1740 | Simple code style 1741 | 1742 | - Outside Module Function 1743 | 1744 | ```py 1745 | asyncio.run(bot.add_users_to_group(, )) 1746 | ``` 1747 | 1748 |
1749 | 1750 | - Inside Module Function (You can use ``await`` instead.) 1751 | 1752 | ```py 1753 | await bot.add_users_to_group(, ) 1754 | ``` 1755 | 1756 |
1757 | 1758 | 1759 | 1760 |
1761 | 1762 | 1763 | 1764 | ### Kick Users In Group 1765 | 1766 | This function will Kickout members in group by ID. 1767 | 1768 | > - Args: 1769 | > - members (str | list): One or More member IDs to kickout 1770 | > - groupId (int | str): Group ID to kick member from 1771 | 1772 |
1773 | Normal code style 1774 | 1775 | - Outside Module Function 1776 | 1777 | ```py 1778 | bot.kickUsersInGroup(, ) 1779 | ``` 1780 | 1781 |
1782 | 1783 | - Inside Module Function 1784 | 1785 | ```py 1786 | self.kickUsersInGroup(, ) 1787 | ``` 1788 | 1789 |
1790 | 1791 |
1792 | Async code style 1793 | 1794 | - Outside Module Function 1795 | 1796 | ```py 1797 | asyncio.run(bot.kickUsersInGroup(, )) 1798 | ``` 1799 | 1800 |
1801 | 1802 | - Inside Module Function (You can use ``await`` instead.) 1803 | 1804 | ```py 1805 | await self.kickUsersInGroup(, ) 1806 | ``` 1807 | 1808 |
1809 | 1810 |
1811 | Simple code style 1812 | 1813 | - Outside Module Function 1814 | 1815 | ```py 1816 | asyncio.run(bot.kick_users_in_group(, )) 1817 | ``` 1818 | 1819 |
1820 | 1821 | - Inside Module Function (You can use ``await`` instead.) 1822 | 1823 | ```py 1824 | await bot.kick_users_in_group(, ) 1825 | ``` 1826 | 1827 |
1828 | 1829 | > [!NOTE] 1830 | Client must be the Owner of the group. 1831 | 1832 | 1833 | 1834 |
1835 | 1836 | 1837 | 1838 | ### Block Users In Group 1839 | 1840 | This function will Blocked members in group by ID. 1841 | 1842 | > - Args: 1843 | > - members (str | list): One or More member IDs to block 1844 | > - groupId (int | str): Group ID to block member from 1845 | 1846 |
1847 | Normal code style 1848 | 1849 | - Outside Module Function 1850 | 1851 | ```py 1852 | bot.blockUsersInGroup(, ) 1853 | ``` 1854 | 1855 |
1856 | 1857 | - Inside Module Function 1858 | 1859 | ```py 1860 | self.blockUsersInGroup(, ) 1861 | ``` 1862 | 1863 |
1864 | 1865 |
1866 | Async code style 1867 | 1868 | - Outside Module Function 1869 | 1870 | ```py 1871 | asyncio.run(bot.blockUsersInGroup(, )) 1872 | ``` 1873 | 1874 |
1875 | 1876 | - Inside Module Function (You can use ``await`` instead.) 1877 | 1878 | ```py 1879 | await self.blockUsersInGroup(, ) 1880 | ``` 1881 | 1882 |
1883 | 1884 |
1885 | Simple code style 1886 | 1887 | - Outside Module Function 1888 | 1889 | ```py 1890 | asyncio.run(bot.block_users_in_group(, )) 1891 | ``` 1892 | 1893 |
1894 | 1895 | - Inside Module Function (You can use ``await`` instead.) 1896 | 1897 | ```py 1898 | await bot.block_users_in_group(, ) 1899 | ``` 1900 | 1901 |
1902 | 1903 | > [!NOTE] 1904 | Client must be the Owner of the group. 1905 | 1906 | 1907 | 1908 |
1909 | 1910 | 1911 | 1912 | ### Unblock Users In Group 1913 | 1914 | This function will Unblock members in group by ID. 1915 | 1916 | > - Args: 1917 | > - members (str | list): One or More member IDs to unblock 1918 | > - groupId (int | str): Group ID to unblock member from 1919 | 1920 |
1921 | Normal code style 1922 | 1923 | - Outside Module Function 1924 | 1925 | ```py 1926 | bot.unblockUsersInGroup(, ) 1927 | ``` 1928 | 1929 |
1930 | 1931 | - Inside Module Function 1932 | 1933 | ```py 1934 | self.unblockUsersInGroup(, ) 1935 | ``` 1936 | 1937 |
1938 | 1939 |
1940 | Async code style 1941 | 1942 | - Outside Module Function 1943 | 1944 | ```py 1945 | asyncio.run(bot.unblockUsersInGroup(, )) 1946 | ``` 1947 | 1948 |
1949 | 1950 | - Inside Module Function (You can use ``await`` instead.) 1951 | 1952 | ```py 1953 | await self.unblockUsersInGroup(, ) 1954 | ``` 1955 | 1956 |
1957 | 1958 |
1959 | Simple code style 1960 | 1961 | - Outside Module Function 1962 | 1963 | ```py 1964 | asyncio.run(bot.unblock_users_in_group(, )) 1965 | ``` 1966 | 1967 |
1968 | 1969 | - Inside Module Function (You can use ``await`` instead.) 1970 | 1971 | ```py 1972 | await bot.unblock_users_in_group(, ) 1973 | ``` 1974 | 1975 |
1976 | 1977 | > [!NOTE] 1978 | Client must be the Owner of the group. 1979 | 1980 | 1981 | 1982 |
1983 | 1984 | 1985 | 1986 | ### Add Group Admins 1987 | 1988 | This function will Add admins to the group by ID. 1989 | 1990 | > - Args: 1991 | > - members (str | list): One or More member IDs to add 1992 | > - groupId (int | str): Group ID to add admins 1993 | 1994 |
1995 | Normal code style 1996 | 1997 | - Outside Module Function 1998 | 1999 | ```py 2000 | bot.addGroupAdmins(, ) 2001 | ``` 2002 | 2003 |
2004 | 2005 | - Inside Module Function 2006 | 2007 | ```py 2008 | self.addGroupAdmins(, ) 2009 | ``` 2010 | 2011 |
2012 | 2013 |
2014 | Async code style 2015 | 2016 | - Outside Module Function 2017 | 2018 | ```py 2019 | asyncio.run(bot.addGroupAdmins(, )) 2020 | ``` 2021 | 2022 |
2023 | 2024 | - Inside Module Function (You can use ``await`` instead.) 2025 | 2026 | ```py 2027 | await self.addGroupAdmins(, ) 2028 | ``` 2029 | 2030 |
2031 | 2032 |
2033 | Simple code style 2034 | 2035 | - Outside Module Function 2036 | 2037 | ```py 2038 | asyncio.run(bot.add_group_admins(, )) 2039 | ``` 2040 | 2041 |
2042 | 2043 | - Inside Module Function (You can use ``await`` instead.) 2044 | 2045 | ```py 2046 | await bot.add_group_admins(, ) 2047 | ``` 2048 | 2049 |
2050 | 2051 | > [!NOTE] 2052 | Client must be the Owner of the group. 2053 | 2054 | 2055 | 2056 |
2057 | 2058 | 2059 | 2060 | ### Remove Group Admins 2061 | 2062 | This function will Remove admins in the group by ID. 2063 | 2064 | > - Args: 2065 | > - members (str | list): One or More admin IDs to remove 2066 | > - groupId (int | str): Group ID to remove admins 2067 | 2068 |
2069 | Normal code style 2070 | 2071 | - Outside Module Function 2072 | 2073 | ```py 2074 | bot.removeGroupAdmins(, ) 2075 | ``` 2076 | 2077 |
2078 | 2079 | - Inside Module Function 2080 | 2081 | ```py 2082 | self.removeGroupAdmins(, ) 2083 | ``` 2084 | 2085 |
2086 | 2087 |
2088 | Async code style 2089 | 2090 | - Outside Module Function 2091 | 2092 | ```py 2093 | asyncio.run(bot.removeGroupAdmins(, )) 2094 | ``` 2095 | 2096 |
2097 | 2098 | - Inside Module Function (You can use ``await`` instead.) 2099 | 2100 | ```py 2101 | await self.removeGroupAdmins(, ) 2102 | ``` 2103 | 2104 |
2105 | 2106 |
2107 | Simple code style 2108 | 2109 | - Outside Module Function 2110 | 2111 | ```py 2112 | asyncio.run(bot.remove_group_admins(, )) 2113 | ``` 2114 | 2115 |
2116 | 2117 | - Inside Module Function (You can use ``await`` instead.) 2118 | 2119 | ```py 2120 | await bot.remove_group_admins(, ) 2121 | ``` 2122 | 2123 |
2124 | 2125 | > [!NOTE] 2126 | Client must be the Owner of the group. 2127 | 2128 | 2129 | 2130 |
2131 | 2132 | 2133 | 2134 | ### Pin Group Message 2135 | 2136 | This function will Pin message in group by ID. 2137 | 2138 | > - Args: 2139 | > - pinMsg (Message): Message Object to pin 2140 | > - groupId (int | str): Group ID to pin message 2141 | 2142 |
2143 | Normal code style 2144 | 2145 | - Outside Module Function 2146 | 2147 | ```py 2148 | bot.pinGroupMsg(, ) 2149 | ``` 2150 | 2151 |
2152 | 2153 | - Inside Module Function 2154 | 2155 | ```py 2156 | self.pinGroupMsg(, ) 2157 | ``` 2158 | 2159 |
2160 | 2161 |
2162 | Async code style 2163 | 2164 | - Outside Module Function 2165 | 2166 | ```py 2167 | asyncio.run(bot.pinGroupMsg(, )) 2168 | ``` 2169 | 2170 |
2171 | 2172 | - Inside Module Function (You can use ``await`` instead.) 2173 | 2174 | ```py 2175 | await self.pinGroupMsg(, ) 2176 | ``` 2177 | 2178 |
2179 | 2180 |
2181 | Simple code style 2182 | 2183 | - Outside Module Function 2184 | 2185 | ```py 2186 | asyncio.run(bot.pin_group_msg(, )) 2187 | ``` 2188 | 2189 |
2190 | 2191 | - Inside Module Function (You can use ``await`` instead.) 2192 | 2193 | ```py 2194 | await bot.pin_group_msg(, ) 2195 | ``` 2196 | 2197 |
2198 | 2199 | 2200 | 2201 |
2202 | 2203 | 2204 | 2205 | ### Unpin Group Message 2206 | 2207 | This function will Unpin message in group by ID. 2208 | 2209 | > - Args: 2210 | > - pinId (int | str): Pin ID to unpin 2211 | > - pinTime (int): Pin start time 2212 | > - groupId (int | str): Group ID to unpin message 2213 | 2214 |
2215 | Normal code style 2216 | 2217 | - Outside Module Function 2218 | 2219 | ```py 2220 | bot.unpinGroupMsg(, , ) 2221 | ``` 2222 | 2223 |
2224 | 2225 | - Inside Module Function 2226 | 2227 | ```py 2228 | self.unpinGroupMsg(, , ) 2229 | ``` 2230 | 2231 |
2232 | 2233 |
2234 | Async code style 2235 | 2236 | - Outside Module Function 2237 | 2238 | ```py 2239 | asyncio.run(bot.unpinGroupMsg(, , )) 2240 | ``` 2241 | 2242 |
2243 | 2244 | - Inside Module Function (You can use ``await`` instead.) 2245 | 2246 | ```py 2247 | await self.unpinGroupMsg(, , ) 2248 | ``` 2249 | 2250 |
2251 | 2252 |
2253 | Simple code style 2254 | 2255 | - Outside Module Function 2256 | 2257 | ```py 2258 | asyncio.run(bot.unpin_group_msg(, , )) 2259 | ``` 2260 | 2261 |
2262 | 2263 | - Inside Module Function (You can use ``await`` instead.) 2264 | 2265 | ```py 2266 | await bot.unpin_group_msg(, , ) 2267 | ``` 2268 | 2269 |
2270 | 2271 | 2272 | 2273 |
2274 | 2275 | 2276 | 2277 | ### Delete Group Message 2278 | 2279 | This function will Delete message in group by ID. 2280 | 2281 | > - Args: 2282 | > - msgId (int | str): Message ID to delete 2283 | > - ownerId (int | str): Owner ID of the message to delete 2284 | > - clientMsgId (int | str): Client message ID to delete message 2285 | > - groupId (int | str): Group ID to delete message 2286 | 2287 |
2288 | Normal code style 2289 | 2290 | - Outside Module Function 2291 | 2292 | ```py 2293 | bot.deleteGroupMsg(, , , ) 2294 | ``` 2295 | 2296 |
2297 | 2298 | - Inside Module Function 2299 | 2300 | ```py 2301 | self.deleteGroupMsg(, , , ) 2302 | ``` 2303 | 2304 |
2305 | 2306 |
2307 | Async code style 2308 | 2309 | - Outside Module Function 2310 | 2311 | ```py 2312 | asyncio.run(bot.deleteGroupMsg(, , , )) 2313 | ``` 2314 | 2315 |
2316 | 2317 | - Inside Module Function (You can use ``await`` instead.) 2318 | 2319 | ```py 2320 | await self.deleteGroupMsg(, , , ) 2321 | ``` 2322 | 2323 |
2324 | 2325 |
2326 | Simple code style 2327 | 2328 | - Outside Module Function 2329 | 2330 | ```py 2331 | asyncio.run(bot.delete_group_msg(, , , )) 2332 | ``` 2333 | 2334 |
2335 | 2336 | - Inside Module Function (You can use ``await`` instead.) 2337 | 2338 | ```py 2339 | await bot.delete_group_msg(, , , ) 2340 | ``` 2341 | 2342 |
2343 | 2344 | 2345 | 2346 |
2347 | 2348 | 2349 | 2350 | ### View Group Pending 2351 | 2352 | This function will Give list of people pending approval in group by ID. 2353 | 2354 | > - Args: 2355 | > - groupId (int | str): Group ID to view pending members 2356 | 2357 |
2358 | Normal code style 2359 | 2360 | - Outside Module Function 2361 | 2362 | ```py 2363 | bot.viewGroupPending() 2364 | ``` 2365 | 2366 |
2367 | 2368 | - Inside Module Function 2369 | 2370 | ```py 2371 | self.viewGroupPending() 2372 | ``` 2373 | 2374 |
2375 | 2376 |
2377 | Async code style 2378 | 2379 | - Outside Module Function 2380 | 2381 | ```py 2382 | asyncio.run(bot.viewGroupPending()) 2383 | ``` 2384 | 2385 |
2386 | 2387 | - Inside Module Function (You can use ``await`` instead.) 2388 | 2389 | ```py 2390 | await self.viewGroupPending() 2391 | ``` 2392 | 2393 |
2394 | 2395 |
2396 | Simple code style 2397 | 2398 | - Outside Module Function 2399 | 2400 | ```py 2401 | asyncio.run(bot.view_group_pending()) 2402 | ``` 2403 | 2404 |
2405 | 2406 | - Inside Module Function (You can use ``await`` instead.) 2407 | 2408 | ```py 2409 | await bot.view_group_pending() 2410 | ``` 2411 | 2412 |
2413 | 2414 | 2415 | 2416 |
2417 | 2418 | 2419 | 2420 | ### Handle Group Pending 2421 | 2422 | This function will Approve/Deny pending users to the group from the group's approval. 2423 | 2424 | > - Args: 2425 | > - members (str | list): One or More member IDs to handle 2426 | > - groupId (int | str): ID of the group to handle pending members 2427 | > - isApprove (bool): Approve/Reject pending members (True | False) 2428 | 2429 |
2430 | Normal code style 2431 | 2432 | - Outside Module Function 2433 | 2434 | ```py 2435 | bot.handleGroupPending(, ) 2436 | ``` 2437 | 2438 |
2439 | 2440 | - Inside Module Function 2441 | 2442 | ```py 2443 | self.handleGroupPending(, ) 2444 | ``` 2445 | 2446 |
2447 | 2448 |
2449 | Async code style 2450 | 2451 | - Outside Module Function 2452 | 2453 | ```py 2454 | asyncio.run(bot.handleGroupPending(, )) 2455 | ``` 2456 | 2457 |
2458 | 2459 | - Inside Module Function (You can use ``await`` instead.) 2460 | 2461 | ```py 2462 | await self.handleGroupPending(, ) 2463 | ``` 2464 | 2465 |
2466 | 2467 |
2468 | Simple code style 2469 | 2470 | - Outside Module Function 2471 | 2472 | ```py 2473 | asyncio.run(bot.handle_group_pending(, )) 2474 | ``` 2475 | 2476 |
2477 | 2478 | - Inside Module Function (You can use ``await`` instead.) 2479 | 2480 | ```py 2481 | await bot.handle_group_pending(, ) 2482 | ``` 2483 | 2484 |
2485 | 2486 | 2487 | 2488 |
2489 | 2490 | 2491 | 2492 | ### View Poll Detail 2493 | 2494 | This function will Give poll data by ID. 2495 | 2496 | > - Args: 2497 | > - pollId (int | str): Poll ID to view detail 2498 | 2499 |
2500 | Normal code style 2501 | 2502 | - Outside Module Function 2503 | 2504 | ```py 2505 | bot.viewPollDetail() 2506 | ``` 2507 | 2508 |
2509 | 2510 | - Inside Module Function 2511 | 2512 | ```py 2513 | self.viewPollDetail() 2514 | ``` 2515 | 2516 |
2517 | 2518 |
2519 | Async code style 2520 | 2521 | - Outside Module Function 2522 | 2523 | ```py 2524 | asyncio.run(bot.viewPollDetail()) 2525 | ``` 2526 | 2527 |
2528 | 2529 | - Inside Module Function (You can use ``await`` instead.) 2530 | 2531 | ```py 2532 | await self.viewPollDetail() 2533 | ``` 2534 | 2535 |
2536 | 2537 |
2538 | Simple code style 2539 | 2540 | - Outside Module Function 2541 | 2542 | ```py 2543 | asyncio.run(bot.view_poll_detail()) 2544 | ``` 2545 | 2546 |
2547 | 2548 | - Inside Module Function (You can use ``await`` instead.) 2549 | 2550 | ```py 2551 | await bot.view_poll_detail() 2552 | ``` 2553 | 2554 |
2555 | 2556 | 2557 | 2558 |
2559 | 2560 | 2561 | 2562 | ### Create Poll 2563 | 2564 | This function will Create poll in group by ID. 2565 | 2566 | > - Args: 2567 | > - question (str): Question for poll 2568 | > - options (str | list): List options for poll 2569 | > - groupId (int | str): Group ID to create poll from 2570 | > - expiredTime (int): Poll expiration time (0 = no expiration) 2571 | > - pinAct (bool): Pin action (pin poll) 2572 | > - multiChoices (bool): Allows multiple poll choices 2573 | > - allowAddNewOption (bool): Allow members to add new options 2574 | > - hideVotePreview (bool): Hide voting results when haven't voted 2575 | > - isAnonymous (bool): Hide poll voters 2576 | 2577 | 2578 |
2579 | Normal code style 2580 | 2581 | - Outside Module Function 2582 | 2583 | ```py 2584 | bot.createPoll(, , ) 2585 | ``` 2586 | 2587 |
2588 | 2589 | - Inside Module Function 2590 | 2591 | ```py 2592 | self.createPoll(, , ) 2593 | ``` 2594 | 2595 |
2596 | 2597 |
2598 | Async code style 2599 | 2600 | - Outside Module Function 2601 | 2602 | ```py 2603 | asyncio.run(bot.createPoll(, , )) 2604 | ``` 2605 | 2606 |
2607 | 2608 | - Inside Module Function (You can use ``await`` instead.) 2609 | 2610 | ```py 2611 | await self.createPoll(, , ) 2612 | ``` 2613 | 2614 |
2615 | 2616 |
2617 | Simple code style 2618 | 2619 | - Outside Module Function 2620 | 2621 | ```py 2622 | asyncio.run(bot.create_poll(, , )) 2623 | ``` 2624 | 2625 |
2626 | 2627 | - Inside Module Function (You can use ``await`` instead.) 2628 | 2629 | ```py 2630 | await bot.create_poll(, , ) 2631 | ``` 2632 | 2633 |
2634 | 2635 | 2636 | 2637 |
2638 | 2639 | 2640 | 2641 | ### Lock Poll 2642 | 2643 | This function will Lock/end poll by ID. 2644 | 2645 | > - Args: 2646 | > - pollId (int | str): Poll ID to lock 2647 | 2648 |
2649 | Normal code style 2650 | 2651 | - Outside Module Function 2652 | 2653 | ```py 2654 | bot.lockPoll() 2655 | ``` 2656 | 2657 |
2658 | 2659 | - Inside Module Function 2660 | 2661 | ```py 2662 | self.lockPoll() 2663 | ``` 2664 | 2665 |
2666 | 2667 |
2668 | Async code style 2669 | 2670 | - Outside Module Function 2671 | 2672 | ```py 2673 | asyncio.run(bot.lockPoll()) 2674 | ``` 2675 | 2676 |
2677 | 2678 | - Inside Module Function (You can use ``await`` instead.) 2679 | 2680 | ```py 2681 | await self.lockPoll() 2682 | ``` 2683 | 2684 |
2685 | 2686 |
2687 | Simple code style 2688 | 2689 | - Outside Module Function 2690 | 2691 | ```py 2692 | asyncio.run(bot.lock_poll()) 2693 | ``` 2694 | 2695 |
2696 | 2697 | - Inside Module Function (You can use ``await`` instead.) 2698 | 2699 | ```py 2700 | await bot.lock_poll() 2701 | ``` 2702 | 2703 |
2704 | 2705 | 2706 | 2707 |
2708 | 2709 | 2710 | 2711 | ### Disperse Group 2712 | 2713 | This function will Disperse group by ID. 2714 | 2715 | > - Args: 2716 | > - groupId (int | str): Group ID to disperse 2717 | 2718 |
2719 | Normal code style 2720 | 2721 | - Outside Module Function 2722 | 2723 | ```py 2724 | bot.disperseGroup() 2725 | ``` 2726 | 2727 |
2728 | 2729 | - Inside Module Function 2730 | 2731 | ```py 2732 | self.disperseGroup() 2733 | ``` 2734 | 2735 |
2736 | 2737 |
2738 | Async code style 2739 | 2740 | - Outside Module Function 2741 | 2742 | ```py 2743 | asyncio.run(bot.disperseGroup()) 2744 | ``` 2745 | 2746 |
2747 | 2748 | - Inside Module Function (You can use ``await`` instead.) 2749 | 2750 | ```py 2751 | await self.disperseGroup() 2752 | ``` 2753 | 2754 |
2755 | 2756 |
2757 | Simple code style 2758 | 2759 | - Outside Module Function 2760 | 2761 | ```py 2762 | asyncio.run(bot.disperse_group()) 2763 | ``` 2764 | 2765 |
2766 | 2767 | - Inside Module Function (You can use ``await`` instead.) 2768 | 2769 | ```py 2770 | await bot.disperse_group() 2771 | ``` 2772 | 2773 |
2774 | 2775 | 2776 | 2777 |
2778 | 2779 | 2780 | 2781 | ### Send Message 2782 | 2783 | This function will Send message to a thread (user/group). 2784 | 2785 | > - Args: 2786 | > - message (Message): ``Message`` Object to send 2787 | > - thread_id (int | str): User/Group ID to send to 2788 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 2789 | > - mark_message (str): Send messages as `Urgent` or `Important` mark 2790 | 2791 |
2792 | Normal code style 2793 | 2794 | - Outside Module Function 2795 | 2796 | ```py 2797 | bot.send(, , ) 2798 | ``` 2799 | 2800 | or 2801 | 2802 | ```py 2803 | bot.sendMessage(, , ) 2804 | ``` 2805 | 2806 |
2807 | 2808 | - Inside Module Function 2809 | 2810 | ```py 2811 | self.send(, , ) 2812 | ``` 2813 | 2814 | or 2815 | 2816 | ```py 2817 | self.sendMessage(, , ) 2818 | ``` 2819 | 2820 |
2821 | 2822 |
2823 | Async code style 2824 | 2825 | - Outside Module Function 2826 | 2827 | ```py 2828 | asyncio.run(bot.send(, , )) 2829 | ``` 2830 | 2831 | or 2832 | 2833 | ```py 2834 | asyncio.run(bot.sendMessage(, , )) 2835 | ``` 2836 | 2837 |
2838 | 2839 | - Inside Module Function (You can use ``await`` instead.) 2840 | 2841 | ```py 2842 | await self.send(, , ) 2843 | ``` 2844 | 2845 | or 2846 | 2847 | ```py 2848 | await self.sendMessage(, , ) 2849 | ``` 2850 | 2851 |
2852 | 2853 |
2854 | Simple code style 2855 | 2856 | - Outside Module Function 2857 | 2858 | ```py 2859 | asyncio.run(bot.send(, , )) 2860 | ``` 2861 | 2862 | or 2863 | 2864 | ```py 2865 | asyncio.run(bot.send_message(, , )) 2866 | ``` 2867 | 2868 |
2869 | 2870 | - Inside Module Function (You can use ``await`` instead.) 2871 | 2872 | ```py 2873 | await bot.send(, , ) 2874 | ``` 2875 | 2876 | or 2877 | 2878 | ```py 2879 | await bot.send_message(, , ) 2880 | ``` 2881 | 2882 |
2883 | 2884 | 2885 | 2886 |
2887 | 2888 | 2889 | 2890 | ### Reply Message 2891 | 2892 | This function will Reply message in thread (user/group). 2893 | 2894 | > - Args: 2895 | > - message (Message): ``Message Object`` to send 2896 | > - replyMsg (Message): ``Message Object`` to reply 2897 | > - thread_id (int | str): User/Group ID to send to. 2898 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 2899 | 2900 |
2901 | Normal code style 2902 | 2903 | - Outside Module Function 2904 | 2905 | ```py 2906 | bot.replyMessage(, , , ) 2907 | ``` 2908 | 2909 |
2910 | 2911 | - Inside Module Function 2912 | 2913 | ```py 2914 | self.replyMessage(, , , ) 2915 | ``` 2916 | 2917 |
2918 | 2919 |
2920 | Async code style 2921 | 2922 | - Outside Module Function 2923 | 2924 | ```py 2925 | asyncio.run(bot.replyMessage(, , , )) 2926 | ``` 2927 | 2928 |
2929 | 2930 | - Inside Module Function (You can use ``await`` instead.) 2931 | 2932 | ```py 2933 | await self.replyMessage(, , , ) 2934 | ``` 2935 | 2936 |
2937 | 2938 |
2939 | Simple code style 2940 | 2941 | - Outside Module Function 2942 | 2943 | ```py 2944 | asyncio.run(bot.reply_message(, , , )) 2945 | ``` 2946 | 2947 |
2948 | 2949 | - Inside Module Function (You can use ``await`` instead.) 2950 | 2951 | ```py 2952 | await bot.reply_message(, , , ) 2953 | ``` 2954 | 2955 |
2956 | 2957 | 2958 | 2959 |
2960 | 2961 | 2962 | 2963 | ### Undo Message 2964 | 2965 | This function will Undo message from the client (self) by ID. 2966 | 2967 | > - Args: 2968 | > - msgId (int | str): Message ID to undo 2969 | > - cliMsgId (int | str): Client Msg ID to undo 2970 | > - thread_id (int | str): User/Group ID to undo message 2971 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 2972 | 2973 |
2974 | Normal code style 2975 | 2976 | - Outside Module Function 2977 | 2978 | ```py 2979 | bot.undoMessage(, , , ) 2980 | ``` 2981 | 2982 |
2983 | 2984 | - Inside Module Function 2985 | 2986 | ```py 2987 | self.undoMessage(, , , ) 2988 | ``` 2989 | 2990 |
2991 | 2992 |
2993 | Async code style 2994 | 2995 | - Outside Module Function 2996 | 2997 | ```py 2998 | asyncio.run(bot.undoMessage(, , , )) 2999 | ``` 3000 | 3001 |
3002 | 3003 | - Inside Module Function (You can use ``await`` instead.) 3004 | 3005 | ```py 3006 | await self.undoMessage(, , , ) 3007 | ``` 3008 | 3009 |
3010 | 3011 |
3012 | Simple code style 3013 | 3014 | - Outside Module Function 3015 | 3016 | ```py 3017 | asyncio.run(bot.undo_message(, , , )) 3018 | ``` 3019 | 3020 |
3021 | 3022 | - Inside Module Function (You can use ``await`` instead.) 3023 | 3024 | ```py 3025 | await bot.undo_message(, , , ) 3026 | ``` 3027 | 3028 |
3029 | 3030 | 3031 | 3032 |
3033 | 3034 | 3035 | 3036 | ### Send Reaction 3037 | 3038 | This function will Reaction message in thread (user/group) by ID. 3039 | 3040 | > - Args: 3041 | > - messageObject (Message): ``Message Object`` to reaction 3042 | > - reactionIcon (str): Icon/Text to reaction 3043 | > - thread_id (int | str): Group/User ID contain message to reaction 3044 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3045 | 3046 |
3047 | Normal code style 3048 | 3049 | - Outside Module Function 3050 | 3051 | ```py 3052 | bot.sendReaction(, , , ) 3053 | ``` 3054 | 3055 |
3056 | 3057 | - Inside Module Function 3058 | 3059 | ```py 3060 | self.sendReaction(, , , ) 3061 | ``` 3062 | 3063 |
3064 | 3065 |
3066 | Async code style 3067 | 3068 | - Outside Module Function 3069 | 3070 | ```py 3071 | asyncio.run(bot.sendReaction(, , , )) 3072 | ``` 3073 | 3074 |
3075 | 3076 | - Inside Module Function (You can use ``await`` instead.) 3077 | 3078 | ```py 3079 | await self.sendReaction(, , , ) 3080 | ``` 3081 | 3082 |
3083 | 3084 |
3085 | Simple code style 3086 | 3087 | - Outside Module Function 3088 | 3089 | ```py 3090 | asyncio.run(bot.send_reaction(, , , )) 3091 | ``` 3092 | 3093 |
3094 | 3095 | - Inside Module Function (You can use ``await`` instead.) 3096 | 3097 | ```py 3098 | await bot.send_reaction(, , , ) 3099 | ``` 3100 | 3101 |
3102 | 3103 | 3104 | 3105 |
3106 | 3107 | 3108 | 3109 | ### Send Multiple Reactions 3110 | 3111 | This function will Reaction multi message in thread (user/group) by ID. 3112 | 3113 | > - Args: 3114 | > - reactionObj (MessageReaction): Message(s) data to reaction 3115 | > - reactionIcon (str): Icon/Text to reaction 3116 | > - thread_id (int | str): Group/User ID contain message to reaction 3117 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3118 | 3119 |
3120 | Normal code style 3121 | 3122 | - Outside Module Function 3123 | 3124 | ```py 3125 | bot.sendMultiReaction(, , , ) 3126 | ``` 3127 | 3128 |
3129 | 3130 | - Inside Module Function 3131 | 3132 | ```py 3133 | self.sendMultiReaction(, , , ) 3134 | ``` 3135 | 3136 |
3137 | 3138 |
3139 | Async code style 3140 | 3141 | - Outside Module Function 3142 | 3143 | ```py 3144 | asyncio.run(bot.sendMultiReaction(, , , )) 3145 | ``` 3146 | 3147 |
3148 | 3149 | - Inside Module Function (You can use ``await`` instead.) 3150 | 3151 | ```py 3152 | await self.sendMultiReaction(, , , ) 3153 | ``` 3154 | 3155 |
3156 | 3157 |
3158 | Simple code style 3159 | 3160 | - Outside Module Function 3161 | 3162 | ```py 3163 | asyncio.run(bot.send_multi_reaction(, , , )) 3164 | ``` 3165 | 3166 |
3167 | 3168 | - Inside Module Function (You can use ``await`` instead.) 3169 | 3170 | ```py 3171 | await bot.send_multi_reaction(, , , ) 3172 | ``` 3173 | 3174 |
3175 | 3176 | 3177 | 3178 |
3179 | 3180 | 3181 | 3182 | ### Send Remote File 3183 | 3184 | This function will Send File to a User/Group with url. 3185 | 3186 | > - Args: 3187 | > - fileUrl (str): File url to send 3188 | > - thread_id (int | str): User/Group ID to send to. 3189 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3190 | > - fileName (str): File name to send 3191 | > - fileSize (int): File size to send 3192 | > - extension (str): type of file to send (py, txt, mp4, ...) 3193 | 3194 |
3195 | Normal code style 3196 | 3197 | - Outside Module Function 3198 | 3199 | ```py 3200 | bot.sendRemoteFile(, , ) 3201 | ``` 3202 | 3203 |
3204 | 3205 | - Inside Module Function 3206 | 3207 | ```py 3208 | self.sendRemoteFile(, , ) 3209 | ``` 3210 | 3211 |
3212 | 3213 |
3214 | Async code style 3215 | 3216 | - Outside Module Function 3217 | 3218 | ```py 3219 | asyncio.run(bot.sendRemoteFile(, , )) 3220 | ``` 3221 | 3222 |
3223 | 3224 | - Inside Module Function (You can use ``await`` instead.) 3225 | 3226 | ```py 3227 | await self.sendRemoteFile(, , ) 3228 | ``` 3229 | 3230 |
3231 | 3232 |
3233 | Simple code style 3234 | 3235 | - Outside Module Function 3236 | 3237 | ```py 3238 | asyncio.run(bot.send_remote_file(, , )) 3239 | ``` 3240 | 3241 |
3242 | 3243 | - Inside Module Function (You can use ``await`` instead.) 3244 | 3245 | ```py 3246 | await bot.send_remote_file(, , ) 3247 | ``` 3248 | 3249 |
3250 | 3251 | 3252 | 3253 |
3254 | 3255 | 3256 | 3257 | ### Send Remote Video 3258 | 3259 | This function will Send video to a User/Group with url. 3260 | 3261 | > - Args: 3262 | > - videoUrl (str): Video link to send 3263 | > - thumbnailUrl (str): Thumbnail link for video 3264 | > - duration (int | str): Time for video (ms) 3265 | > - thread_id (int | str): User/Group ID to send to. 3266 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3267 | > - width (int): Width of the video 3268 | > - height (int): Height of the video 3269 | > - message (Message): ``Message Object`` to send with video 3270 | 3271 |
3272 | Normal code style 3273 | 3274 | - Outside Module Function 3275 | 3276 | ```py 3277 | bot.sendRemoteVideo(, , , , ) 3278 | ``` 3279 | 3280 |
3281 | 3282 | - Inside Module Function 3283 | 3284 | ```py 3285 | self.sendRemoteVideo(, , , , ) 3286 | ``` 3287 | 3288 |
3289 | 3290 |
3291 | Async code style 3292 | 3293 | - Outside Module Function 3294 | 3295 | ```py 3296 | asyncio.run(bot.sendRemoteVideo(, , , , )) 3297 | ``` 3298 | 3299 |
3300 | 3301 | - Inside Module Function (You can use ``await`` instead.) 3302 | 3303 | ```py 3304 | await self.sendRemoteVideo(, , , , ) 3305 | ``` 3306 | 3307 |
3308 | 3309 |
3310 | Simple code style 3311 | 3312 | - Outside Module Function 3313 | 3314 | ```py 3315 | asyncio.run(bot.send_remote_video(, , , , )) 3316 | ``` 3317 | 3318 |
3319 | 3320 | - Inside Module Function (You can use ``await`` instead.) 3321 | 3322 | ```py 3323 | await bot.send_remote_video(, , , , ) 3324 | ``` 3325 | 3326 |
3327 | 3328 | 3329 | 3330 |
3331 | 3332 | 3333 | 3334 | ### Send Remote Voice 3335 | 3336 | This function will Send voice to a User/Group with url. 3337 | 3338 | > - Args: 3339 | > - voiceUrl (str): Voice link to send 3340 | > - thread_id (int | str): User/Group ID to change status in 3341 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3342 | > - fileSize (int | str): Voice content length (size) to send 3343 | 3344 |
3345 | Normal code style 3346 | 3347 | - Outside Module Function 3348 | 3349 | ```py 3350 | bot.sendRemoteVoice(, , ) 3351 | ``` 3352 | 3353 |
3354 | 3355 | - Inside Module Function 3356 | 3357 | ```py 3358 | self.sendRemoteVoice(, , ) 3359 | ``` 3360 | 3361 |
3362 | 3363 |
3364 | Async code style 3365 | 3366 | - Outside Module Function 3367 | 3368 | ```py 3369 | asyncio.run(bot.sendRemoteVoice(, , )) 3370 | ``` 3371 | 3372 |
3373 | 3374 | - Inside Module Function (You can use ``await`` instead.) 3375 | 3376 | ```py 3377 | await self.sendRemoteVoice(, , ) 3378 | ``` 3379 | 3380 |
3381 | 3382 |
3383 | Simple code style 3384 | 3385 | - Outside Module Function 3386 | 3387 | ```py 3388 | asyncio.run(bot.send_remote_voice(, , )) 3389 | ``` 3390 | 3391 |
3392 | 3393 | - Inside Module Function (You can use ``await`` instead.) 3394 | 3395 | ```py 3396 | await bot.send_remote_voice(, , ) 3397 | ``` 3398 | 3399 |
3400 | 3401 | 3402 | 3403 |
3404 | 3405 | 3406 | 3407 | ### Send Local Image 3408 | 3409 | This function will Send Image to a User/Group with local file. 3410 | 3411 | > - Args: 3412 | > - imagePath (str): Image directory to send 3413 | > - thread_id (int | str): User/Group ID to send to. 3414 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3415 | > - width (int): Image width to send 3416 | > - height (int): Image height to send 3417 | > - message (Message): ``Message Object`` to send with image 3418 | 3419 |
3420 | Normal code style 3421 | 3422 | - Outside Module Function 3423 | 3424 | ```py 3425 | bot.sendLocalImage(, , ) 3426 | ``` 3427 | 3428 |
3429 | 3430 | - Inside Module Function 3431 | 3432 | ```py 3433 | self.sendLocalImage(, , ) 3434 | ``` 3435 | 3436 |
3437 | 3438 |
3439 | Async code style 3440 | 3441 | - Outside Module Function 3442 | 3443 | ```py 3444 | asyncio.run(bot.sendLocalImage(, , )) 3445 | ``` 3446 | 3447 |
3448 | 3449 | - Inside Module Function (You can use ``await`` instead.) 3450 | 3451 | ```py 3452 | await self.sendLocalImage(, , ) 3453 | ``` 3454 | 3455 |
3456 | 3457 |
3458 | Simple code style 3459 | 3460 | - Outside Module Function 3461 | 3462 | ```py 3463 | asyncio.run(bot.send_local_image(, , )) 3464 | ``` 3465 | 3466 |
3467 | 3468 | - Inside Module Function (You can use ``await`` instead.) 3469 | 3470 | ```py 3471 | await bot.send_local_image(, , ) 3472 | ``` 3473 | 3474 |
3475 | 3476 | 3477 | 3478 |
3479 | 3480 | 3481 | 3482 | ### Send Multiple Local Image 3483 | 3484 | This function will Send Multiple Image to a User/Group with local file. 3485 | 3486 | > - Args: 3487 | > - imagePathList (list): List image directory to send 3488 | > - thread_id (int | str): User/Group ID to send to. 3489 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3490 | > - width (int): Image width to send 3491 | > - height (int): Image height to send 3492 | > - message (Message): ``Message Object`` to send with image 3493 | 3494 |
3495 | Normal code style 3496 | 3497 | - Outside Module Function 3498 | 3499 | ```py 3500 | bot.sendMultiLocalImage(, , ) 3501 | ``` 3502 | 3503 |
3504 | 3505 | - Inside Module Function 3506 | 3507 | ```py 3508 | self.sendMultiLocalImage(, , ) 3509 | ``` 3510 | 3511 |
3512 | 3513 |
3514 | Async code style 3515 | 3516 | - Outside Module Function 3517 | 3518 | ```py 3519 | asyncio.run(bot.sendMultiLocalImage(, , )) 3520 | ``` 3521 | 3522 |
3523 | 3524 | - Inside Module Function (You can use ``await`` instead.) 3525 | 3526 | ```py 3527 | await self.sendMultiLocalImage(, , ) 3528 | ``` 3529 | 3530 |
3531 | 3532 |
3533 | Simple code style 3534 | 3535 | - Outside Module Function 3536 | 3537 | ```py 3538 | asyncio.run(bot.send_multi_local_image(, , )) 3539 | ``` 3540 | 3541 |
3542 | 3543 | - Inside Module Function (You can use ``await`` instead.) 3544 | 3545 | ```py 3546 | await bot.send_multi_local_image(, , ) 3547 | ``` 3548 | 3549 |
3550 | 3551 | 3552 | 3553 |
3554 | 3555 | 3556 | 3557 | ### Send Local Gif 3558 | 3559 | This function will Send Gif to a User/Group with local file. 3560 | 3561 | > - Args: 3562 | > - gifPath (str): Gif path to send 3563 | > - thumbnailUrl (str): Thumbnail of gif to send 3564 | > - thread_id (int | str): User/Group ID to send to. 3565 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3566 | > - gifName (str): Gif name to send 3567 | > - width (int): Gif width to send 3568 | > - height (int): Gif height to send 3569 | 3570 |
3571 | Normal code style 3572 | 3573 | - Outside Module Function 3574 | 3575 | ```py 3576 | bot.sendLocalGif(, , , ) 3577 | ``` 3578 | 3579 |
3580 | 3581 | - Inside Module Function 3582 | 3583 | ```py 3584 | self.sendLocalGif(, , , ) 3585 | ``` 3586 | 3587 |
3588 | 3589 |
3590 | Async code style 3591 | 3592 | - Outside Module Function 3593 | 3594 | ```py 3595 | asyncio.run(bot.sendLocalGif(, , , )) 3596 | ``` 3597 | 3598 |
3599 | 3600 | - Inside Module Function (You can use ``await`` instead.) 3601 | 3602 | ```py 3603 | await self.sendLocalGif(, , , ) 3604 | ``` 3605 | 3606 |
3607 | 3608 |
3609 | Simple code style 3610 | 3611 | - Outside Module Function 3612 | 3613 | ```py 3614 | asyncio.run(bot.send_local_gif(, , , )) 3615 | ``` 3616 | 3617 |
3618 | 3619 | - Inside Module Function (You can use ``await`` instead.) 3620 | 3621 | ```py 3622 | await bot.send_local_gif(, , , ) 3623 | ``` 3624 | 3625 |
3626 | 3627 | 3628 | 3629 |
3630 | 3631 | 3632 | 3633 | ### Send Sticker 3634 | 3635 | This function will Send Sticker to a User/Group. 3636 | 3637 | > - Args: 3638 | > - stickerType (int | str): Sticker type to send 3639 | > - stickerId (int | str): Sticker id to send 3640 | > - cateId (int | str): Sticker category id to send 3641 | > - thread_id (int | str): User/Group ID to send to. 3642 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3643 | 3644 |
3645 | Normal code style 3646 | 3647 | - Outside Module Function 3648 | 3649 | ```py 3650 | bot.sendSticker(, , , , ) 3651 | ``` 3652 | 3653 |
3654 | 3655 | - Inside Module Function 3656 | 3657 | ```py 3658 | self.sendSticker(, , , , ) 3659 | ``` 3660 | 3661 |
3662 | 3663 |
3664 | Async code style 3665 | 3666 | - Outside Module Function 3667 | 3668 | ```py 3669 | asyncio.run(bot.sendSticker(, , , , )) 3670 | ``` 3671 | 3672 |
3673 | 3674 | - Inside Module Function (You can use ``await`` instead.) 3675 | 3676 | ```py 3677 | await self.sendSticker(, , , , ) 3678 | ``` 3679 | 3680 |
3681 | 3682 |
3683 | Simple code style 3684 | 3685 | - Outside Module Function 3686 | 3687 | ```py 3688 | asyncio.run(bot.send_sticker(, , , , )) 3689 | ``` 3690 | 3691 |
3692 | 3693 | - Inside Module Function (You can use ``await`` instead.) 3694 | 3695 | ```py 3696 | await bot.send_sticker(, , , , ) 3697 | ``` 3698 | 3699 |
3700 | 3701 | 3702 | 3703 |
3704 | 3705 | 3706 | 3707 | ### Send Custom Sticker 3708 | 3709 | This function will Send custom (static/animation) sticker to a User/Group with url. 3710 | 3711 | > - Args: 3712 | > - staticImgUrl (str): Image url (png, jpg, jpeg) format to create sticker 3713 | > - animationImgUrl (str): Static/Animation image url (webp) format to create sticker 3714 | > - thread_id (int | str): User/Group ID to send sticker to. 3715 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3716 | > - reply (int | str): Message ID to send stickers with quote 3717 | > - width (int | str): Width of photo/sticker 3718 | > - height (int | str): Height of photo/sticker 3719 | 3720 |
3721 | Normal code style 3722 | 3723 | - Outside Module Function 3724 | 3725 | ```py 3726 | bot.sendCustomSticker(, , , ) 3727 | ``` 3728 | 3729 |
3730 | 3731 | - Inside Module Function 3732 | 3733 | ```py 3734 | self.sendCustomSticker(, , , ) 3735 | ``` 3736 | 3737 |
3738 | 3739 |
3740 | Async code style 3741 | 3742 | - Outside Module Function 3743 | 3744 | ```py 3745 | asyncio.run(bot.sendCustomSticker(, , , )) 3746 | ``` 3747 | 3748 |
3749 | 3750 | - Inside Module Function (You can use ``await`` instead.) 3751 | 3752 | ```py 3753 | await self.sendCustomSticker(, , , ) 3754 | ``` 3755 | 3756 |
3757 | 3758 |
3759 | Simple code style 3760 | 3761 | - Outside Module Function 3762 | 3763 | ```py 3764 | asyncio.run(bot.send_custom_sticker(, , , )) 3765 | ``` 3766 | 3767 |
3768 | 3769 | - Inside Module Function (You can use ``await`` instead.) 3770 | 3771 | ```py 3772 | await bot.send_custom_sticker(, , , ) 3773 | ``` 3774 | 3775 |
3776 | 3777 | 3778 | 3779 |
3780 | 3781 | 3782 | 3783 | ### Send Link 3784 | 3785 | This function will Send link to a User/Group with url. 3786 | 3787 | > - Args: 3788 | > - linkUrl (str): Link url to send 3789 | > - title (str): Title for card to send 3790 | > - thread_id (int | str): User/Group ID to send link to 3791 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3792 | > - thumbnailUrl (str): Thumbnail link url for card to send 3793 | > - domainUrl (str): Main domain of Link to send (eg: github.com) 3794 | > - desc (str): Description for card to send 3795 | > - message (Message): ``Message Object`` to send with the link 3796 | 3797 |
3798 | Normal code style 3799 | 3800 | - Outside Module Function 3801 | 3802 | ```py 3803 | bot.sendLink(, , <thread_id>, <thread_type>) 3804 | ``` 3805 | 3806 | </br> 3807 | 3808 | - Inside Module Function 3809 | 3810 | ```py 3811 | self.sendLink(<linkUrl>, <title>, <thread_id>, <thread_type>) 3812 | ``` 3813 | 3814 | </details> 3815 | 3816 | <details> 3817 | <summary><b><i>Async</b> code style</i></summary> 3818 | 3819 | - Outside Module Function 3820 | 3821 | ```py 3822 | asyncio.run(bot.sendLink(<linkUrl>, <title>, <thread_id>, <thread_type>)) 3823 | ``` 3824 | 3825 | </br> 3826 | 3827 | - Inside Module Function (You can use ``await`` instead.) 3828 | 3829 | ```py 3830 | await self.sendLink(<linkUrl>, <title>, <thread_id>, <thread_type>) 3831 | ``` 3832 | 3833 | </details> 3834 | 3835 | <details> 3836 | <summary><b><i>Simple</b> code style</i></summary> 3837 | 3838 | - Outside Module Function 3839 | 3840 | ```py 3841 | asyncio.run(bot.send_link(<linkUrl>, <title>, <thread_id>, <thread_type>)) 3842 | ``` 3843 | 3844 | </br> 3845 | 3846 | - Inside Module Function (You can use ``await`` instead.) 3847 | 3848 | ```py 3849 | await bot.send_link(<linkUrl>, <title>, <thread_id>, <thread_type>) 3850 | ``` 3851 | 3852 | </details> 3853 | 3854 | <!-- END sendLink --> 3855 | 3856 | </br> 3857 | 3858 | <!-- sendReport --> 3859 | 3860 | ### Send Report 3861 | 3862 | This function will Send report to Zalo. 3863 | 3864 | > - Args: 3865 | > - user_id (int | str): User ID to report 3866 | > - reason (int): Reason for reporting 3867 | > 3868 | > - 1 = Nội dung nhạy cảm 3869 | > - 2 = Làm phiền 3870 | > - 3 = Lừa đảo 3871 | > - 0 = custom 3872 | > 3873 | > - content (str): Report content (work if reason = custom) 3874 | 3875 | <details> 3876 | <summary><b><i>Normal</b> code style</i></summary> 3877 | 3878 | - Outside Module Function 3879 | 3880 | ```py 3881 | bot.sendReport(<user_id>) 3882 | ``` 3883 | 3884 | </br> 3885 | 3886 | - Inside Module Function 3887 | 3888 | ```py 3889 | self.sendReport(<user_id>) 3890 | ``` 3891 | 3892 | </details> 3893 | 3894 | <details> 3895 | <summary><b><i>Async</b> code style</i></summary> 3896 | 3897 | - Outside Module Function 3898 | 3899 | ```py 3900 | asyncio.run(bot.sendReport(<user_id>)) 3901 | ``` 3902 | 3903 | </br> 3904 | 3905 | - Inside Module Function (You can use ``await`` instead.) 3906 | 3907 | ```py 3908 | await self.sendReport(<user_id>) 3909 | ``` 3910 | 3911 | </details> 3912 | 3913 | <details> 3914 | <summary><b><i>Simple</b> code style</i></summary> 3915 | 3916 | - Outside Module Function 3917 | 3918 | ```py 3919 | asyncio.run(bot.send_report(<user_id>)) 3920 | ``` 3921 | 3922 | </br> 3923 | 3924 | - Inside Module Function (You can use ``await`` instead.) 3925 | 3926 | ```py 3927 | await bot.send_report(<user_id>) 3928 | ``` 3929 | 3930 | </details> 3931 | 3932 | <!-- END sendReport --> 3933 | 3934 | </br> 3935 | 3936 | <!-- sendBusinessCard --> 3937 | 3938 | ### Send Business Card 3939 | 3940 | This function will Send business card to thread (user/group) by user ID. 3941 | 3942 | > - Args: 3943 | > - userId (int | str): Business card user ID 3944 | > - qrCodeUrl (str): QR Code link with business card profile information 3945 | > - thread_id (int | str): User/Group ID to change status in 3946 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 3947 | > - phone (int | str): Send business card with phone number 3948 | 3949 | <details> 3950 | <summary><b><i>Normal</b> code style</i></summary> 3951 | 3952 | - Outside Module Function 3953 | 3954 | ```py 3955 | bot.sendBusinessCard(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>) 3956 | ``` 3957 | 3958 | </br> 3959 | 3960 | - Inside Module Function 3961 | 3962 | ```py 3963 | self.sendBusinessCard(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>) 3964 | ``` 3965 | 3966 | </details> 3967 | 3968 | <details> 3969 | <summary><b><i>Async</b> code style</i></summary> 3970 | 3971 | - Outside Module Function 3972 | 3973 | ```py 3974 | asyncio.run(bot.sendBusinessCard(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>)) 3975 | ``` 3976 | 3977 | </br> 3978 | 3979 | - Inside Module Function (You can use ``await`` instead.) 3980 | 3981 | ```py 3982 | await self.sendBusinessCard(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>) 3983 | ``` 3984 | 3985 | </details> 3986 | 3987 | <details> 3988 | <summary><b><i>Simple</b> code style</i></summary> 3989 | 3990 | - Outside Module Function 3991 | 3992 | ```py 3993 | asyncio.run(bot.send_business_card(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>)) 3994 | ``` 3995 | 3996 | </br> 3997 | 3998 | - Inside Module Function (You can use ``await`` instead.) 3999 | 4000 | ```py 4001 | await bot.send_business_card(<userId>, <qrCodeUrl>, <thread_id>, <thread_type>) 4002 | ``` 4003 | 4004 | </details> 4005 | 4006 | <!-- END sendBusinessCard --> 4007 | 4008 | </br> 4009 | 4010 | <!-- setTypingStatus --> 4011 | 4012 | ### Set Typing Status 4013 | 4014 | This function will Set users typing status. 4015 | 4016 | > - Args: 4017 | > - thread_id: User/Group ID to change status in. 4018 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 4019 | 4020 | <details> 4021 | <summary><b><i>Normal</b> code style</i></summary> 4022 | 4023 | - Outside Module Function 4024 | 4025 | ```py 4026 | bot.setTyping(<thread_id>, <thread_type>) 4027 | ``` 4028 | 4029 | </br> 4030 | 4031 | - Inside Module Function 4032 | 4033 | ```py 4034 | self.setTyping(<thread_id>, <thread_type>) 4035 | ``` 4036 | 4037 | </details> 4038 | 4039 | <details> 4040 | <summary><b><i>Async</b> code style</i></summary> 4041 | 4042 | - Outside Module Function 4043 | 4044 | ```py 4045 | asyncio.run(bot.setTyping(<thread_id>, <thread_type>)) 4046 | ``` 4047 | 4048 | </br> 4049 | 4050 | - Inside Module Function (You can use ``await`` instead.) 4051 | 4052 | ```py 4053 | await self.setTyping(<thread_id>, <thread_type>) 4054 | ``` 4055 | 4056 | </details> 4057 | 4058 | <details> 4059 | <summary><b><i>Simple</b> code style</i></summary> 4060 | 4061 | - Outside Module Function 4062 | 4063 | ```py 4064 | asyncio.run(bot.set_typing(<thread_id>, <thread_type>)) 4065 | ``` 4066 | 4067 | </br> 4068 | 4069 | - Inside Module Function (You can use ``await`` instead.) 4070 | 4071 | ```py 4072 | await bot.set_typing(<thread_id>, <thread_type>) 4073 | ``` 4074 | 4075 | </details> 4076 | 4077 | <!-- END setTypingStatus --> 4078 | 4079 | </br> 4080 | 4081 | <!-- markAsDelivered --> 4082 | 4083 | ### Mark Message As Delivered 4084 | 4085 | This function will Mark a message as delivered. 4086 | 4087 | > - Args: 4088 | > - msgId (int | str): Message ID to set as delivered 4089 | > - cliMsgId (int | str): Client message ID 4090 | > - senderId (int | str): Message sender Id 4091 | > - thread_id (int | str): User/Group ID to mark as delivered 4092 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 4093 | 4094 | <details> 4095 | <summary><b><i>Normal</b> code style</i></summary> 4096 | 4097 | - Outside Module Function 4098 | 4099 | ```py 4100 | bot.markAsDelivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4101 | ``` 4102 | 4103 | </br> 4104 | 4105 | - Inside Module Function 4106 | 4107 | ```py 4108 | self.markAsDelivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4109 | ``` 4110 | 4111 | </details> 4112 | 4113 | <details> 4114 | <summary><b><i>Async</b> code style</i></summary> 4115 | 4116 | - Outside Module Function 4117 | 4118 | ```py 4119 | asyncio.run(bot.markAsDelivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>)) 4120 | ``` 4121 | 4122 | </br> 4123 | 4124 | - Inside Module Function (You can use ``await`` instead.) 4125 | 4126 | ```py 4127 | await self.markAsDelivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4128 | ``` 4129 | 4130 | </details> 4131 | 4132 | <details> 4133 | <summary><b><i>Simple</b> code style</i></summary> 4134 | 4135 | - Outside Module Function 4136 | 4137 | ```py 4138 | asyncio.run(bot.mark_as_delivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>)) 4139 | ``` 4140 | 4141 | </br> 4142 | 4143 | - Inside Module Function (You can use ``await`` instead.) 4144 | 4145 | ```py 4146 | await bot.mark_as_delivered(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4147 | ``` 4148 | 4149 | </details> 4150 | 4151 | <!-- END markAsDelivered --> 4152 | 4153 | </br> 4154 | 4155 | <!-- markAsRead --> 4156 | 4157 | ### Mark Message As Read 4158 | 4159 | This function will Mark a message as read. 4160 | 4161 | > - Args: 4162 | > - msgId (int | str): Message ID to set as delivered 4163 | > - cliMsgId (int | str): Client message ID 4164 | > - senderId (int | str): Message sender Id 4165 | > - thread_id (int | str): User/Group ID to mark as read 4166 | > - thread_type (ThreadType): ``ThreadType.USER``, ``ThreadType.GROUP`` 4167 | 4168 | <details> 4169 | <summary><b><i>Normal</b> code style</i></summary> 4170 | 4171 | - Outside Module Function 4172 | 4173 | ```py 4174 | bot.markAsRead(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4175 | ``` 4176 | 4177 | </br> 4178 | 4179 | - Inside Module Function 4180 | 4181 | ```py 4182 | self.markAsRead(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4183 | ``` 4184 | 4185 | </details> 4186 | 4187 | <details> 4188 | <summary><b><i>Async</b> code style</i></summary> 4189 | 4190 | - Outside Module Function 4191 | 4192 | ```py 4193 | asyncio.run(bot.markAsRead(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>)) 4194 | ``` 4195 | 4196 | </br> 4197 | 4198 | - Inside Module Function (You can use ``await`` instead.) 4199 | 4200 | ```py 4201 | await self.markAsRead(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4202 | ``` 4203 | 4204 | </details> 4205 | 4206 | <details> 4207 | <summary><b><i>Simple</b> code style</i></summary> 4208 | 4209 | - Outside Module Function 4210 | 4211 | ```py 4212 | asyncio.run(bot.mark_as_read(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>)) 4213 | ``` 4214 | 4215 | </br> 4216 | 4217 | - Inside Module Function (You can use ``await`` instead.) 4218 | 4219 | ```py 4220 | await bot.mark_as_read(<msgId>, <cliMsgId>, <senderId>, <thread_id>, <thread_type>) 4221 | ``` 4222 | 4223 | </details> 4224 | 4225 | <!-- END markAsRead --> 4226 | 4227 | </br> 4228 | 4229 | <!-- listen --> 4230 | 4231 | ### Listen 4232 | 4233 | This function will Initialize and runs the listening loop continually. 4234 | 4235 | > - Args: 4236 | > - delay (int): Delay time for each message fetch for ``requests`` type (Default: 1) 4237 | > - thread (bool): Handle messages within the thread for ``requests`` type (Default: False) 4238 | > - type (str): Type of listening (Default: websocket) 4239 | > - reconnect (int): Delay interval when reconnecting 4240 | 4241 | - Use Outside Of Function 4242 | 4243 | ```py 4244 | bot.listen() 4245 | ``` 4246 | 4247 | <!-- END listen --> 4248 | 4249 | </br> 4250 | 4251 | <!-- onListening --> 4252 | 4253 | ### On Listening 4254 | 4255 | This function is called when the client is listening. 4256 | 4257 | <details> 4258 | <summary><b><i>Normal</b> code style</i></summary> 4259 | 4260 | - Inside Module Custom Class 4261 | 4262 | ```py 4263 | def onListening(self): 4264 | .... 4265 | ``` 4266 | 4267 | </details> 4268 | 4269 | <details> 4270 | <summary><b><i>Async</b> code style</i></summary> 4271 | 4272 | - Inside Module Custom Class 4273 | 4274 | ```py 4275 | async def onListening(self): 4276 | .... 4277 | ``` 4278 | 4279 | </details> 4280 | 4281 | <details> 4282 | <summary><b><i>Simple</b> code style</i></summary> 4283 | 4284 | 4285 | - Outside Module Class 4286 | 4287 | ```py 4288 | @bot.event 4289 | async def on_listening(): 4290 | .... 4291 | ``` 4292 | 4293 | </details> 4294 | 4295 | <!-- END onListening --> 4296 | 4297 | </br> 4298 | 4299 | <!-- onMessage --> 4300 | 4301 | ### On Message 4302 | 4303 | This function is called when the client is listening, and somebody sends a message. 4304 | 4305 | > - Args: 4306 | > - mid: The message ID 4307 | > - author_id: The ID of the author 4308 | > - message: The message content of the author 4309 | > - message_object: The message (As a `Message` object) 4310 | > - thread_id: Thread ID that the message was sent to. 4311 | > - thread_type (ThreadType): Type of thread that the message was sent to. 4312 | 4313 | <details> 4314 | <summary><b><i>Normal</b> code style</i></summary> 4315 | 4316 | - Inside Module Custom Class 4317 | 4318 | ```py 4319 | def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 4320 | .... 4321 | ``` 4322 | 4323 | </details> 4324 | 4325 | <details> 4326 | <summary><b><i>Async</b> code style</i></summary> 4327 | 4328 | - Inside Module Custom Class 4329 | 4330 | ```py 4331 | async def onMessage(self, mid, author_id, message, message_object, thread_id, thread_type): 4332 | .... 4333 | ``` 4334 | 4335 | </details> 4336 | 4337 | <details> 4338 | <summary><b><i>Simple</b> code style</i></summary> 4339 | 4340 | > - In simple type, all event or register_handler functions use args with context. 4341 | > 4342 | > - Args Context Example: 4343 | > - ctx.message_id 4344 | > - ctx.author_id 4345 | > - ctx.message 4346 | > - ctx.message_object 4347 | > - ctx.thread_id 4348 | > - ctx.thread_type 4349 | 4350 | - Outside Module Class 4351 | 4352 | ```py 4353 | @bot.event 4354 | async def on_message(ctx): 4355 | .... 4356 | ``` 4357 | 4358 | </details> 4359 | 4360 | <!-- END onMessage --> 4361 | 4362 | </br> 4363 | 4364 | <!-- onEvent --> 4365 | 4366 | ### On Event 4367 | 4368 | This function is called when the client listening, and some events occurred. 4369 | 4370 | > - Args: 4371 | > - event_data (EventObject): Event data (As a `EventObject` object) 4372 | > - event_type (EventType/GroupEventType): Event Type 4373 | 4374 | <details> 4375 | <summary><b><i>Normal</b> code style</i></summary> 4376 | 4377 | - Inside Module Custom Class 4378 | 4379 | ```py 4380 | def onEvent(self, event_data, event_type): 4381 | .... 4382 | ``` 4383 | 4384 | </details> 4385 | 4386 | <details> 4387 | <summary><b><i>Async</b> code style</i></summary> 4388 | 4389 | - Inside Module Custom Class 4390 | 4391 | ```py 4392 | async def onEvent(self, event_data, event_type): 4393 | .... 4394 | ``` 4395 | 4396 | </details> 4397 | 4398 | <details> 4399 | <summary><b><i>Simple</b> code style</i></summary> 4400 | 4401 | > - In simple type, all event or register_handler functions use args with context. 4402 | > 4403 | > - Args Context Example: 4404 | > - ctx.event_data 4405 | > - ctx.event_type 4406 | 4407 | - Outside Module Class 4408 | 4409 | ```py 4410 | @bot.event 4411 | async def on_event(ctx): 4412 | .... 4413 | ``` 4414 | 4415 | </details> 4416 | 4417 | <!-- END onEvent --> 4418 | 4419 | </br> 4420 | 4421 | <!-- Messages --> 4422 | 4423 | ### Messages 4424 | 4425 | Represents a Zalo message. 4426 | 4427 | > - Args: 4428 | > - text (str): The actual message 4429 | > - style (MessageStyle/MultiMsgStyle): A ``MessageStyle`` or ``MultiMsgStyle`` objects 4430 | > - mention (Mention/MultiMention): A ``Mention`` or ``MultiMention`` objects 4431 | > - parse_mode (str): Format messages in ``Markdown``, ``HTML`` style 4432 | 4433 | ```py 4434 | Message(text=<text>, mention=<mention>, style=<style>) 4435 | ``` 4436 | 4437 | <!-- END Messages --> 4438 | 4439 | </br> 4440 | 4441 | <!-- MessageStyle --> 4442 | 4443 | ### Message Style 4444 | 4445 | Style for message. 4446 | 4447 | > - Args: 4448 | > - offset (int): The starting position of the style. Defaults to 0. 4449 | > - length (int): The length of the style. Defaults to 1. 4450 | > - style (str): The type of style. Can be "font", "bold", "italic", "underline", "strike", or "color". Defaults to "font". 4451 | > - color (str): The color of the style in hexadecimal format (e.g. "ffffff"). Only applicable when style is "color". Defaults to "ffffff". 4452 | > - size (int | str): The font size of the style. Only applicable when style is "font". Defaults to "18". 4453 | > - auto_format (bool): If there are multiple styles (used in ``MultiMsgStyle``) then set it to False. Default is True (1 style) 4454 | 4455 | - Example 4456 | 4457 | - **bold** style with offset is 5, length is 10. 4458 | 4459 | ```py 4460 | style = MessageStyle(offset=5, length=10, style="bold") 4461 | ... 4462 | ``` 4463 | 4464 | </br> 4465 | 4466 | - color style with offset is 10, length is 5 and color="![#ff0000](https://placehold.co/20x15/ff0000/ff0000.png) `#ff0000`" 4467 | 4468 | ```py 4469 | style = MessageStyle(offset=10, ``length=5``, style="color", color="ff0000") 4470 | ... 4471 | ``` 4472 | 4473 | </br> 4474 | 4475 | - font style with offset is 15, length is 8 and size="24" (Customize font size to 24) 4476 | 4477 | ```py 4478 | style = MessageStyle(offset=15, length=8, style="font", size="24") 4479 | ... 4480 | ``` 4481 | 4482 | <!-- END MessageStyle --> 4483 | 4484 | </br> 4485 | 4486 | <!-- MultiMsgStyle --> 4487 | 4488 | ### Multiple Message Style 4489 | 4490 | Multiple style for message. 4491 | 4492 | > - Args: 4493 | > - listStyle (MessageStyle): A list of ``MessageStyle`` objects to be combined into a single style format. 4494 | 4495 | ```py 4496 | style = MultiMsgStyle([ 4497 | MessageStyle(offset=<text>, length=<mention>, style=<style>, color=<color>, size=<size>, auto_format=False), 4498 | MessageStyle(offset=<text>, length=<mention>, style=<style>, color=<color>, size=<size>, auto_format=False), 4499 | ... 4500 | ]) 4501 | ``` 4502 | 4503 | <!-- END MultiMsgStyle --> 4504 | 4505 | </br> 4506 | 4507 | <!-- Mention --> 4508 | 4509 | ### Mention 4510 | 4511 | Represents a @mention. 4512 | 4513 | > - Args: 4514 | > - uid (str): The user ID to be mentioned. 4515 | > - length (int): The length of the mention. Defaults to 1. 4516 | > - offset (int): The starting position of the mention. Defaults to 0. 4517 | > - auto_format (bool): If there are multiple mention (used in ``MultiMention``) then set it to False. Default is True (1 mention). 4518 | 4519 | ```py 4520 | mention = Mention(uid=<uid>, length=<length>, offset=<offset>) 4521 | ... 4522 | ``` 4523 | 4524 | </br> 4525 | 4526 | - Mention user id *1234567890* with offset is 10 and length is 5. 4527 | 4528 | ```py 4529 | mention = Mention("1234567890", length=5, offset=10) 4530 | ... 4531 | ``` 4532 | 4533 | <!-- END Mention --> 4534 | 4535 | </br> 4536 | 4537 | <!-- MultiMention --> 4538 | 4539 | ### Multiple Mention 4540 | 4541 | Represents multiple @mentions. 4542 | 4543 | > - Args: 4544 | > - listMention (Mention): A list of ``Mention`` objects to be combined into a single mention format. 4545 | 4546 | ```py 4547 | mention = MultiMention([ 4548 | Mention(uid=<uid>, length=<length>, offset=<offset>, auto_format=False), 4549 | Mention(uid=<uid>, length=<length>, offset=<offset>, auto_format=False), 4550 | ... 4551 | ]) 4552 | ``` 4553 | 4554 | </br> 4555 | 4556 | - Mention user id *1234567890* with offset is 10 and length is 5. 4557 | - Mention user id *9876543210* with offset is 20 and length is 3. 4558 | 4559 | ```py 4560 | mention1 = Mention("1234567890", length=5, offset=10) 4561 | mention2 = Mention("9876543210", length=3, offset=20) 4562 | mention = MultiMention([mention1, mention2]) 4563 | ``` 4564 | 4565 | <!-- END MultiMention --> 4566 | 4567 | </br> 4568 | 4569 | ## Example 4570 | 4571 | See [examples](examples) folder to learn more about ``zlapi``. 4572 | 4573 | </br> 4574 | 4575 | ## Acknowledgments 4576 | 4577 | - This project was originally inspired by [fbchat](https://github.com/fbchat-dev/fbchat). 4578 | - listen ``websocket`` type taken from [zca-js](https://github.com/RFS-ADRENO/zca-js). 4579 | 4580 | - Thanks for support: 4581 | - [Crow](https://t.me/crowmatacc) for Hosting. 4582 | - [Duy Hoang](https://t.me/Tcp_API) for the Video Tutorial. 4583 | - [Nguyen Hong Anh Duc](https://t.me/ducknha) for the Example. 4584 | - [Khang Phan](https://www.facebook.com/khang.phan27.info) for help fix the ``listen`` function error. 4585 | 4586 | ## Contact For Help 4587 | 4588 | - <img src="https://upload.wikimedia.org/wikipedia/commons/8/83/Telegram_2019_Logo.svg" alt="Telegram Icon" width=20 height=15/> Telegram: [Vexx](https://t.me/vrxx1337) 4589 | - <img src="https://raw.githubusercontent.com/dheereshagrwal/colored-icons/master/public/logos/facebook/facebook.svg" alt="Facebook Icon" width=20 height=15/> Facebook: [Lê Quốc Việt](https://www.facebook.com/profile.php?id=100094031375075) 4590 | --------------------------------------------------------------------------------