├── app.json
├── heroku.yml
├── runtime.txt
├── Procfile
├── start.sh
├── utils
├── __init__.py
└── logging_setup.py
├── core
├── __init__.py
└── start.py
├── modules
├── __init__.py
└── notify.py
├── requirements.txt
├── docker-compose.yml
├── sample.env
├── Dockerfile
├── main.py
├── user.py
├── app.py
├── LICENSE
├── config.py
└── README.md
/app.json:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/heroku.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.10.13
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: bash start.sh
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python3 main.py
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
1 | from .logging_setup import LOGGER
--------------------------------------------------------------------------------
/core/__init__.py:
--------------------------------------------------------------------------------
1 | from .start import setup_start_handler
--------------------------------------------------------------------------------
/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from .notify import setup_modules_handlers
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pyrofork
2 | asyncio
3 | python-dotenv
4 | python-dateutil
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | smartmonitor:
3 | build: .
4 | container_name: smartmonitor
5 | ports:
6 | - "8000:8000"
7 | env_file:
8 | - .env
9 | volumes:
10 | - .:/app
--------------------------------------------------------------------------------
/sample.env:
--------------------------------------------------------------------------------
1 | API_ID=YOUR_API_ID_HERE
2 | API_HASH=YOUR_API_HASH_HERE
3 | BOT_TOKEN=YOUR_BOT_TOKEN_HERE
4 | SESSION_STRING=YOUR_SESSION_STRING_HERE
5 | OWNER_ID=YOUR_USER_ID_HERE
6 | UPDATE_CHANNEL_URL=YOUR_UPDATE_CHANNEL_URL_HERE
7 | CHANNEL_ID=MONITOR_CHANNEL_ID
8 | COMMAND_PREFIX=!|.|#|,|/
9 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9-slim-buster
2 |
3 | RUN apt update && apt install -y git curl && apt clean
4 |
5 | WORKDIR /app
6 |
7 | COPY requirements.txt .
8 | RUN pip install --no-cache-dir -r requirements.txt
9 |
10 | COPY . .
11 |
12 | RUN chmod +x start.sh
13 |
14 | EXPOSE 8000
15 |
16 | CMD ["bash", "start.sh"]
17 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | from utils import LOGGER
2 | from modules import setup_modules_handlers
3 | from core import setup_start_handler
4 | from app import app
5 | from user import user
6 |
7 | setup_modules_handlers(app)
8 | setup_start_handler(app)
9 |
10 | LOGGER.info("Bot Successfully Started! 💥")
11 | user.start()
12 | app.run()
13 |
--------------------------------------------------------------------------------
/user.py:
--------------------------------------------------------------------------------
1 | #Copyright @ISmartDevs
2 | #Channel t.me/TheSmartDev
3 | from pyrogram import Client
4 | from utils import LOGGER
5 | from config import SESSION_STRING
6 |
7 | # Initialize User Client
8 | LOGGER.info("Creating User Client From SESSION_STRING")
9 |
10 | user = Client(
11 | "user_session",
12 | session_string=SESSION_STRING,
13 | workers=1000
14 | )
15 |
16 | LOGGER.info("User Client Successfully Created!")
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | #Copyright @ISmartDevs
2 | #Channel t.me/TheSmartDev
3 | from pyrogram import Client
4 | from utils import LOGGER
5 | from config import (
6 | API_ID,
7 | API_HASH,
8 | BOT_TOKEN
9 | )
10 |
11 | LOGGER.info("Creating Bot Client From BOT_TOKEN")
12 |
13 | app = Client(
14 | "SmartTools",
15 | api_id=API_ID,
16 | api_hash=API_HASH,
17 | bot_token=BOT_TOKEN,
18 | workers=1000
19 | )
20 |
21 | LOGGER.info("Bot Client Created Successfully!")
--------------------------------------------------------------------------------
/utils/logging_setup.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from logging.handlers import RotatingFileHandler
3 |
4 | logging.basicConfig(
5 | level=logging.INFO,
6 | format="%(asctime)s - %(levelname)s - %(message)s",
7 | datefmt='%Y-%m-%d %H:%M:%S',
8 | handlers=[
9 | RotatingFileHandler("botlog.txt", maxBytes=50000000, backupCount=10),
10 | logging.StreamHandler()
11 | ]
12 | )
13 |
14 | logging.getLogger("pyrogram").setLevel(logging.ERROR)
15 | logging.getLogger("aiohttp").setLevel(logging.ERROR)
16 | logging.getLogger("apscheduler").setLevel(logging.ERROR)
17 |
18 | LOGGER = logging.getLogger(__name__)
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 ISmartCoder
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.
--------------------------------------------------------------------------------
/core/start.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
3 | from pyrogram.enums import ParseMode, ChatType
4 | from config import UPDATE_CHANNEL_URL, COMMAND_PREFIX
5 |
6 |
7 | def setup_start_handler(app: Client):
8 | @app.on_message(filters.command(["start"], prefixes=COMMAND_PREFIX) & (filters.private | filters.group))
9 | async def start_message(client: Client, message: Message):
10 | chat_id = message.chat.id
11 |
12 | full_name = "User"
13 | if message.from_user:
14 | first_name = message.from_user.first_name or ""
15 | last_name = message.from_user.last_name or ""
16 | full_name = f"{first_name} {last_name}".strip()
17 |
18 | response_text = (
19 | f"Hi {full_name}! Welcome To This Bot\n"
20 | "━━━━━━━━━━━━━━━━━━━━━━\n"
21 | f"Smart Monitor: The ultimate toolkit on Telegram can monitor any channels or groups actions where he is admin and notify owner.\n"
22 | "━━━━━━━━━━━━━━━━━━━━━━\n"
23 | "Don't Forget To Join Here For Updates!".format(UPDATE_CHANNEL_URL=UPDATE_CHANNEL_URL)
24 | )
25 |
26 | await client.send_message(
27 | chat_id=chat_id,
28 | text=response_text,
29 | parse_mode=ParseMode.HTML,
30 | reply_markup=InlineKeyboardMarkup([
31 | [[InlineKeyboardButton("Update Channel", url="UPDATE_CHANNEL_URL")]]
32 | ]),
33 | disable_web_page_preview=True,
34 | )
35 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dotenv import load_dotenv
3 |
4 | load_dotenv()
5 |
6 | def get_env_or_default(key, default=None, cast_func=str):
7 | value = os.getenv(key)
8 | if value is not None and value.strip() != "":
9 | try:
10 | return cast_func(value)
11 | except (ValueError, TypeError):
12 | return default
13 | return default
14 |
15 | # Load main credentials
16 | API_ID = get_env_or_default("API_ID", cast_func=int)
17 | API_HASH = get_env_or_default("API_HASH")
18 | BOT_TOKEN = get_env_or_default("BOT_TOKEN")
19 | SESSION_STRING = get_env_or_default("SESSION_STRING")
20 | OWNER_ID = get_env_or_default("OWNER_ID", cast_func=int)
21 | CHANNEL_ID = get_env_or_default("CHANNEL_ID", cast_func=int)
22 |
23 | # Load command prefixes
24 | raw_prefixes = get_env_or_default("COMMAND_PREFIX", "!|.|#|,|/")
25 | COMMAND_PREFIX = [prefix.strip() for prefix in raw_prefixes.split("|") if prefix.strip()]
26 |
27 | # Update channel
28 | UPDATE_CHANNEL_URL = get_env_or_default("UPDATE_CHANNEL_URL", "t.me/TheSmartDev")
29 |
30 | # Required variable validation
31 | required_vars = {
32 | "API_ID": API_ID,
33 | "API_HASH": API_HASH,
34 | "BOT_TOKEN": BOT_TOKEN,
35 | "SESSION_STRING": SESSION_STRING,
36 | "OWNER_ID": OWNER_ID,
37 | "CHANNEL_ID": CHANNEL_ID,
38 | }
39 |
40 | for var_name, var_value in required_vars.items():
41 | if var_value is None or (isinstance(var_value, str) and var_value.strip() == ""):
42 | raise ValueError(f"Required variable {var_name} is missing or invalid.")
43 |
44 | if not COMMAND_PREFIX:
45 | raise ValueError("No command prefixes found. Set COMMAND_PREFIX in .env.")
46 |
47 | print("Loaded COMMAND_PREFIX:", COMMAND_PREFIX)
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🔥 SmartMonitorBot 💀👀
2 |
3 | SmartMonitorBot is the ultimate Telegram channel event tracker, crafted with Pyrofork. This beast monitors your supergroups and channels like a cyber hawk, delivering real-time alerts to the owner for every major action. Powered by `Client.get_chat_event_log()`, it’s your go-to for staying in control. Rule your Telegram empire with style! 🚀
4 |
5 | 
6 | 
7 | 
8 | 
9 | 
10 | 
11 | 
12 | 
13 | 
14 | 
15 |
16 | ---
17 |
18 | ## ⚠️ Ethical Use Warning
19 |
20 | This project is open-source under the MIT License, but **do not copy the code** without proper attribution. Instead, **fork the repository** on [GitHub](https://github.com/TheSmartDevs/SmartMonitorBot) and customize it for your needs. If you use any part of this code, **give credit** to [@ISmartCoder](https://github.com/abirxdhack) and link back to this repository. Respect the hustle and keep it ethical! 🙏
21 |
22 | ---
23 |
24 | ## ✨ Epic Features ✅
25 |
26 | SmartMonitorBot is loaded with features that make it the slickest Telegram monitoring tool:
27 |
28 | - **Instant Alerts**: Get pinged the moment something happens in your channel. No delays, just raw speed. ⚡️
29 | - **All-Seeing Event Tracking**: Catches every move, including:
30 | - Title, description, username, or photo changes 📝
31 | - Invite, signature, or slow mode toggles 🔄
32 | - Pinned/unpinned messages 📌
33 | - Edited or deleted messages ✏️🗑️
34 | - Joins, leaves, or invites 👥
35 | - Bans, unbans, admin promotions, or demotions 🚨
36 | - Group calls, sticker sets, linked chats, or location updates 🎙️🌍
37 | - Subscription extensions or pre-history toggles ❄️
38 | - **One-Command Start**: Hit `/start`, and the bot auto-notifies the owner. Zero hassle. 😎
39 | - **Deployment Nirvana**: Heroku, VPS with `screen`, or Docker—pick your vibe. 🐳
40 | - **Custom Prefixes**: Set prefixes like `!`, `.`, `#`, `,`, or `/` via `.env`. Make it yours. ⚙️
41 | - **Bulletproof Config**: Validates required env vars to keep things rock-solid. No crashes allowed. 💪
42 |
43 | ---
44 |
45 | ## 💀 Events Watched Like a Boss
46 |
47 | Here’s the full rundown of what SmartMonitorBot tracks (from `EVENT_TYPE_MAP`):
48 |
49 | | Event Type | What’s Happening? |
50 | |------------|-------------------|
51 | | `ChannelAdminLogEventActionChangeTitle` | Channel title got a glow-up |
52 | | `ChannelAdminLogEventActionChangeAbout` | Description revamped |
53 | | `ChannelAdminLogEventActionChangeUsername` | Username switched |
54 | | `ChannelAdminLogEventActionChangePhoto` | New profile pic dropped |
55 | | `ChannelAdminLogEventActionToggleInvites` | Invites flipped on/off |
56 | | `ChannelAdminLogEventActionToggleSignatures` | Signatures toggled |
57 | | `ChannelAdminLogEventActionUpdatePinned` | Message pinned or unpinned |
58 | | `ChannelAdminLogEventActionEditMessage` | Message edited |
59 | | `ChannelAdminLogEventActionDeleteMessage` | Message yeeted |
60 | | `ChannelAdminLogEventActionParticipantJoin` | New member joined the party |
61 | | `ChannelAdminLogEventActionParticipantLeave` | Someone ghosted |
62 | | `ChannelAdminLogEventActionParticipantInvite` | Fresh invite sent |
63 | | `ChannelAdminLogEventActionParticipantToggleBan` | User banned or unbanned |
64 | | `ChannelAdminLogEventActionParticipantToggleAdmin` | Admin promoted or demoted |
65 | | `ChannelAdminLogEventActionChangeStickerSet` | Sticker set swapped |
66 | | `ChannelAdminLogEventActionTogglePreHistoryHidden` | Pre-history visibility toggled |
67 | | `ChannelAdminLogEventActionDefaultBannedRights` | Default banned rights updated |
68 | | `ChannelAdminLogEventActionStartGroupCall` | Group call started |
69 | | `ChannelAdminLogEventActionEndGroupCall` | Group call ended |
70 | | `ChannelAdminLogEventActionChangeLinkedChat` | Linked chat switched |
71 | | `ChannelAdminLogEventActionChangeLocation` | Location updated |
72 | | `ChannelAdminLogEventActionToggleSlowMode` | Slow mode flipped |
73 | | `ChannelAdminLogEventActionToggleSubExtend` | Subscription extension toggled |
74 |
75 | ---
76 |
77 | ## 📂 Project Structure
78 |
79 | Here’s the layout of this masterpiece:
80 |
81 | ```
82 | SmartMonitorBot/
83 | ├── core/ # Core bot logic 💻
84 | │ └── start.py
85 | ├── modules/ # Notification magic ✨
86 | │ ├── notify.py
87 | │ └── __init__.py
88 | ├── utils/ # Utility spells 🛠️
89 | │ ├── event.py
90 | │ ├── logging_setup.py
91 | │ └── __init__.py
92 | ├── sample.env # Env template 📜
93 | ├── app.json # Heroku config ⚙️
94 | ├── app.py # App entry point 🚪
95 | ├── config.py # Config wizardry 🪄
96 | ├── docker-compose.yml # Docker setup 🐳
97 | ├── Dockerfile # Docker blueprint 📦
98 | ├── heroku.yml # Heroku deployment 📡
99 | ├── main.py # Main bot engine 🔥
100 | ├── Procfile # Heroku process 📋
101 | ├── requirements.txt # Dependencies list 📦
102 | ├── runtime.txt # Runtime spec ⚡️
103 | ├── start.sh # Startup script 🏁
104 | ├── user.py # User client logic 👤
105 | └── README.md # This epic guide 📖
106 | ```
107 |
108 | ---
109 |
110 | ## 🚀 Get It Running
111 |
112 | ### Prerequisites ✅
113 | - Python 3.8+ (local or VPS)
114 | - Docker & Docker Compose (for containerized deployment)
115 | - Telegram account with admin rights in your supergroup/channel
116 | - API credentials from [my.telegram.org](https://my.telegram.org)
117 | - Bot token from [@BotFather](https://t.me/BotFather)
118 |
119 | ### Setup Steps 👀
120 | 1. **Clone the Repo**:
121 | ```bash
122 | git clone https://github.com/TheSmartDevs/SmartMonitorBot.git
123 | cd SmartMonitorBot
124 | ```
125 |
126 | 2. **Configure `.env`**:
127 | - Copy the sample:
128 | ```bash
129 | cp sample.env .env
130 | ```
131 | - Add your credentials:
132 | ```
133 | API_ID=your_api_id
134 | API_HASH=your_api_hash
135 | BOT_TOKEN=your_bot_token
136 | SESSION_STRING=your_session_string
137 | OWNER_ID=your_user_id
138 | CHANNEL_ID=your_channel_id
139 | UPDATE_CHANNEL_URL=your_update_channel_url
140 | COMMAND_PREFIX=!|.|#|,|/
141 | ```
142 |
143 | 3. **Install Dependencies**:
144 | - Local/VPS:
145 | ```bash
146 | pip install -r requirements.txt
147 | ```
148 | - Docker handles this automatically.
149 |
150 | 4. **Fire It Up**:
151 | - **Local/VPS**:
152 | ```bash
153 | python main.py
154 | ```
155 | - **VPS with `screen`** (for persistent sessions):
156 | ```bash
157 | screen -S SmartMonitorBot
158 | python main.py
159 | ```
160 | Detach with `Ctrl+A`, then `D`. Reattach with:
161 | ```bash
162 | screen -r SmartMonitorBot
163 | ```
164 | - **Docker**:
165 | ```bash
166 | docker compose up --build --remove-orphans
167 | ```
168 | Stop it with:
169 | ```bash
170 | docker compose down
171 | ```
172 |
173 | 5. **Activate the Bot**:
174 | - Send `/start` to the bot, and it’ll auto-notify the owner of events. Done deal. ✅
175 |
176 | ---
177 |
178 | ## 🌐 Deployment Options
179 |
180 | ### Heroku Deployment 🚀
181 | Launch on Heroku with one click:
182 |
183 | [](https://heroku.com/deploy?template=https://github.com/TheSmartDevs/SmartMonitorBot)
184 |
185 | 1. Hit the button above.
186 | 2. Fill in your `.env` vars in Heroku’s dashboard.
187 | 3. Deploy and start owning your channel! 👀
188 |
189 | ### VPS Deployment with `screen` ❄️
190 | 1. Install Python and `screen`:
191 | ```bash
192 | sudo apt update
193 | sudo apt install python3 python3-pip screen
194 | ```
195 | 2. Clone the repo and set up `.env`.
196 | 3. Install dependencies:
197 | ```bash
198 | pip install -r requirements.txt
199 | ```
200 | 4. Run in a `screen` session:
201 | ```bash
202 | screen -S SmartMonitorBot
203 | python main.py
204 | ```
205 | 5. Detach (`Ctrl+A`, `D`) and check back with:
206 | ```bash
207 | screen -r SmartMonitorBot
208 | ```
209 |
210 | ### Docker Deployment 🐳
211 | 1. Install Docker & Docker Compose:
212 | ```bash
213 | sudo apt install docker.io docker-compose
214 | ```
215 | 2. Clone the repo and configure `.env`.
216 | 3. Build and run:
217 | ```bash
218 | docker compose up --build --remove-orphans
219 | ```
220 | 4. Shut it down:
221 | ```bash
222 | docker compose down
223 | ```
224 |
225 | ---
226 |
227 | ## 🤝 Contributing
228 |
229 | Want to make this bot even crazier? Fork the repo, customize, and submit PRs at [GitHub](https://github.com/TheSmartDevs/SmartMonitorBot). Keep the code tight, add tests, and respect the ethical warning above. Let’s build something epic together! ✅
230 |
231 | ---
232 |
233 | ## 📜 License
234 |
235 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
236 |
237 | ---
238 |
239 | ## 📬 Connect
240 |
241 | - **Owner**: [@ISmartCoder](https://github.com/abirxdhack) 💀
242 | - **Update Channel**: [t.me/TheSmartDev](https://t.me/TheSmartDev) 👀
243 |
244 | Monitor like a boss with SmartMonitorBot! 🔥
--------------------------------------------------------------------------------
/modules/notify.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import datetime
3 | from pyrogram import Client, filters
4 | from pyrogram.errors import FloodWait, ChatAdminRequired
5 | from pyrogram.enums import ParseMode
6 | from pyrogram.raw.types import ChannelAdminLogEventsFilter
7 | from pyrogram.raw.functions.channels import GetAdminLog
8 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
9 | from app import app
10 | from user import user
11 | from config import CHANNEL_ID, OWNER_ID, UPDATE_CHANNEL_URL
12 |
13 | EVENT_TYPE_MAP = {
14 | "ChannelAdminLogEventActionChangeTitle": "Changed channel title",
15 | "ChannelAdminLogEventActionChangeAbout": "Changed channel description",
16 | "ChannelAdminLogEventActionChangeUsername": "Changed channel username",
17 | "ChannelAdminLogEventActionChangePhoto": "Changed channel photo",
18 | "ChannelAdminLogEventActionToggleInvites": "Toggled invites",
19 | "ChannelAdminLogEventActionToggleSignatures": "Toggled signatures",
20 | "ChannelAdminLogEventActionUpdatePinned": "Pinned/unpinned message",
21 | "ChannelAdminLogEventActionEditMessage": "Edited message",
22 | "ChannelAdminLogEventActionDeleteMessage": "Deleted message",
23 | "ChannelAdminLogEventActionParticipantJoin": "Participant joined",
24 | "ChannelAdminLogEventActionParticipantLeave": "Participant left",
25 | "ChannelAdminLogEventActionParticipantInvite": "Invited participant",
26 | "ChannelAdminLogEventActionParticipantToggleBan": "Banned/unbanned user",
27 | "ChannelAdminLogEventActionParticipantToggleAdmin": "Promoted/demoted admin",
28 | "ChannelAdminLogEventActionChangeStickerSet": "Changed sticker set",
29 | "ChannelAdminLogEventActionTogglePreHistoryHidden": "Toggled pre-history hidden",
30 | "ChannelAdminLogEventActionDefaultBannedRights": "Changed default banned rights",
31 | "ChannelAdminLogEventActionStartGroupCall": "Started group call",
32 | "ChannelAdminLogEventActionEndGroupCall": "Ended group call",
33 | "ChannelAdminLogEventActionChangeLinkedChat": "Changed linked chat",
34 | "ChannelAdminLogEventActionChangeLocation": "Changed location",
35 | "ChannelAdminLogEventActionToggleSlowMode": "Toggled slow mode",
36 | "ChannelAdminLogEventActionToggleSubExtend": "Toggled subscription extension",
37 | }
38 |
39 | def setup_modules_handlers(app):
40 | async def send_notification(event_description, user_name, user_id, channel_id, event_date):
41 | try:
42 | formatted_time = event_date.strftime("%I:%M %p")
43 | formatted_date = event_date.strftime("%d-%m-%Y")
44 | except (ValueError, TypeError) as e:
45 | formatted_time = "Invalid time"
46 | formatted_date = "Invalid date"
47 | print(f"Error formatting event date: {e}")
48 |
49 | chat_id_display = f"{channel_id}"
50 | if "Posted new message" in event_description:
51 | alert_title = "Alert: New Message Posted in Channel"
52 | else:
53 | alert_title = "Alert: Admin Changed Channel Settings"
54 | error_message = (
55 | f"**🔍 {alert_title} 📋**\n"
56 | "**━━━━━━━━━━━━━━━━**\n"
57 | f"**• COMMAND:** `Admin Action`\n"
58 | f"**• EVENT TYPE:** `{event_description}`\n"
59 | f"**• USER NAME:** `{user_name}`\n"
60 | f"**• USER ID:** `{user_id}`\n"
61 | f"**• CHANNEL ID:** `{chat_id_display}`\n"
62 | f"**• TIME:** `{formatted_time}`\n"
63 | f"**• DATE:** `{formatted_date}`\n"
64 | "**━━━━━━━━━━━━━━━━**\n"
65 | "**🔍 Always Check & Take Action 📋**"
66 | )
67 |
68 | keyboard = InlineKeyboardMarkup(
69 | [
70 | [
71 | InlineKeyboardButton("User's Profile", user_id=user_id if user_id != "N/A" else OWNER_ID),
72 | InlineKeyboardButton("Developer", user_id=OWNER_ID)
73 | ],
74 | [
75 | InlineKeyboardButton("Updates Channel", url=UPDATE_CHANNEL_URL)
76 | ]
77 | ]
78 | )
79 |
80 | await app.send_message(
81 | OWNER_ID,
82 | error_message,
83 | parse_mode=ParseMode.MARKDOWN,
84 | disable_web_page_preview=True,
85 | reply_markup=keyboard
86 | )
87 |
88 | def get_user_name(from_user):
89 | if from_user:
90 | user_name = from_user.first_name
91 | if not user_name and from_user.username:
92 | user_name = f"@{from_user.username}"
93 | elif not user_name:
94 | user_name = "Anonymous"
95 | if from_user.last_name:
96 | user_name += f" {from_user.last_name}"
97 | return user_name
98 | return "Anonymous"
99 |
100 | @app.on_message(filters.chat(CHANNEL_ID) & filters.create(lambda _, __, m: m.from_user is not None))
101 | async def handle_new_message(client: Client, message: Message):
102 | try:
103 | chat_member = await client.get_chat_member(CHANNEL_ID, message.from_user.id)
104 | if not chat_member.privileges and chat_member.status != "creator":
105 | return
106 |
107 | user_id = message.from_user.id
108 | user_name = get_user_name(message.from_user)
109 |
110 | event_date = message.date.astimezone(datetime.timezone(datetime.timedelta(hours=6)))
111 |
112 | await send_notification(
113 | event_description="Posted new message (admin)",
114 | user_name=user_name,
115 | user_id=user_id,
116 | channel_id=CHANNEL_ID,
117 | event_date=event_date
118 | )
119 | except Exception as e:
120 | error_msg = f"**❌ Error processing admin message in channel `{CHANNEL_ID}`: {str(e)}**"
121 | print(error_msg)
122 | await client.send_message(
123 | OWNER_ID,
124 | error_msg,
125 | parse_mode=ParseMode.MARKDOWN,
126 | disable_web_page_preview=True
127 | )
128 |
129 | @app.on_message(filters.chat(CHANNEL_ID))
130 | async def handle_new_post(client: Client, message: Message):
131 | try:
132 | user_name = "Anonymous"
133 | user_id = "N/A"
134 |
135 | if message.from_user:
136 | user_id = message.from_user.id
137 | user_name = get_user_name(message.from_user)
138 | elif message.sender_chat:
139 | user_name = message.sender_chat.title or "Channel"
140 | user_id = message.sender_chat.id
141 |
142 | event_date = message.date.astimezone(datetime.timezone(datetime.timedelta(hours=6)))
143 |
144 | await send_notification(
145 | event_description="Posted new message",
146 | user_name=user_name,
147 | user_id=user_id,
148 | channel_id=CHANNEL_ID,
149 | event_date=event_date
150 | )
151 |
152 | print(f"New message detected in channel {CHANNEL_ID}: {message.text or 'No text'}")
153 | except Exception as e:
154 | error_msg = f"**❌ Error processing new post in channel `{CHANNEL_ID}`: {str(e)}**"
155 | print(error_msg)
156 | await client.send_message(
157 | OWNER_ID,
158 | error_msg,
159 | parse_mode=ParseMode.MARKDOWN,
160 | disable_web_page_preview=True
161 | )
162 |
163 | async def main():
164 | while not (app.is_connected and user.is_connected):
165 | try:
166 | await asyncio.sleep(0.5)
167 | await app.get_me()
168 | await user.get_me()
169 | except Exception:
170 | continue
171 |
172 | print("Bot and user clients started...")
173 |
174 | try:
175 | channel = await user.get_chat(CHANNEL_ID)
176 | channel_id = channel.id
177 | print(f"Monitoring channel: {channel.title} ({CHANNEL_ID})")
178 | except Exception as e:
179 | error_msg = f"**❌ Sorry Channel Invalid `{CHANNEL_ID}`: {str(e)}**"
180 | print(error_msg)
181 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
182 | return
183 |
184 | try:
185 | chat_member = await user.get_chat_member(CHANNEL_ID, "me")
186 | if not chat_member.privileges or not chat_member.privileges.can_manage_chat:
187 | error_msg = f"**❌ User Client Don't Have Enough Permission Bro `{CHANNEL_ID}`**"
188 | print(error_msg)
189 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
190 | return
191 | except ChatAdminRequired:
192 | error_msg = f"**❌ User Client Not Admin In Base Channel `{CHANNEL_ID}`**"
193 | print(error_msg)
194 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
195 | return
196 | except Exception as e:
197 | error_msg = f"**❌ Can Not Verify User's ChatMemberStatus In `{CHANNEL_ID}`: {str(e)}**"
198 | print(error_msg)
199 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
200 | return
201 |
202 | try:
203 | bot_member = await app.get_chat_member(CHANNEL_ID, (await app.get_me()).id)
204 | if not bot_member.privileges or not bot_member.privileges.can_manage_chat:
205 | error_msg = f"**❌ Bot Client Does Not Have Proper Permission In `{CHANNEL_ID}`**"
206 | print(error_msg)
207 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
208 | return
209 | except ChatAdminRequired:
210 | error_msg = f"**❌ Bot Client Not Admin In `{CHANNEL_ID}`**"
211 | print(error_msg)
212 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
213 | return
214 | except Exception as e:
215 | error_msg = f"**❌ Can Not Verify Bot Client ChatMemberStatus In `{CHANNEL_ID}`: {str(e)}**"
216 | print(error_msg)
217 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
218 | return
219 |
220 | try:
221 | admin_log = await user.invoke(
222 | GetAdminLog(
223 | channel=await user.resolve_peer(channel_id),
224 | q="",
225 | events_filter=ChannelAdminLogEventsFilter(),
226 | admins=None,
227 | max_id=0, # Fixed from max_idouples
228 | min_id=0,
229 | limit=1
230 | )
231 | )
232 | except ChatAdminRequired:
233 | error_msg = f"**❌ User Client Disallowed To View Logs `{CHANNEL_ID}`**"
234 | print(error_msg)
235 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
236 | return
237 | except Exception as e:
238 | error_msg = f"**❌ User Client Failed To Retrieve Logs From `{CHANNEL_ID}`: {str(e)}**"
239 | print(error_msg)
240 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
241 | return
242 |
243 | now = datetime.datetime.now().astimezone(datetime.timezone(datetime.timedelta(hours=6)))
244 | startup_msg = f"**Smart Monitor Is Alive & Start Monitoring `{channel.title}`**"
245 | await app.send_message(
246 | OWNER_ID,
247 | startup_msg,
248 | parse_mode=ParseMode.MARKDOWN,
249 | disable_web_page_preview=True
250 | )
251 |
252 | last_event_id = 0
253 | forty_eight_hours_ago = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(hours=48)
254 | try:
255 | event_filter = ChannelAdminLogEventsFilter(
256 | join=True,
257 | leave=True,
258 | invite=True,
259 | ban=True,
260 | unban=True,
261 | kick=True,
262 | unkick=True,
263 | promote=True,
264 | demote=True,
265 | info=True,
266 | settings=True,
267 | pinned=True,
268 | edit=True,
269 | delete=True,
270 | group_call=True,
271 | invites=True,
272 | send=True,
273 | forums=True,
274 | sub_extend=True
275 | )
276 | admin_log = await user.invoke(
277 | GetAdminLog(
278 | channel=await user.resolve_peer(channel_id),
279 | q="",
280 | events_filter=event_filter,
281 | admins=None,
282 | max_id=0,
283 | min_id=0,
284 | limit=100
285 | )
286 | )
287 |
288 | for event in reversed(admin_log.events):
289 | event_date = datetime.datetime.fromtimestamp(event.date, tz=datetime.timezone.utc)
290 | if event_date >= forty_eight_hours_ago:
291 | last_event_id = max(last_event_id, event.id)
292 |
293 | user_id = getattr(event.user_id, 'user_id', None) or event.user_id
294 | try:
295 | event_user = await user.get_users(user_id)
296 | user_name = get_user_name(event_user)
297 | except Exception as e:
298 | user_name = "Anonymous"
299 | print(f"Error fetching admin log user {user_id}: {str(e)}")
300 |
301 | event_type = type(event.action).__name__
302 | event_description = EVENT_TYPE_MAP.get(event_type, event_type)
303 |
304 | event_date = event_date.astimezone(datetime.timezone(datetime.timedelta(hours=6)))
305 |
306 | await send_notification(
307 | event_description=event_description,
308 | user_name=user_name,
309 | user_id=user_id,
310 | channel_id=channel_id,
311 | event_date=event_date
312 | )
313 | except Exception as e:
314 | error_msg = f"**❌ Sorry Bro Last 48 Hours Logs Not Available `{CHANNEL_ID}`: {str(e)}**"
315 | print(error_msg)
316 | await app.send_message(OWNER_ID, error_msg, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
317 |
318 | while True:
319 | try:
320 | event_filter = ChannelAdminLogEventsFilter(
321 | join=True,
322 | leave=True,
323 | invite=True,
324 | ban=True,
325 | unban=True,
326 | kick=True,
327 | unkick=True,
328 | promote=True,
329 | demote=True,
330 | info=True,
331 | settings=True,
332 | pinned=True,
333 | edit=True,
334 | delete=True,
335 | group_call=True,
336 | invites=True,
337 | send=True,
338 | forums=True,
339 | sub_extend=True
340 | )
341 | admin_log = await user.invoke(
342 | GetAdminLog(
343 | channel=await user.resolve_peer(channel_id),
344 | q="",
345 | events_filter=event_filter,
346 | admins=None,
347 | max_id=0,
348 | min_id=last_event_id,
349 | limit=100
350 | )
351 | )
352 |
353 | for event in reversed(admin_log.events):
354 | if event.id > last_event_id:
355 | last_event_id = event.id
356 |
357 | user_id = getattr(event.user_id, 'user_id', None) or event.user_id
358 | try:
359 | event_user = await user.get_users(user_id)
360 | user_name = get_user_name(event_user)
361 | except Exception as e:
362 | user_name = "Anonymous"
363 | print(f"Error fetching admin log user {user_id}: {str(e)}")
364 |
365 | event_type = type(event.action).__name__
366 | event_description = EVENT_TYPE_MAP.get(event_type, event_type)
367 |
368 | event_date = datetime.datetime.fromtimestamp(event.date).astimezone(
369 | datetime.timezone(datetime.timedelta(hours=6))
370 | )
371 |
372 | await send_notification(
373 | event_description=event_description,
374 | user_name=user_name,
375 | user_id=user_id,
376 | channel_id=channel_id,
377 | event_date=event_date
378 | )
379 |
380 | await asyncio.sleep(30)
381 |
382 | except FloodWait as e:
383 | print(f"FloodWait: Sleeping for {e.value} seconds")
384 | await asyncio.sleep(e.value)
385 | except Exception as e:
386 | error_msg = f"**❌ Bot Client Can Not Monitor `{CHANNEL_ID}`: {str(e)}**"
387 | print(error_msg)
388 | await app.send_message(
389 | OWNER_ID,
390 | error_msg,
391 | parse_mode=ParseMode.MARKDOWN,
392 | disable_web_page_preview=True
393 | )
394 | await asyncio.sleep(60)
395 |
396 | app.loop.create_task(main())
--------------------------------------------------------------------------------