├── 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 |
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 | [](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