vtu-auto 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: vtu-auto
3
+ Version: 0.1.0
4
+ Summary: VTU online video progress automater
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: requests>=2.33.1
8
+ Requires-Dist: rich>=13.0.0
9
+
10
+ # VTU Auto-Progress Bypasser
11
+
12
+ A beautiful, fast, API-driven CLI tool to automate video progress completion on the VTU portal.
13
+
14
+ ## Features
15
+ - **API-Driven**: Completes hours of video in seconds by safely pinging the backend.
16
+ - **Beautiful UI**: Built with `rich` for elegant tables, spinners, and live progress bars.
17
+ - **Smart Pumping**: Overrides internal VTU progress bugs by dynamically pumping progress payloads until completion is acknowledged by the server.
18
+ - **Secure**: Takes credentials safely through prompt hiding in the terminal. No credentials are saved to disk.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install vtu-auto
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ Simply run:
29
+ ```bash
30
+ vtu-auto
31
+ ```
32
+
33
+ To view underlying API HTTP response trace logs locally:
34
+ ```bash
35
+ vtu-auto --log
36
+ ```
@@ -0,0 +1,27 @@
1
+ # VTU Auto-Progress Bypasser
2
+
3
+ A beautiful, fast, API-driven CLI tool to automate video progress completion on the VTU portal.
4
+
5
+ ## Features
6
+ - **API-Driven**: Completes hours of video in seconds by safely pinging the backend.
7
+ - **Beautiful UI**: Built with `rich` for elegant tables, spinners, and live progress bars.
8
+ - **Smart Pumping**: Overrides internal VTU progress bugs by dynamically pumping progress payloads until completion is acknowledged by the server.
9
+ - **Secure**: Takes credentials safely through prompt hiding in the terminal. No credentials are saved to disk.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install vtu-auto
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Simply run:
20
+ ```bash
21
+ vtu-auto
22
+ ```
23
+
24
+ To view underlying API HTTP response trace logs locally:
25
+ ```bash
26
+ vtu-auto --log
27
+ ```
@@ -0,0 +1,13 @@
1
+ [project]
2
+ name = "vtu-auto"
3
+ version = "0.1.0"
4
+ description = "VTU online video progress automater"
5
+ readme = "README.md"
6
+ requires-python = ">=3.8"
7
+ dependencies = [
8
+ "requests>=2.33.1",
9
+ "rich>=13.0.0",
10
+ ]
11
+
12
+ [project.scripts]
13
+ vtu-auto = "vtu_auto.cli:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ # Initialize module
@@ -0,0 +1,253 @@
1
+ import requests
2
+ import json
3
+ import time
4
+ import sys
5
+ import os
6
+ import argparse
7
+ import logging
8
+ from rich.console import Console
9
+ from rich.prompt import Prompt
10
+ from rich.panel import Panel
11
+ from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn
12
+ from rich.syntax import Syntax
13
+ from rich.table import Table
14
+ from rich import box
15
+ from rich.align import Align
16
+
17
+ # Initialize Rich Console
18
+ console = Console()
19
+
20
+ # Setup standard logging to file
21
+ log_formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s')
22
+ logger = logging.getLogger('vtu_automater')
23
+ logger.setLevel(logging.DEBUG)
24
+
25
+ file_handler = logging.FileHandler('api_responses.log', 'w', encoding='utf-8')
26
+ file_handler.setFormatter(log_formatter)
27
+ logger.addHandler(file_handler)
28
+
29
+ BASE_URL = "https://online.vtu.ac.in/api/v1"
30
+
31
+ class VTUBypasser:
32
+ def __init__(self, email, password):
33
+ self.email = email
34
+ self.password = password
35
+ self.session = requests.Session()
36
+ self.session.headers.update({
37
+ "Accept": "application/json",
38
+ "Content-Type": "application/json",
39
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
40
+ "Origin": "https://online.vtu.ac.in",
41
+ "Referer": "https://online.vtu.ac.in/"
42
+ })
43
+
44
+ def login(self):
45
+ login_url = f"{BASE_URL}/auth/login"
46
+ payload = {"email": self.email, "password": self.password}
47
+
48
+ try:
49
+ response = self.session.post(login_url, json=payload)
50
+ data = response.json()
51
+ logger.info(f"Login Response: HTTP {response.status_code} | Body: {json.dumps(data)}")
52
+
53
+ if response.status_code == 200 and data.get("success"):
54
+ user_name = data.get("data", {}).get("name", "User")
55
+ return True, user_name
56
+ else:
57
+ msg = data.get('message', 'Unknown Error')
58
+ return False, msg
59
+ except Exception as e:
60
+ logger.error(f"Login Error: {e}", exc_info=True)
61
+ return False, str(e)
62
+
63
+ def get_enrolled_courses(self):
64
+ enrollments_url = f"{BASE_URL}/student/my-enrollments"
65
+ try:
66
+ response = self.session.get(enrollments_url)
67
+ data = response.json()
68
+ if response.status_code == 200 and data.get("success"):
69
+ return data.get("data", [])
70
+ except Exception as e:
71
+ logger.error(f"Enrollments Error: {e}", exc_info=True)
72
+ return []
73
+
74
+ def get_course_details(self, course_slug):
75
+ course_url = f"{BASE_URL}/student/my-courses/{course_slug}"
76
+ try:
77
+ response = self.session.get(course_url)
78
+ data = response.json()
79
+ if response.status_code == 200 and data.get("success"):
80
+ return data.get("data", {})
81
+ except Exception as e:
82
+ logger.error(f"Course Details Error for {course_slug}: {e}", exc_info=True)
83
+ return None
84
+
85
+ def mark_video_complete(self, course_slug, lecture_id, progress_ctx, task_id):
86
+ progress_url = f"{BASE_URL}/student/my-courses/{course_slug}/lectures/{lecture_id}/progress"
87
+
88
+ max_attempts = 150
89
+ current_time = 0
90
+
91
+ for attempt in range(1, max_attempts + 1):
92
+ current_time += 120
93
+ payload = {
94
+ "current_time_seconds": current_time,
95
+ "total_duration_seconds": 3600,
96
+ "seconds_just_watched": 120
97
+ }
98
+
99
+ try:
100
+ response = self.session.post(progress_url, json=payload)
101
+ res_data = response.json()
102
+ data_dict = res_data.get("data", {})
103
+
104
+ is_completed = data_dict.get("is_completed", False)
105
+ percent = data_dict.get("percent", 0)
106
+
107
+ logger.info(f"Progress Ping ({lecture_id}) Att {attempt}: HTTP {response.status_code} | Body: {json.dumps(res_data)}")
108
+
109
+ progress_ctx.update(task_id, completed=percent)
110
+
111
+ if is_completed or percent >= 98:
112
+ progress_ctx.update(task_id, completed=100)
113
+ return True, percent
114
+
115
+ if attempt == max_attempts:
116
+ return False, percent
117
+
118
+ time.sleep(0.5)
119
+ except Exception as e:
120
+ logger.error(f"Progress Ping Error ({lecture_id}): {e}", exc_info=True)
121
+ return False, -1
122
+
123
+ def view_logs():
124
+ if not os.path.exists('api_responses.log'):
125
+ console.print("[bold yellow]⚠ Log file 'api_responses.log' not found.[/bold yellow]")
126
+ return
127
+
128
+ console.print(Panel(Align.center("[bold cyan]◷ Recent VTU API Responses Log [/bold cyan]"), border_style="cyan", padding=(1,2)))
129
+
130
+ with open('api_responses.log', 'r', encoding='utf-8') as f:
131
+ lines = f.readlines()
132
+ recent = "".join(lines[-40:])
133
+
134
+ syntax = Syntax(recent, "log", theme="monokai", word_wrap=True, line_numbers=True)
135
+ console.print(syntax)
136
+
137
+ def main():
138
+ parser = argparse.ArgumentParser(description="VTU Online Video Automation CLI")
139
+ parser.add_argument("--log", action="store_true", help="View recent API response logs")
140
+ args = parser.parse_args()
141
+
142
+ os.system('cls' if os.name == 'nt' else 'clear')
143
+
144
+ # Title Header
145
+ header = Panel(
146
+ Align.center("[bold magenta]🎓 VTU Auto-Progress Bypasser[/bold magenta]\n[dim]v0.1.0 • API-Driven Fast Automation[/dim]"),
147
+ border_style="magenta",
148
+ box=box.DOUBLE
149
+ )
150
+ console.print(header)
151
+ console.print()
152
+
153
+ if args.log:
154
+ view_logs()
155
+ sys.exit(0)
156
+
157
+ # Login UI
158
+ with console.status("[bold blue]Ready...", spinner="point"):
159
+ email = Prompt.ask("[bold cyan]✉ Email[/bold cyan]")
160
+ password = Prompt.ask("[bold cyan]🔑 Password[/bold cyan]", password=True)
161
+
162
+ console.print()
163
+
164
+ bypasser = VTUBypasser(email, password)
165
+
166
+ with console.status("[bold yellow]Authenticating securely...", spinner="aesthetic"):
167
+ success, msg_or_name = bypasser.login()
168
+
169
+ if not success:
170
+ console.print(Panel(f"[bold red]✖ Authentication Failed:[/bold red]\n{msg_or_name}", border_style="red"))
171
+ sys.exit(1)
172
+
173
+ console.print(f"[bold green]✔[/bold green] Authentication successful! Welcome, [bold cyan]{msg_or_name}[/bold cyan]!")
174
+
175
+ # Fetch courses
176
+ with console.status("[bold yellow]Fetching your enrolled courses...", spinner="aesthetic"):
177
+ courses = bypasser.get_enrolled_courses()
178
+
179
+ if not courses:
180
+ console.print(Panel("[bold red]✖ No enrolled courses found on this account.[/bold red]", border_style="red"))
181
+ sys.exit(0)
182
+
183
+ # Display courses cleanly in a table
184
+ table = Table(title="📚 Enrolled Courses", box=box.ROUNDED, border_style="blue", title_style="bold underline")
185
+ table.add_column("Course ID", justify="center", style="cyan", no_wrap=True)
186
+ table.add_column("Course Title", style="magenta")
187
+ table.add_column("Progress", justify="right", style="green")
188
+
189
+ for enrollment in courses:
190
+ details = enrollment.get("details", {})
191
+ prog = enrollment.get("progress_percent", "0")
192
+ table.add_row(str(details.get("id", "N/A")), details.get("title", "Unknown"), f"{prog}%")
193
+
194
+ console.print("\n")
195
+ console.print(table)
196
+ console.print("\n")
197
+
198
+ for enrollment in courses:
199
+ details = enrollment.get("details", {})
200
+ course_slug = details.get("slug")
201
+ course_title = details.get("title")
202
+
203
+ if not course_slug:
204
+ continue
205
+
206
+ console.print(Panel(Align.center(f"[bold white]Processing:[/bold white] [bold yellow]{course_title}[/bold yellow]"), border_style="green"))
207
+
208
+ course_data = bypasser.get_course_details(course_slug)
209
+ if not course_data:
210
+ console.print(f"[bold red]✖ Could not load details for {course_title}[/bold red]")
211
+ continue
212
+
213
+ lessons = course_data.get("lessons", [])
214
+
215
+ for week in lessons:
216
+ week_name = week.get("name", "Unknown Week")
217
+ lectures = week.get("lectures", [])
218
+
219
+ console.print(f"\n[bold blue]⮞ {week_name}[/bold blue] [dim]({len(lectures)} lectures)[/dim]")
220
+
221
+ for lecture in lectures:
222
+ lecture_id = lecture.get("id")
223
+ lecture_title = lecture.get("title", f"Lecture {lecture_id}")
224
+
225
+ # We use a beautiful progress bar for every single video
226
+ with Progress(
227
+ SpinnerColumn(),
228
+ TextColumn("[bold cyan]{task.description}"),
229
+ BarColumn(complete_style="green", finished_style="bold green"),
230
+ TaskProgressColumn(),
231
+ TimeElapsedColumn(),
232
+ console=console,
233
+ transient=False # Keep it printed afterwards
234
+ ) as progress:
235
+
236
+ # Target is 100%
237
+ task_id = progress.add_task(f"{lecture_title}", total=100, completed=0)
238
+
239
+ success, final_percent = bypasser.mark_video_complete(course_slug, lecture_id, progress, task_id)
240
+
241
+ if not success:
242
+ if final_percent == -1:
243
+ progress.update(task_id, description=f"[bold red]✖ {lecture_title} (Network Error)[/bold red]")
244
+ else:
245
+ progress.update(task_id, description=f"[bold yellow]⚠ {lecture_title} (Capped at {final_percent}%)[/bold yellow]")
246
+ else:
247
+ progress.update(task_id, description=f"[bold green]✔ {lecture_title} (Matched 100%)[/bold green]")
248
+
249
+ console.print("\n")
250
+ console.print(Panel(Align.center("[bold green]🎉 All tasks fully finished! You can check the portal now![/bold green]"), border_style="green"))
251
+
252
+ if __name__ == "__main__":
253
+ main()
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: vtu-auto
3
+ Version: 0.1.0
4
+ Summary: VTU online video progress automater
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: requests>=2.33.1
8
+ Requires-Dist: rich>=13.0.0
9
+
10
+ # VTU Auto-Progress Bypasser
11
+
12
+ A beautiful, fast, API-driven CLI tool to automate video progress completion on the VTU portal.
13
+
14
+ ## Features
15
+ - **API-Driven**: Completes hours of video in seconds by safely pinging the backend.
16
+ - **Beautiful UI**: Built with `rich` for elegant tables, spinners, and live progress bars.
17
+ - **Smart Pumping**: Overrides internal VTU progress bugs by dynamically pumping progress payloads until completion is acknowledged by the server.
18
+ - **Secure**: Takes credentials safely through prompt hiding in the terminal. No credentials are saved to disk.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install vtu-auto
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ Simply run:
29
+ ```bash
30
+ vtu-auto
31
+ ```
32
+
33
+ To view underlying API HTTP response trace logs locally:
34
+ ```bash
35
+ vtu-auto --log
36
+ ```
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ vtu_auto/__init__.py
4
+ vtu_auto/cli.py
5
+ vtu_auto.egg-info/PKG-INFO
6
+ vtu_auto.egg-info/SOURCES.txt
7
+ vtu_auto.egg-info/dependency_links.txt
8
+ vtu_auto.egg-info/entry_points.txt
9
+ vtu_auto.egg-info/requires.txt
10
+ vtu_auto.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ vtu-auto = vtu_auto.cli:main
@@ -0,0 +1,2 @@
1
+ requests>=2.33.1
2
+ rich>=13.0.0
@@ -0,0 +1 @@
1
+ vtu_auto