├── Procfile ├── requirements.txt ├── start.sh ├── heroku.yml ├── config.py ├── Dockerfile ├── README.md └── scr.py /Procfile: -------------------------------------------------------------------------------- 1 | worker: ./start.sh 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | aiofiles 3 | asyncio 4 | tgcrypto 5 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run the scr.py script 4 | python scr.py 5 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile 4 | 5 | run: 6 | web: ./start.sh 7 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # Pyrogram setup 2 | API_ID = "123456" # Replace this API ID with your actual API ID 3 | API_HASH = "XXXXXXXXXXX" # Replace this API HASH with your actual API HASH 4 | SESSION_STRING = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # Replace this SESSION STRING with your actual SESSION_STRING 5 | BOT_TOKEN = "12345678:XXXXXXXXXXXXXX" # Replace this BOT_TOKEN 6 | 7 | # Admin IDs 8 | ADMIN_IDS = [12345678, 12345678] 9 | 10 | # Limits 11 | DEFAULT_LIMIT = 10000 # Card Scrapping Limit For Everyone 12 | ADMIN_LIMIT = 50000 # Card Scrapping Limit For Admin -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official Python 3.10 image from the Docker Hub 2 | FROM python:3.10-slim 3 | 4 | # Set the working directory in the container 5 | WORKDIR /app 6 | 7 | # Copy the requirements.txt file into the container at /app 8 | COPY requirements.txt /app/ 9 | 10 | # Install any dependencies specified in requirements.txt 11 | RUN pip install --no-cache-dir -r requirements.txt 12 | 13 | # Copy the rest of the working directory contents into the container at /app 14 | COPY . /app 15 | 16 | # Make start.sh executable 17 | RUN chmod +x start.sh 18 | 19 | # Run start.sh when the container launches 20 | CMD ["./start.sh"] 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
12 | CC Scraper: An advanced Telegram bot script to scrape credit cards from specified Telegram groups and channels. 13 |
14 |{source_name} 🌐\n"
133 | f"Amount: {len(unique_messages)} 📝\n"
134 | f"Duplicates Removed: {duplicates_removed} 🗑️\n"
135 | )
136 | # Add BIN filter to caption if provided
137 | if bin_filter:
138 | caption += f"📝 BIN Filter: {bin_filter}\n"
139 | # Add Bank filter to caption if provided
140 | if bank_filter:
141 | caption += f"📝 Bank Filter: {bank_filter}\n"
142 | caption += (
143 | f"━━━━━━━━━━━━━━━━\n"
144 | f"✅ Card-Scrapped By: {user_link}\n"
145 | )
146 | await message.delete()
147 | await client.send_document(message.chat.id, file_name, caption=caption)
148 | os.remove(file_name)
149 | logger.info(f"Results sent successfully for {source_name}")
150 | else:
151 | await message.edit_text("Sorry Bro ❌ No Credit Card Found")
152 | logger.info("No credit cards found")
153 |
154 | async def get_user_link(message):
155 | if message.from_user is None:
156 | return 'Smart Tool'
157 | else:
158 | user_first_name = message.from_user.first_name
159 | user_last_name = message.from_user.last_name or ""
160 | user_full_name = f"{user_first_name} {user_last_name}".strip()
161 | return f'{user_full_name}'
162 |
163 | async def join_private_chat(client, invite_link):
164 | try:
165 | await client.join_chat(invite_link)
166 | logger.info(f"Joined chat via invite link: {invite_link}")
167 | return True
168 | except UserAlreadyParticipant:
169 | logger.info(f"Already a participant in the chat: {invite_link}")
170 | return True
171 | except InviteRequestSent:
172 | logger.info(f"Join request sent to the chat: {invite_link}")
173 | return False
174 | except (InviteHashExpired, InviteHashInvalid) as e:
175 | logger.error(f"Failed to join chat {invite_link}: {e}")
176 | return False
177 |
178 | async def send_join_request(client, invite_link, message):
179 | try:
180 | await client.join_chat(invite_link)
181 | logger.info(f"Sent join request to chat: {invite_link}")
182 | return True
183 | except PeerIdInvalid as e:
184 | logger.error(f"Failed to send join request to chat {invite_link}: {e}")
185 | return False
186 | except InviteRequestSent:
187 | logger.info(f"Join request sent to the chat: {invite_link}")
188 | await message.edit_text("Hey Bro I Have Sent Join Request✅")
189 | return False
190 |
191 | def setup_scr_handler(app):
192 | @app.on_message(filters.command(["scr", "ccscr", "scrcc"], prefixes=["/", ".", ",", "!"]) & (filters.group | filters.private))
193 | async def scr_cmd(client, message):
194 | args = message.text.split()[1:]
195 | user_id = message.from_user.id if message.from_user else None
196 |
197 | if len(args) < 2:
198 | await client.send_message(message.chat.id, "⚠️ Provide channel username and amount to scrape ❌")
199 | logger.warning("Invalid command: Missing arguments")
200 | return
201 |
202 | # Extract channel identifier (username, invite link, or chat ID)
203 | channel_identifier = args[0]
204 | chat = None
205 | channel_name = ""
206 | channel_username = ""
207 |
208 | # Handle private channel chat ID (numeric)
209 | if channel_identifier.lstrip("-").isdigit():
210 | # Treat it as a chat ID
211 | chat_id = int(channel_identifier)
212 | try:
213 | # Fetch the chat details
214 | chat = await user.get_chat(chat_id)
215 | channel_name = chat.title
216 | logger.info(f"Scraping from private channel: {channel_name} (ID: {chat_id})")
217 | except Exception as e:
218 | await client.send_message(message.chat.id, "Hey Bro! 🥲 Invalid chat ID ❌")
219 | logger.error(f"Failed to fetch private channel: {e}")
220 | return
221 | else:
222 | # Handle public channels or private invite links
223 | if channel_identifier.startswith("https://t.me/+"):
224 | # Private invite link
225 | invite_link = channel_identifier
226 | temporary_msg = await client.send_message(message.chat.id, "Checking Username...")
227 | joined = await join_private_chat(user, invite_link)
228 | if not joined:
229 | request_sent = await send_join_request(user, invite_link, temporary_msg)
230 | if not request_sent:
231 | return
232 | else:
233 | await temporary_msg.delete()
234 | chat = await user.get_chat(invite_link)
235 | channel_name = chat.title
236 | logger.info(f"Joined private channel via link: {channel_name}")
237 | elif channel_identifier.startswith("https://t.me/"):
238 | # Remove "https://t.me/" for regular links
239 | channel_username = channel_identifier[13:]
240 | elif channel_identifier.startswith("t.me/"):
241 | # Remove "t.me/" for short links
242 | channel_username = channel_identifier[5:]
243 | else:
244 | # Assume it's already a username
245 | channel_username = channel_identifier
246 |
247 | if not chat:
248 | try:
249 | # Fetch the chat details
250 | chat = await user.get_chat(channel_username)
251 | channel_name = chat.title
252 | logger.info(f"Scraping from public channel: {channel_name} (Username: {channel_username})")
253 | except Exception as e:
254 | await client.send_message(message.chat.id, "Hey Bro! 🥲 Incorrect username or chat ID ❌")
255 | logger.error(f"Failed to fetch public channel: {e}")
256 | return
257 |
258 | # Extract limit (second argument)
259 | try:
260 | limit = int(args[1])
261 | logger.info(f"Scraping limit set to: {limit}")
262 | except ValueError:
263 | await client.send_message(message.chat.id, "⚠️ Invalid limit value. Please provide a valid number ❌")
264 | logger.warning("Invalid limit value provided")
265 | return
266 |
267 | # Extract optional arguments (starting number or bank name)
268 | start_number = None
269 | bank_name = None
270 | bin_filter = None
271 | if len(args) > 2:
272 | # Check if the third argument is a starting number (digits only)
273 | if args[2].isdigit():
274 | start_number = args[2]
275 | bin_filter = args[2][:6] # Extract first 6 digits as BIN filter
276 | logger.info(f"BIN filter applied: {bin_filter}")
277 | else:
278 | # Otherwise, treat it as a bank name
279 | bank_name = " ".join(args[2:])
280 | logger.info(f"Bank filter applied: {bank_name}")
281 |
282 | # Enforce maximum limit based on user role
283 | max_lim = ADMIN_LIMIT if user_id in ADMIN_IDS else DEFAULT_LIMIT
284 | if limit > max_lim:
285 | await client.send_message(message.chat.id, f"Sorry Bro! Amount over Max limit is {max_lim} ❌")
286 | logger.warning(f"Limit exceeded: {limit} > {max_lim}")
287 | return
288 |
289 | # Send a temporary message to check the username
290 | temporary_msg = await client.send_message(message.chat.id, "Checking The Username...")
291 | await asyncio.sleep(1.5)
292 |
293 | # Start scraping
294 | await temporary_msg.edit_text("Scraping In Progress")
295 | scrapped_results = await scrape_messages(user, chat.id, limit, start_number=start_number, bank_name=bank_name)
296 | unique_messages, duplicates_removed = remove_duplicates(scrapped_results)
297 |
298 | if not unique_messages:
299 | await temporary_msg.edit_text("Sorry Bro ❌ No Credit Card Found")
300 | else:
301 | await send_results(client, temporary_msg, unique_messages, duplicates_removed, channel_name, bin_filter=bin_filter, bank_filter=bank_name)
302 |
303 | @app.on_message(filters.command(["mc", "multiscr", "mscr"], prefixes=["/", ".", ",", "!"]) & (filters.group | filters.private))
304 | async def mc_cmd(client, message):
305 | args = message.text.split()[1:]
306 | if len(args) < 2:
307 | await client.send_message(message.chat.id, "⚠️ Provide at least one channel username")
308 | logger.warning("Invalid command: Missing arguments")
309 | return
310 |
311 | channel_identifiers = args[:-1]
312 | limit = int(args[-1])
313 | user_id = message.from_user.id if message.from_user else None
314 |
315 | max_lim = ADMIN_LIMIT if user_id in ADMIN_IDS else DEFAULT_LIMIT
316 | if limit > max_lim:
317 | await client.send_message(message.chat.id, f"Sorry Bro! Amount over Max limit is {max_lim} ❌")
318 | logger.warning(f"Limit exceeded: {limit} > {max_lim}")
319 | return
320 |
321 | temporary_msg = await client.send_message(message.chat.id, "Scraping In Progress")
322 | all_messages = []
323 | tasks = []
324 |
325 | for channel_identifier in channel_identifiers:
326 | parsed_url = urlparse(channel_identifier)
327 | channel_username = parsed_url.path.lstrip('/') if not parsed_url.scheme else channel_identifier
328 |
329 | tasks.append(scrape_messages_task(user, channel_username, limit, client, message))
330 |
331 | results = await asyncio.gather(*tasks)
332 | for result in results:
333 | all_messages.extend(result)
334 |
335 | unique_messages, duplicates_removed = remove_duplicates(all_messages)
336 | unique_messages = unique_messages[:limit]
337 |
338 | if not unique_messages:
339 | await temporary_msg.edit_text("Sorry Bro ❌ No Credit Card Found")
340 | else:
341 | await send_results(client, temporary_msg, unique_messages, duplicates_removed, "Multiple Chats")
342 |
343 | async def scrape_messages_task(client, channel_username, limit, bot_client, message):
344 | try:
345 | chat = None
346 | if channel_username.startswith("https://t.me/+"):
347 | invite_link = channel_username
348 | temporary_msg = await bot_client.send_message(message.chat.id, "Checking Username...")
349 | joined = await join_private_chat(client, invite_link)
350 | if not joined:
351 | request_sent = await send_join_request(client, invite_link, temporary_msg)
352 | if not request_sent:
353 | return []
354 | else:
355 | await temporary_msg.delete()
356 | chat = await client.get_chat(invite_link)
357 | else:
358 | chat = await client.get_chat(channel_username)
359 |
360 | return await scrape_messages(client, chat.id, limit)
361 | except Exception as e:
362 | await bot_client.send_message(message.chat.id, f"Hey Bro! 🥲 Incorrect username for {channel_username} ❌")
363 | logger.error(f"Failed to scrape from {channel_username}: {e}")
364 | return []
365 |
366 | @app.on_message(filters.command("start", prefixes=["/", ".", ",", "!"]) & (filters.group | filters.private))
367 | async def start(client, message):
368 | buttons = [
369 | [InlineKeyboardButton("Update Channel", url="https://t.me/Modvip_rm"), InlineKeyboardButton("My Dev👨💻", user_id=7303810912)]
370 | ]
371 | await client.send_message(message.chat.id, START_MESSAGE, parse_mode=ParseMode.HTML, disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(buttons))
372 |
373 | if __name__ == "__main__":
374 | setup_scr_handler(app)
375 | user.start()
376 | app.run()
377 |
--------------------------------------------------------------------------------