Upload 5 files
Browse files- eduboom.py +63 -0
- main.py +65 -0
- templates/detail.html +76 -0
- templates/results.html +18 -0
- templates/search.html +13 -0
eduboom.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import json
|
| 3 |
+
from bs4 import BeautifulSoup
|
| 4 |
+
headers = {
|
| 5 |
+
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
|
| 6 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 7 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
| 8 |
+
# 'Accept-Encoding': 'gzip, deflate, br, zstd',
|
| 9 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 10 |
+
'DNT': '1',
|
| 11 |
+
'Sec-GPC': '1',
|
| 12 |
+
'Connection': 'keep-alive',
|
| 13 |
+
'Referer': 'https://eduboom.it/',
|
| 14 |
+
# 'Cookie': 'PHPSESSID=ibmi18fulfuhve42sq49tbkkme',
|
| 15 |
+
'Sec-Fetch-Dest': 'empty',
|
| 16 |
+
'Sec-Fetch-Mode': 'cors',
|
| 17 |
+
'Sec-Fetch-Site': 'same-origin',
|
| 18 |
+
'Pragma': 'no-cache',
|
| 19 |
+
'Cache-Control': 'no-cache',
|
| 20 |
+
# Requests doesn't support trailers
|
| 21 |
+
# 'TE': 'trailers',
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def get_m3u8(temp_url):
|
| 26 |
+
response = requests.get(temp_url, headers=headers)
|
| 27 |
+
soup = BeautifulSoup(response.text, 'lxml')
|
| 28 |
+
data_params = soup.find('div', class_='ucha-player play-button')['data-params']
|
| 29 |
+
real_data = json.loads(data_params)
|
| 30 |
+
m3u8_link = real_data['sources']['main']['smil']
|
| 31 |
+
if "smil:trailer" in m3u8_link:
|
| 32 |
+
m3u8_link = m3u8_link.replace("smil:trailers","smil:videos").replace("/registration","")
|
| 33 |
+
print("Found .m3u8 link:", m3u8_link)
|
| 34 |
+
return m3u8_link
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def eduboom(query):
|
| 39 |
+
try:
|
| 40 |
+
params = {
|
| 41 |
+
'term': query,
|
| 42 |
+
}
|
| 43 |
+
response = requests.get('https://eduboom.it/ajax/lessons-search', params=params, headers=headers)
|
| 44 |
+
data = response.json()
|
| 45 |
+
i = 0
|
| 46 |
+
for item in data:
|
| 47 |
+
i = i + 1
|
| 48 |
+
name = item['value']
|
| 49 |
+
category = item['category']
|
| 50 |
+
grade = item['grade']
|
| 51 |
+
print("ID:",i,"Name:",name,"Category:",category,"Grade:",grade)
|
| 52 |
+
user_input = int(input("Enter the id of the video you want to watch: "))
|
| 53 |
+
selected_item = data[user_input-1]
|
| 54 |
+
link = selected_item['url']
|
| 55 |
+
m3u8_link = get_m3u8(link)
|
| 56 |
+
return m3u8_link
|
| 57 |
+
|
| 58 |
+
except Exception as e:
|
| 59 |
+
print("Nothing",e)
|
| 60 |
+
return None
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
a = eduboom("Parini")
|
main.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Request, Form
|
| 2 |
+
from fastapi.responses import HTMLResponse
|
| 3 |
+
from fastapi.templating import Jinja2Templates
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
from bs4 import BeautifulSoup
|
| 7 |
+
|
| 8 |
+
# FastAPI setup
|
| 9 |
+
app = FastAPI()
|
| 10 |
+
|
| 11 |
+
# Set up Jinja2 for templating
|
| 12 |
+
templates = Jinja2Templates(directory="templates")
|
| 13 |
+
|
| 14 |
+
# Custom headers for the requests
|
| 15 |
+
headers = {
|
| 16 |
+
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
|
| 17 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 18 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
| 19 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 20 |
+
'DNT': '1',
|
| 21 |
+
'Sec-GPC': '1',
|
| 22 |
+
'Connection': 'keep-alive',
|
| 23 |
+
'Referer': 'https://eduboom.it/',
|
| 24 |
+
'Pragma': 'no-cache',
|
| 25 |
+
'Cache-Control': 'no-cache',
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
def get_m3u8(temp_url):
|
| 29 |
+
response = requests.get(temp_url, headers=headers)
|
| 30 |
+
soup = BeautifulSoup(response.text, 'lxml')
|
| 31 |
+
data_params = soup.find('div', class_='ucha-player play-button')['data-params']
|
| 32 |
+
real_data = json.loads(data_params)
|
| 33 |
+
m3u8_link = real_data['sources']['main']['smil']
|
| 34 |
+
if "smil:trailer" in m3u8_link:
|
| 35 |
+
m3u8_link = m3u8_link.replace("smil:trailers", "smil:videos").replace("/registration", "")
|
| 36 |
+
return m3u8_link
|
| 37 |
+
|
| 38 |
+
def eduboom(query):
|
| 39 |
+
params = {'term': query}
|
| 40 |
+
response = requests.get('https://eduboom.it/ajax/lessons-search', params=params, headers=headers)
|
| 41 |
+
data = response.json()
|
| 42 |
+
return data
|
| 43 |
+
|
| 44 |
+
@app.get("/", response_class=HTMLResponse)
|
| 45 |
+
async def search_form(request: Request):
|
| 46 |
+
return templates.TemplateResponse("search.html", {"request": request})
|
| 47 |
+
|
| 48 |
+
@app.post("/search", response_class=HTMLResponse)
|
| 49 |
+
async def search_results(request: Request, query: str = Form(...)):
|
| 50 |
+
results = eduboom(query)
|
| 51 |
+
return templates.TemplateResponse("results.html", {"request": request, "results": results, "query": query})
|
| 52 |
+
|
| 53 |
+
@app.get("/video/{video_id}", response_class=HTMLResponse)
|
| 54 |
+
async def video_details(request: Request, video_id: int, query: str):
|
| 55 |
+
results = eduboom(query)
|
| 56 |
+
selected_item = results[video_id - 1]
|
| 57 |
+
link = selected_item['url']
|
| 58 |
+
m3u8_link = get_m3u8(link)
|
| 59 |
+
return templates.TemplateResponse("detail.html", {
|
| 60 |
+
"request": request,
|
| 61 |
+
"name": selected_item['value'],
|
| 62 |
+
"category": selected_item['category'],
|
| 63 |
+
"grade": selected_item['grade'],
|
| 64 |
+
"m3u8_link": m3u8_link
|
| 65 |
+
})
|
templates/detail.html
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>{{ name }}</title>
|
| 7 |
+
|
| 8 |
+
<!-- Video.js CSS -->
|
| 9 |
+
<link href="https://vjs.zencdn.net/7.2.3/video-js.css" rel="stylesheet">
|
| 10 |
+
|
| 11 |
+
<!-- Custom CSS for larger video and centered layout -->
|
| 12 |
+
<style>
|
| 13 |
+
body {
|
| 14 |
+
display: flex;
|
| 15 |
+
justify-content: center;
|
| 16 |
+
align-items: flex-start; /* Align items towards the top */
|
| 17 |
+
flex-direction: column;
|
| 18 |
+
padding-top: 20px; /* Spacing from the top */
|
| 19 |
+
margin: 0;
|
| 20 |
+
font-family: Arial, sans-serif;
|
| 21 |
+
}
|
| 22 |
+
h1, p {
|
| 23 |
+
text-align: center;
|
| 24 |
+
width: 100%;
|
| 25 |
+
}
|
| 26 |
+
.video-container {
|
| 27 |
+
display: flex;
|
| 28 |
+
justify-content: center;
|
| 29 |
+
width: 100%;
|
| 30 |
+
}
|
| 31 |
+
video {
|
| 32 |
+
width: 100%; /* Let the video fill the container */
|
| 33 |
+
max-width: 1280px; /* Maximum width for larger screens */
|
| 34 |
+
height: 720px; /* Maintain 720p height */
|
| 35 |
+
}
|
| 36 |
+
</style>
|
| 37 |
+
</head>
|
| 38 |
+
<body>
|
| 39 |
+
<h1>{{ name }}</h1>
|
| 40 |
+
<p>Categoria: {{ category }}</p>
|
| 41 |
+
<p>Grado: {{ grade }}</p>
|
| 42 |
+
|
| 43 |
+
<!-- Container to center the video -->
|
| 44 |
+
<div class="video-container">
|
| 45 |
+
<!-- Video.js Player -->
|
| 46 |
+
<video
|
| 47 |
+
id="hls-example"
|
| 48 |
+
class="video-js vjs-default-skin"
|
| 49 |
+
controls
|
| 50 |
+
preload="auto">
|
| 51 |
+
<!-- Embed the .m3u8 stream dynamically -->
|
| 52 |
+
<source src="{{ m3u8_link }}" type="application/x-mpegURL">
|
| 53 |
+
</video>
|
| 54 |
+
</div>
|
| 55 |
+
|
| 56 |
+
<!-- Link to the .m3u8 file -->
|
| 57 |
+
<p>
|
| 58 |
+
<a href="{{ m3u8_link }}" target="_blank">Link to m3u8</a>
|
| 59 |
+
</p>
|
| 60 |
+
|
| 61 |
+
<!-- JS for Video.js and HLS playback support -->
|
| 62 |
+
<script src="https://vjs.zencdn.net/7.2.3/video.js"></script>
|
| 63 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.14.1/videojs-contrib-hls.js"></script>
|
| 64 |
+
|
| 65 |
+
<script>
|
| 66 |
+
// Initialize the player and force the width/height to be larger
|
| 67 |
+
var player = videojs('hls-example', {
|
| 68 |
+
width: 1280, // Width of the video
|
| 69 |
+
height: 720 // Height of the video
|
| 70 |
+
});
|
| 71 |
+
|
| 72 |
+
// Autoplay video when the page loads
|
| 73 |
+
player.play();
|
| 74 |
+
</script>
|
| 75 |
+
</body>
|
| 76 |
+
</html>
|
templates/results.html
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html>
|
| 3 |
+
<head>
|
| 4 |
+
<title>Risultati della Ricerca</title>
|
| 5 |
+
</head>
|
| 6 |
+
<body>
|
| 7 |
+
<h1>Risultati per "{{ query }}"</h1>
|
| 8 |
+
<ul>
|
| 9 |
+
{% for result in results %}
|
| 10 |
+
<li>
|
| 11 |
+
<a href="/video/{{ loop.index }}?query={{ query }}">
|
| 12 |
+
{{ result.value }} - {{ result.category }} - {{ result.grade }}
|
| 13 |
+
</a>
|
| 14 |
+
</li>
|
| 15 |
+
{% endfor %}
|
| 16 |
+
</ul>
|
| 17 |
+
</body>
|
| 18 |
+
</html>
|
templates/search.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html>
|
| 3 |
+
<head>
|
| 4 |
+
<title>Cerca un video su eduboom</title>
|
| 5 |
+
</head>
|
| 6 |
+
<body>
|
| 7 |
+
<h1>Cerca un video</h1>
|
| 8 |
+
<form action="/search" method="post">
|
| 9 |
+
<input type="text" name="query" placeholder="Enter your query">
|
| 10 |
+
<button type="submit">Cerca</button>
|
| 11 |
+
</form>
|
| 12 |
+
</body>
|
| 13 |
+
</html>
|