├── resources
├── .resource
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
└── 7.jpg
├── Procfile
├── requirements.txt
├── .gitignore
├── Dockerfile
├── config.py
├── app.json
├── README.md
├── LICENSE
└── bot.py
/resources/.resource:
--------------------------------------------------------------------------------
1 | images
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: python3 bot.py
--------------------------------------------------------------------------------
/resources/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/1.jpg
--------------------------------------------------------------------------------
/resources/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/2.jpg
--------------------------------------------------------------------------------
/resources/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/3.jpg
--------------------------------------------------------------------------------
/resources/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/4.jpg
--------------------------------------------------------------------------------
/resources/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/5.jpg
--------------------------------------------------------------------------------
/resources/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/6.jpg
--------------------------------------------------------------------------------
/resources/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJBotVerse/RequestTrackerBot/HEAD/resources/7.jpg
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | async-lru==1.0.2
2 | dnspython==2.1.0
3 | pyaes==1.6.1
4 | pymongo==3.12.1
5 | Pyrogram==1.2.20
6 | PySocks==1.7.1
7 | TgCrypto==1.2.2
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Virtual environment
4 | venv
5 |
6 | # Test/Experiment Folder
7 | testexp
8 |
9 | # Session File
10 | RequestTrackerBot.session
11 |
12 | # Cache File
13 | __pycache__
14 |
15 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:latest
2 |
3 | RUN apt update && apt upgrade -y
4 | RUN apt install git python3-pip -y
5 | RUN git clone https://github.com/AJTimePyro/RequestTrackerBot
6 | WORKDIR /RequestTrackerBot
7 | RUN pip3 install -U -r requirements.txt
8 | CMD python3 bot.py
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 |
4 | """Importing"""
5 | from os import environ
6 |
7 |
8 | class Config(object):
9 | API_ID = int(environ.get("API_ID", 0))
10 | API_HASH = environ.get("API_HASH", "")
11 | BOT_TOKEN = environ.get("BOT_TOKEN", "")
12 | MONGO_STR = environ.get("MONGO_STR", "")
13 |
14 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "RequestTrackerBot",
3 | "description" : "This is RequestTrackerBot and it used for tracking request made by user in a group",
4 | "keywords" : [
5 | "telegram",
6 | "bot",
7 | "heroku",
8 | "python",
9 | "pyrogram",
10 | "app.json",
11 | "app",
12 | "request",
13 | "#request",
14 | "tracker",
15 | "anime",
16 | "movie",
17 | "series",
18 | "webseries"
19 | ],
20 | "repository" : "https://github.com/AJTimePyro/RequestTrackerBot",
21 | "env" : {
22 | "BOT_TOKEN" : {
23 | "description" : "Get From https://t.me/BotFather"
24 | },
25 | "API_ID" : {
26 | "description" : "Get From https://my.telegram.org"
27 | },
28 | "API_HASH" : {
29 | "description" : "Get From https://my.telegram.org"
30 | },
31 | "MONGO_STR" : {
32 | "description" : "Get from Mongo DB Atlas"
33 | }
34 | },
35 | "stack" : "heroku-20",
36 | "buildpacks" : [
37 | {
38 | "url" : "heroku/python"
39 | }
40 | ],
41 | "formation" : {
42 | "worker" : {
43 | "quantity" : 1,
44 | "size" : "free"
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Request Tracker Bot
2 |
3 | This is a Request Tracker Bot repo, It is for those who upload content like movies, anime, etc. It can be used for tracking request of content that your members asked for.
4 |
5 | The owner of this bot is [AJTimePyro](https://t.me/AJTimePyro), His Telegram [Channel](http://t.me/AJPyroVerse) & [Group](http://t.me/AJPyroVerseGroup).
6 | Don't Forget to give a Star.
7 |
8 | ## Some ScreenShots
9 | These ScreenShots might help you to understand this bot well.
10 | 
11 |
12 | 
13 |
14 | 
15 |
16 | 
17 |
18 | 
19 |
20 | 
21 |
22 | 
23 |
24 |
25 | ## Requirement
26 | * API ID & API Hash - Get both from https://my.telegram.org
27 | * Bot Token - Get easily from [Bot Father](https://t.me/BotFather)
28 | * MongoDB Connection String - Get From MongoDB Atlas
29 |
30 |
31 | ## Direct Deploy
32 | Click Below Button to Deploy your Bot.
33 |
34 | [](https://heroku.com/deploy?template=https://github.com/AJTimePyro/RequestBot)
35 |
36 | [](https://railway.app/new/template?template=https%3A%2F%2Fgithub.com%2FAJTimePyro%2FRequestTrackerBot&envs=API_ID%2CAPI_HASH%2CBOT_TOKEN%2CMONGO_STR&API_IDDesc=+Get+both+from+https%3A%2F%2Fmy.telegram.org&API_HASHDesc=+Get+both+from+https%3A%2F%2Fmy.telegram.org&BOT_TOKENDesc=Get+easily+from+https%3A%2F%2Ft.me%2FBotFather&MONGO_STRDesc=Get+From+MongoDB+Atlas)
37 |
38 | ## How to use?
39 | 1. Deploy your Bot on Heroku
40 | 2. Add Bot to your group & make it admin.
41 | 3. Add Bot to your Channel & make admin there as well, also make sure to give permission to Post Messages, Edit Messages & Delete Messages.
42 | 4. Send ID of Group & Channel in this format `/add groupID channelID` to Bot.
43 | 5. Now any user of group can request for content by using #request Keyword.
44 |
45 | ## Support Telegram Group and Channel
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 |
4 | """Importing"""
5 | # Importing External Packages
6 | from pyrogram import (
7 | Client,
8 | filters
9 | )
10 | from pyrogram.types import (
11 | Update,
12 | Message,
13 | CallbackQuery,
14 | InlineKeyboardButton,
15 | InlineKeyboardMarkup
16 | )
17 | from pyrogram.errors.exceptions.bad_request_400 import (
18 | PeerIdInvalid,
19 | UserNotParticipant,
20 | ChannelPrivate,
21 | ChatIdInvalid,
22 | ChannelInvalid
23 | )
24 | from pymongo import MongoClient
25 |
26 | # Importing Credentials & Required Data
27 | try:
28 | from testexp.config import *
29 | except ModuleNotFoundError:
30 | from config import *
31 |
32 | # Importing built-in module
33 | from re import match, search
34 |
35 |
36 | """Connecting to Bot"""
37 | app = Client(
38 | session_name = "RequestTrackerBot",
39 | api_id = Config.API_ID,
40 | api_hash = Config.API_HASH,
41 | bot_token = Config.BOT_TOKEN
42 | )
43 |
44 |
45 | '''Connecting To Database'''
46 | mongo_client = MongoClient(Config.MONGO_STR)
47 | db_bot = mongo_client['RequestTrackerBot']
48 | collection_ID = db_bot['channelGroupID']
49 |
50 |
51 | # Regular Expression for #request
52 | requestRegex = "#[rR][eE][qQ][uU][eE][sS][tT] "
53 |
54 |
55 | """Handlers"""
56 |
57 | # Start & Help Handler
58 | @app.on_message(filters.private & filters.command(["start", "help"]))
59 | async def startHandler(bot:Update, msg:Message):
60 | botInfo = await bot.get_me()
61 | await msg.reply_text(
62 | "Hi, I am Request Tracker Bot🤖.\nIf you hadn't added me in your Group & Channel then ➕add me now.\n\nHow to Use me?\n\t1. Add me to your Group & CHannel.\n\t2. Make me admin in both Channel & Group.\n\t3. Give permission to Post , Edit & Delete Messages.\n\t4. Now send Group ID & Channel ID in this format /add GroupID ChannelID.\nNow Bot is ready to be used.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
63 | parse_mode = "html",
64 | reply_markup = InlineKeyboardMarkup(
65 | [
66 | [
67 | InlineKeyboardButton(
68 | "➕Add me to your Group.",
69 | url = f"https://telegram.me/{botInfo.username}?startgroup=true"
70 | )
71 | ]
72 | ]
73 | )
74 | )
75 | return
76 |
77 | # return group id when bot is added to group
78 | @app.on_message(filters.new_chat_members)
79 | async def chatHandler(bot:Update, msg:Message):
80 | if msg.new_chat_members[0].is_self: # If bot is added
81 | await msg.reply_text(
82 | f"Hey😁, Your Group ID is {msg.chat.id}",
83 | parse_mode = "html"
84 | )
85 | return
86 |
87 | # return channel id when message/post from channel is forwarded
88 | @app.on_message(filters.forwarded & filters.private)
89 | async def forwardedHandler(bot:Update, msg:Message):
90 | forwardInfo = msg.forward_from_chat
91 | if forwardInfo.type == "channel": # If message forwarded from channel
92 | await msg.reply_text(
93 | f"Hey😁, Your Channel ID is {forwardInfo.id}\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
94 | parse_mode = "html"
95 | )
96 | return
97 |
98 | # /add handler to add group id & channel id with database
99 | @app.on_message(filters.private & filters.command("add"))
100 | async def groupChannelIDHandler(bot:Update, msg:Message):
101 | message = msg.text.split(" ")
102 | if len(message) == 3: # If command is valid
103 | _, groupID, channelID = message
104 | try:
105 | int(groupID)
106 | int(channelID)
107 | except ValueError: # If Ids are not integer type
108 | await msg.reply_text(
109 | "Group ID & Channel ID should be integer type😒.",
110 | parse_mode = "html"
111 | )
112 | else: # If Ids are integer type
113 | documents = collection_ID.find()
114 | for document in documents:
115 | try:
116 | document[groupID]
117 | except KeyError:
118 | pass
119 | else: # If group id found in database
120 | await msg.reply_text(
121 | "Your Group ID already Added.",
122 | parse_mode = "html"
123 | )
124 | break
125 | for record in document:
126 | if record == "_id":
127 | continue
128 | else:
129 | if document[record][0] == channelID: #If channel id found in database
130 | await msg.reply_text(
131 | "Your Channel ID already Added.",
132 | parse_mode = "html"
133 | )
134 | break
135 | else: # If group id & channel not found in db
136 | try:
137 | botSelfGroup = await bot.get_chat_member(int(groupID), 'me')
138 | except (PeerIdInvalid, ValueError): # If given group id is invalid
139 | await msg.reply_text(
140 | "😒Group ID is wrong.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
141 | parse_mode = "html"
142 | )
143 | except UserNotParticipant: # If bot is not in group
144 | await msg.reply_text(
145 | "😁Add me in group and make me admin, then use /add.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
146 | parse_mode = "html"
147 | )
148 | else:
149 | if botSelfGroup.status != "administrator": # If bot is not admin in group
150 | await msg.reply_text(
151 | "🥲Make me admin in Group, Then add use /add.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
152 | parse_mode = "html"
153 | )
154 | else: # If bot is admin in group
155 | try:
156 | botSelfChannel = await bot.get_chat_member(int(channelID), 'me')
157 | except (UserNotParticipant, ChannelPrivate): # If bot not in channel
158 | await msg.reply_text(
159 | "😁Add me in Channel and make me admin, then use /add.",
160 | parse_mode = "html"
161 | )
162 | except (ChatIdInvalid, ChannelInvalid): # If given channel id is invalid
163 | await msg.reply_text(
164 | "😒Channel ID is wrong.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
165 | parse_mode = "html"
166 | )
167 | else:
168 | if not (botSelfChannel.can_post_messages and botSelfChannel.can_edit_messages and botSelfChannel.can_delete_messages): # If bot has not enough permissions
169 | await msg.reply_text(
170 | "🥲Make sure to give Permissions like Post Messages, Edit Messages & Delete Messages.",
171 | parse_mode = "html"
172 | )
173 | else: # Adding Group ID, Channel ID & User ID in group
174 | collection_ID.insert_one(
175 | {
176 | groupID : [channelID, msg.chat.id]
177 | }
178 | )
179 | await msg.reply_text(
180 | "Your Group and Channel has now been added SuccessFully🥳.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
181 | parse_mode = "html"
182 | )
183 | else: # If command is invalid
184 | await msg.reply_text(
185 | "Invalid Format😒\nSend Group ID & Channel ID in this format /add GroupID ChannelID.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
186 | parse_mode = "html"
187 | )
188 | return
189 |
190 | # /remove handler to remove group id & channel id from database
191 | @app.on_message(filters.private & filters.command("remove"))
192 | async def channelgroupRemover(bot:Update, msg:Message):
193 | message = msg.text.split(" ")
194 | if len(message) == 2: # If command is valid
195 | _, groupID = message
196 | try:
197 | int(groupID)
198 | except ValueError: # If group id not integer type
199 | await msg.reply_text(
200 | "Group ID should be integer type😒.",
201 | parse_mode = "html"
202 | )
203 | else: # If group id is integer type
204 | documents = collection_ID.find()
205 | for document in documents:
206 | try:
207 | document[groupID]
208 | except KeyError:
209 | continue
210 | else: # If group id found in database
211 | if document[groupID][1] == msg.chat.id: # If group id, channel id is removing by one who added
212 | collection_ID.delete_one(document)
213 | await msg.reply_text(
214 | "Your Channel ID & Group ID has now been Deleted😢 from our Database.\nYou can add them again by using /add GroupID ChannelID.",
215 | parse_mode = "html"
216 | )
217 | else: # If group id, channel id is not removing by one who added
218 | await msg.reply_text(
219 | "😒You are not the one who added this Channel ID & Group ID.",
220 | parse_mode = "html"
221 | )
222 | break
223 | else: # If group id not found in database
224 | await msg.reply_text(
225 | "Given Group ID is not found in our Database🤔.\n\n😊Join @AJPyroVerse & @AJPyroVerseGroup for getting more awesome 🤖bots like this.",
226 | parse_mode = "html"
227 | )
228 | else: # If command is invalid
229 | await msg.reply_text(
230 | "Invalid Command😒\nUse /remove GroupID.",
231 | parse_mode = "html"
232 | )
233 | return
234 |
235 | # #request handler
236 | @app.on_message(filters.group & filters.regex(requestRegex + "(.*)"))
237 | async def requestHandler(bot:Update, msg:Message):
238 | groupID = str(msg.chat.id)
239 |
240 | documents = collection_ID.find()
241 | for document in documents:
242 | try:
243 | document[groupID]
244 | except KeyError:
245 | continue
246 | else: # If group id found in database
247 | channelID = document[groupID][0]
248 | fromUser = msg.from_user
249 | mentionUser = f"{fromUser.first_name}"
250 | requestText = f"Request by {mentionUser}\n\n{msg.text}"
251 | originalMSG = msg.text
252 | findRegexStr = match(requestRegex, originalMSG)
253 | requestString = findRegexStr.group()
254 | contentRequested = originalMSG.split(requestString)[1]
255 |
256 | try:
257 | groupIDPro = groupID.removeprefix(str(-100))
258 | channelIDPro = channelID.removeprefix(str(-100))
259 | except AttributeError:
260 | groupIDPro = groupID[4:]
261 | channelIDPro = channelID[4:]
262 |
263 | # Sending request in channel
264 | requestMSG = await bot.send_message(
265 | int(channelID),
266 | requestText,
267 | reply_markup = InlineKeyboardMarkup(
268 | [
269 | [
270 | InlineKeyboardButton(
271 | "Requested Message",
272 | url = f"https://t.me/c/{groupIDPro}/{msg.message_id}"
273 | )
274 | ],
275 | [
276 | InlineKeyboardButton(
277 | "🚫Reject",
278 | "reject"
279 | ),
280 | InlineKeyboardButton(
281 | "Done✅",
282 | "done"
283 | )
284 | ],
285 | [
286 | InlineKeyboardButton(
287 | "⚠️Unavailable⚠️",
288 | "unavailable"
289 | )
290 | ]
291 | ]
292 | )
293 | )
294 |
295 | replyText = f"👋 Hello {mentionUser} !!\n\n📍 Your Request for {contentRequested} has been submitted to the admins.\n\n🚀 Your Request Will Be Uploaded soon.\n📌 Please Note that Admins might be busy. So, this may take more time.\n\n👇 See Your Request Status Here 👇"
296 |
297 | # Sending message for user in group
298 | await msg.reply_text(
299 | replyText,
300 | parse_mode = "html",
301 | reply_to_message_id = msg.message_id,
302 | reply_markup = InlineKeyboardMarkup(
303 | [
304 | [
305 | InlineKeyboardButton(
306 | "⏳Request Status⏳",
307 | url = f"https://t.me/c/{channelIDPro}/{requestMSG.message_id}"
308 | )
309 | ]
310 | ]
311 | )
312 | )
313 | break
314 | return
315 |
316 | # callback buttons handler
317 | @app.on_callback_query()
318 | async def callBackButton(bot:Update, callback_query:CallbackQuery):
319 | channelID = str(callback_query.message.chat.id)
320 |
321 | documents = collection_ID.find()
322 | for document in documents:
323 | for key in document:
324 | if key == "_id":
325 | continue
326 | else:
327 | if document[key][0] != channelID:
328 | continue
329 | else: # If channel id found in database
330 | groupID = key
331 |
332 | data = callback_query.data # Callback Data
333 | if data == "rejected":
334 | return await callback_query.answer(
335 | "This request is rejected💔...\nAsk admins in group for more info💔",
336 | show_alert = True
337 | )
338 | elif data == "completed":
339 | return await callback_query.answer(
340 | "This request Is Completed🥳...\nCheckout in Channel😊",
341 | show_alert = True
342 | )
343 | user = await bot.get_chat_member(int(channelID), callback_query.from_user.id)
344 | if user.status not in ("administrator", "creator"): # If accepting, rejecting request tried to be done by neither admin nor owner
345 | await callback_query.answer(
346 | "Who the hell are you?\nYour are not Admin😒.",
347 | show_alert = True
348 | )
349 | else: # If accepting, rejecting request tried to be done by either admin or owner
350 | if data == "reject":
351 | result = "REJECTED"
352 | groupResult = "has been Rejected💔."
353 | button = InlineKeyboardButton("Request Rejected🚫", "rejected")
354 | elif data == "done":
355 | result = "COMPLETED"
356 | groupResult = "is Completed🥳."
357 | button = InlineKeyboardButton("Request Completed✅", "completed")
358 | elif data == "unavailable":
359 | result = "UNAVAILABLE"
360 | groupResult = "has been rejected💔 due to Unavailablity🥲."
361 | button = InlineKeyboardButton("Request Rejected🚫", "rejected")
362 |
363 | msg = callback_query.message
364 | userid = 12345678
365 | for m in msg.entities:
366 | if m.type == "text_mention":
367 | userid = m.user.id
368 | originalMsg = msg.text
369 | findRegexStr = search(requestRegex, originalMsg)
370 | requestString = findRegexStr.group()
371 | contentRequested = originalMsg.split(requestString)[1]
372 | requestedBy = originalMsg.removeprefix("Request by ").split('\n\n')[0]
373 | mentionUser = f"{requestedBy}"
374 | originalMsgMod = originalMsg.replace(requestedBy, mentionUser)
375 | originalMsgMod = f"{originalMsgMod}"
376 |
377 | newMsg = f"{result}\n\n{originalMsgMod}"
378 |
379 | # Editing reqeust message in channel
380 | await callback_query.edit_message_text(
381 | newMsg,
382 | parse_mode = "html",
383 | reply_markup = InlineKeyboardMarkup(
384 | [
385 | [
386 | button
387 | ]
388 | ]
389 | )
390 | )
391 |
392 | # Result of request sent to group
393 | replyText = f"Dear {mentionUser}🧑\nYour request for {contentRequested} {groupResult}\n👍Thanks for requesting!"
394 | await bot.send_message(
395 | int(groupID),
396 | replyText,
397 | parse_mode = "html"
398 | )
399 | return
400 | return
401 |
402 |
403 | """Bot is Started"""
404 | print("Bot has been Started!!!")
405 | app.run()
406 |
407 |
--------------------------------------------------------------------------------