├── Procfile ├── requirements.txt ├── config.py ├── app.py ├── Dockerfile ├── app.json ├── templates └── welcome.html ├── README.md ├── main.py └── LICENSE /Procfile: -------------------------------------------------------------------------------- 1 | devgagan: python main.py 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | telethon 2 | requests 3 | flask 4 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # copyright github.com/devgaganin 2 | 3 | from os import getenv 4 | 5 | API_ID = int(getenv("API_ID", "")) 6 | API_HASH = getenv("API_HASH", "") 7 | BOT_TOKEN = getenv("BOT_TOKEN", "") 8 | COOKIES = getenv("AUTH_CODE", "") 9 | OWNER_ID = getenv("OWNER_ID", "1213121") # if want to make accessible in channel put channel id in owner id field 10 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask, render_template 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route("/") 7 | def welcome(): 8 | # Render the welcome page with animated "Team SPY" text 9 | return render_template("welcome.html") 10 | 11 | if __name__ == "__main__": 12 | # Default to port 5000 if PORT is not set in the environment 13 | port = int(os.environ.get("PORT", 5000)) 14 | app.run(host="0.0.0.0", port=port) 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10.4-slim-buster 2 | RUN apt update && apt upgrade -y 3 | RUN apt-get install git curl python3-pip ffmpeg -y 4 | RUN apt-get -y install git 5 | RUN apt-get install -y wget python3-pip curl bash neofetch ffmpeg software-properties-common 6 | COPY requirements.txt . 7 | 8 | RUN pip3 install wheel 9 | RUN pip3 install --no-cache-dir -U -r requirements.txt 10 | WORKDIR /app 11 | COPY . . 12 | EXPOSE 5000 13 | 14 | CMD flask run -h 0.0.0.0 -p 5000 & python3 main.py 15 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Oliveboard Mock Bot", 3 | "description": "A Telegram bot to fetch and display test data.", 4 | "repository": "https://github.com/devgaganin/Mocks-Saver-Bot/", 5 | "keywords": ["python", "telegram", "bot", "automation"], 6 | "buildpacks": [ 7 | { 8 | "url": "heroku/python" 9 | } 10 | ], 11 | "env": { 12 | "API_ID": { 13 | "description": "Your Telegram API ID", 14 | "required": true 15 | }, 16 | "API_HASH": { 17 | "description": "Your Telegram API hash", 18 | "required": true 19 | }, 20 | "BOT_TOKEN": { 21 | "description": "Your Telegram bot token", 22 | "required": true 23 | }, 24 | "COOKIES": { 25 | "description": "COOKIES for authorised use", 26 | "required": true 27 | }, 28 | "OWNER_ID": { 29 | "description": "Put owner id / or channel id if want access to channel (with -100)", 30 | "required": true 31 | } 32 | }, 33 | "stack": "heroku-22" 34 | } 35 | -------------------------------------------------------------------------------- /templates/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Team SPY - Bot is Live 7 | 123 | 124 | 125 | 126 |
127 |
Team SPY
128 |
⚡ Bot is Live ⚡
129 | 130 |
131 | Join Us 132 | GitHub 133 |
134 |
135 | 136 | 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Oliveboard Mocks Bot 2 | **A powerful Telegram bot repository to connect with Oliveboard Web Interface via COOKIES to fetch & generate visually appealing HTML test files, using your authorised credentials** 3 | 4 | --- 5 | 6 | ## Features 7 | - Fetch test data using COOKIES. 8 | - Support for multi-language questions (English and Hindi). 9 | - Generates enhanced HTML files with styled question and answer content. 10 | - Fixes image URLs dynamically for compatibility. 11 | - Minimal dependencies and efficient performance. 12 | 13 | --- 14 | ## Requirements 15 | - Python 3.8+ 16 | - [Telethon](https://github.com/LonamiWebs/Telethon) library for interacting with Telegram. 17 | - Internet access to fetch data and communicate with Telegram servers. 18 | 19 | --- 20 | 21 | ### 1. Installing on VPS or Windows 22 | To deploy the bot on your VPS: 23 | 24 | 1. **Clone the Repository**: 25 | ```bash 26 | git clone -b oliveboard https://github.com/devgaganin/Mocks-Saver-Bot.git olive 27 | cd olive 28 | ``` 29 | 30 | 2. **Install Dependencies**: 31 | Ensure Python 3.8+ and `pip` are installed, then run: 32 | ```bash 33 | pip install -r requirements.txt 34 | ``` 35 | 36 | 3. **Set Up Environment Variables**: 37 | Create a `.env` file in the root directory or export the following variables: 38 | ```bash 39 | API_ID=your_api_id 40 | API_HASH=your_api_hash 41 | BOT_TOKEN=your_bot_token 42 | COOKIES=you_cookies 43 | ``` 44 | 45 | 4. **Run the Bot**: 46 | Start the bot using: 47 | ```bash 48 | python main.py 49 | ``` 50 | 51 | --- 52 | 53 | ### 2. Deploying on Heroku 54 | To deploy the bot on **Heroku**, click the button below and fill in the required environment variables: 55 | 56 | [![Deploy on Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) 57 | 58 | #### Steps: 59 | 1. Click the **Deploy on Heroku** button above. 60 | 2. Enter the following required environment variables during deployment: 61 | - `API_ID` 62 | - `API_HASH` 63 | - `BOT_TOKEN` 64 | - `COOKIES` 65 | 3. Deploy the app and monitor the logs to ensure the bot is running successfully. 66 | --- 67 | 68 | ## Commands 69 | 70 | | Command | Description | 71 | |-----------------------------------|---------------------------------------------------------------------------| 72 | | `/start` | Display a welcome message with usage instructions. | 73 | | `/fetch ` | Fetch test data from the OliveBoard for the provided test ID and Exam. | 74 | 75 | --- 76 | 77 | ## Usage 78 | 79 | 1. Start the bot: 80 | - Type `/start` in your Telegram chat with the bot. 81 | - The bot will respond with a welcome message and basic instructions. 82 | 83 | 2. Fetch a test: 84 | - Use `/fetch `. Replace ` and ` with the specific test ID/name provided. 85 | - The bot will validate the test ID and retrieve the corresponding test data. 86 | 87 | --- 88 | 89 | ## Example Workflow 90 | 1. `/start` 91 | Bot: "Welcome to the Testbook Bot! Use the command `/fetch ` to fetch test data." 92 | 93 | 2. `/fetch ntpc1 1` 94 | Bot: "Uploading test papers ... auto submiitting ... uploading solution" 95 | --- 96 | 97 | ## License 98 | This project is licensed under the **GNU Affero General Public License v3** (APGL-3.x). 99 | **Strict Provisions:** 100 | - **No Commercial Use**: This software and its derivatives must not be used for commercial purposes or sold. 101 | - **No part of this code, including edits, is allowed to be used for commercial or sale purposes.** 102 | 103 | **© [GitHub.com/devgaganin](https://github.com/devgaganin)** 104 | Unauthorized commercial use is strictly prohibited. 105 | 106 | --- 107 | 108 | ## Disclaimer 109 | The bot is intended solely for personal and educational purposes. 110 | Use at own responsibilty and copying, modifying part of this code/reuse is not allowed. 111 | The developer is not responsible for any misuse or breach of third-party API terms. 112 | 113 | ## For Oliveboard Representatives: 114 | Hey respected representatives, 115 | If this project is engaging in any activities that you consider misleading, inappropriate, or in violation of your policies, please feel free to reach out to me immediately. I am committed to resolving any issues and will take necessary actions, including shutting down the project if required. 116 | 117 | Contact Information: 118 | [Email](mailto:contact@devgagan.in) 119 | 120 | Thank you for your understanding and cooperation. 121 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Copyright github.com/devgaganin 2 | 3 | import os 4 | import requests 5 | from telethon import TelegramClient, events 6 | from telethon.tl.types import InputFile 7 | from config import API_ID, API_HASH, BOT_TOKEN, COOKIES, OWNER_ID 8 | import re 9 | from bs4 import BeautifulSoup 10 | 11 | # Initialize the Telethon client 12 | bot = TelegramClient("olive_bot", API_ID, API_HASH).start(bot_token=BOT_TOKEN) 13 | 14 | @bot.on(events.NewMessage(pattern="/start")) 15 | async def start(event): 16 | """Handle /start command""" 17 | await event.reply( 18 | "**Welcome to the Mock Extractor Bot!**\n\n" 19 | "Send `/fetch exam testid` for oliveboard\n\n" 20 | "**__Example: `/fetch ntpc1 1`__**\n\n" 21 | "__**Powered by Team SPY**__" 22 | ) 23 | 24 | # --- OLIVEBOARD --- 25 | 26 | # Headers for HTTP requests 27 | HEADERS = { 28 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 29 | "Accept-Encoding": "gzip, deflate, br, zstd", 30 | "Accept-Language": "en-US,en;q=0.9", 31 | "Connection": "keep-alive", 32 | "Cookie": COOKIES, 33 | "Host": "u1.oliveboard.in", 34 | "Sec-Fetch-Dest": "document", 35 | "Sec-Fetch-Mode": "navigate", 36 | "Sec-Fetch-Site": "none", 37 | "Sec-Fetch-User": "?1", 38 | "Upgrade-Insecure-Requests": "1", 39 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", 40 | "sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132", "Google Chrome";v="132"', 41 | "sec-ch-ua-mobile": "?0", 42 | "sec-ch-ua-platform": '"Windows"', 43 | } 44 | 45 | 46 | # Base URIs for different exam types 47 | BASE_URIS = { 48 | "cgl1": "https://u1.oliveboard.in/exams/tests/?c=ssc2019&testid={test_id}", 49 | "chsl": "https://u1.oliveboard.in/exams/tests/?c=chsl&testid={test_id}", 50 | "chsl2": "https://u1.oliveboard.in/exams/tests/?c=chsl2&testid={test_id}", 51 | "sscmts": "https://u1.oliveboard.in/exams/tests/?c=sscmts&testid={test_id}", 52 | "ntpc1": "https://u1.oliveboard.in/exams/tests/?c=ntpc1&os=1&testid={test_id}", 53 | "ntpc2": "https://u1.oliveboard.in/exams/tests/?c=ntpc2&os=1&testid={test_id}", 54 | "rrbalp1": "https://u1.oliveboard.in/exams/tests/?c=rrbalp1&os=1&testid={test_id}", 55 | "rrbalp2": "https://u1.oliveboard.in/exams/tests/?c=rrbalp2&os=1&testid={test_id}", 56 | "rrbgrpd": "https://u1.oliveboard.in/exams/tests/?c=rrbgrpd&os=1&testid={test_id}", 57 | 58 | } 59 | 60 | @bot.on(events.NewMessage(pattern=r"/fetch (\w+) (\d+)")) 61 | async def fetch_exam(event): 62 | """Fetches test details based on the exam type and test ID.""" 63 | if event.sender_id != OWNER_ID: 64 | await event.reply("Not allowed") 65 | return 66 | exam = event.pattern_match.group(1).lower() 67 | test_id = event.pattern_match.group(2) 68 | 69 | if exam not in BASE_URIS: 70 | await event.respond("Invalid exam type! Supported types are: " + ", ".join(BASE_URIS.keys())) 71 | return 72 | 73 | # Construct the URL 74 | url = BASE_URIS[exam].format(test_id=test_id) 75 | 76 | try: 77 | # Fetch the HTML content 78 | response = requests.get(url, headers=HEADERS) 79 | response.raise_for_status() 80 | 81 | html_content = response.text 82 | modified_html = modify_html(html_content, url) 83 | 84 | # Save the modified HTML to a file 85 | file_name = f"exam_{exam}_{test_id}.html" 86 | with open(file_name, "w", encoding="utf-8") as file: 87 | file.write(modified_html) 88 | 89 | prog = await bot.send_message(event.chat_id, "Extracting Questions") 90 | 91 | # Send the file back to the user 92 | await prog.edit("Uploading Test Papers... ") 93 | await event.respond(f"**📕 Exam Name: {exam}**\n**🆔 Test ID: {test_id}**\n**🥹 Type: Question**\n\n__**Powered by Team SPY**__", file=file_name) 94 | await prog.edit("Auto Submitting the test") 95 | submit_test(url) 96 | await prog.edit("Test Submitted Sucessfully... ") 97 | t = url.replace("https://u1.oliveboard.in/exams/tests/", "https://u1.oliveboard.in/exams/solution/index3.php") 98 | print(t) 99 | k = fetch_solution(t) 100 | await prog.edit("Trying to fetch the solution... ") 101 | mod_html = mody_html(k, url) 102 | 103 | file_sol_name = f"solution_exam_{exam}_{test_id}.html" 104 | with open(file_sol_name, "w", encoding="utf-8") as file: 105 | file.write(mod_html) 106 | 107 | await prog.edit("Uploading Solution... ") 108 | await event.respond(f"**📕 Exam Name: {exam}**\n**🆔 Test ID: {test_id}**\n**🥹 Type: Solution**\n\n__**Powered by Team SPY**__", file=file_sol_name) 109 | await prog.delete() 110 | 111 | os.remove(file_name) 112 | if file_sol_name: 113 | os.remove(file_sol_name) 114 | 115 | except requests.exceptions.RequestException as e: 116 | await event.respond(f"Failed to fetch the test details: {e}") 117 | 118 | def submit_test(url, test_id, exam): 119 | surl = "https://u1.oliveboard.in/exams/tests/p/submittestfull.cgi" 120 | headers = { 121 | "Accept": "*/*", 122 | "Accept-Encoding": "gzip, deflate, br, zstd", 123 | "Accept-Language": "en-US,en;q=0.9", 124 | "Connection": "keep-alive", 125 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 126 | "Cookie": COOKIES, 127 | "Host": "u1.oliveboard.in", 128 | "Origin": "https://u1.oliveboard.in", 129 | "Referer": url, 130 | "Sec-Fetch-Dest": "empty", 131 | "Sec-Fetch-Mode": "cors", 132 | "Sec-Fetch-Site": "same-origin", 133 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", 134 | "X-Requested-With": "XMLHttpRequest", 135 | "sec-ch-ua": "\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"", 136 | "sec-ch-ua-mobile": "?0", 137 | "sec-ch-ua-platform": "\"Windows\"", 138 | } 139 | # Formatting q as "test_id001" 140 | q_value = f"{test_id}001" 141 | print(q_value) 142 | raw_data = f"data=%7B%22{q_value}001%22%3A%7B%22q%22%3A%22{q_value}%22%2C%22t%22%3A%5B%7B%22st%22%3A%2201%3A30%3A00%22%2C%22end%22%3A%2201%3A29%3A58%22%7D%5D%2C%22o%22%3A%22%22%7D%2C%22{q_value}002%22%3A%7B%22q%22%3A%22{q_value}%22%2C%22t%22%3A%5B%7B%22st%22%3A%2200%3A59%3A57%22%2C%22end%22%3A%2200%3A59%3A53%22%7D%5D%2C%22o%22%3A%221%22%7D%2C%22{q_value}003%22%3A%7B%22q%22%3A%22{q_value}%22%2C%22t%22%3A%5B%7B%22st%22%3A%2200%3A59%3A53%22%2C%22end%22%3A%2200%3A59%3A47%22%7D%5D%2C%22o%22%3A%22%22%7D%2C%22{q_value}004%22%3A%7B%22q%22%3A%22{q_value}%22%2C%22t%22%3A%5B%7B%22st%22%3A%2200%3A59%3A47%22%2C%22end%22%3A%2200%3A59%3A46%22%7D%2C%7B%22st%22%3A%2200%3A59%3A46%22%2C%22end%22%3A%2200%3A59%3A43%22%7D%5D%2C%22o%22%3A%22%22%7D%7D&uid=&qpi={test_id}&ppi=-1&lang=eqt&c={exam}&source=web" 143 | print(payload) 144 | response = requests.post(surl, headers=headers, data=raw_data) 145 | print(f"Test Submission Response Status Code: {response.status_code}") 146 | 147 | 148 | # Step 2: Fetch Solution 149 | def fetch_solution(url): 150 | headers = { 151 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", 152 | "Accept-Encoding": "gzip, deflate, br, zstd", 153 | "Accept-Language": "en-US,en;q=0.9", 154 | "Connection": "keep-alive", 155 | "Cookie": COOKIES, 156 | "Host": "u1.oliveboard.in", 157 | "Sec-Fetch-Dest": "document", 158 | "Sec-Fetch-Mode": "navigate", 159 | "Sec-Fetch-Site": "none", 160 | "Sec-Fetch-User": "?1", 161 | "Upgrade-Insecure-Requests": "1", 162 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", 163 | "sec-ch-ua": "\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\"", 164 | "sec-ch-ua-mobile": "?0", 165 | "sec-ch-ua-platform": "\"Windows\"", 166 | } 167 | response = requests.get(url, headers=headers) 168 | html_content = response.text 169 | print(f"Solution Fetch Response Status Code: {response.status_code}") 170 | return html_content 171 | 172 | from bs4 import BeautifulSoup 173 | from urllib.parse import urljoin 174 | 175 | DEFAULT_BASE_URL = "https://u1.oliveboard.in/exams/tests/" 176 | 177 | def modify_html(html, full_url): 178 | """ 179 | Modifies the HTML content by appending the appropriate base URL 180 | to relative links for 'href' and 'src' attributes. 181 | """ 182 | soup = BeautifulSoup(html, "html.parser") 183 | 184 | for tag in soup.find_all(["a", "img", "link", "script"]): 185 | # Handle 'href' attribute for and tags 186 | if tag.has_attr("href"): 187 | if not tag["href"].startswith("http"): # Only modify relative links 188 | tag["href"] = urljoin(DEFAULT_BASE_URL, tag["href"]) 189 | 190 | # Handle 'src' attribute for and