fix: Project lists once again display the list
Signed-off-by: Skylar "The Cobra" Widulski <cobra@vern.cc>
This commit is contained in:
parent
8428d81708
commit
30f142ce15
135
main.py
135
main.py
|
@ -3,10 +3,14 @@
|
|||
from flask import Flask, render_template, request, redirect, Response, stream_with_context
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
from math import ceil
|
||||
from bs4 import BeautifulSoup
|
||||
from urllib.parse import quote, unquote
|
||||
from traceback import print_exc
|
||||
|
||||
typesense_key = "TUIxY0xkNjdHV09KaFV1dEVxYVRHNGs1QW1sbzlNVVZBaVZKV2VrODc0VT02ZWFYeyJleGNsdWRlX2ZpZWxkcyI6WyJvdXRfb2YiLCJzZWFyY2hfdGltZV9tcyIsInN0ZXBCb2R5Il0sInBlcl9wYWdlIjo2MH0="
|
||||
|
||||
def proxy(src):
|
||||
return "/proxy/?url=" + quote(str(src))
|
||||
|
||||
|
@ -79,7 +83,67 @@ def member_header(header):
|
|||
|
||||
return [avatar, title, location, signup, instructables, views, comments, followers, bio]
|
||||
|
||||
def category_page(path, name, teachers=False):
|
||||
|
||||
def search(path, args, query='*'):
|
||||
sort_by = "publishDate"
|
||||
if args.get("sort"):
|
||||
if args.get("sort").lower() == "views":
|
||||
sort_by = "views"
|
||||
elif args.get("sort").lower() == "favorites":
|
||||
sort_by = "favorites"
|
||||
elif args.get("sort").lower() == "i made its":
|
||||
sort_by = "IMadeItCount"
|
||||
type_ = "featureFlag%3A%3Dtrue"
|
||||
if args.get("projects"):
|
||||
if args.get("projects").lower() == "winners":
|
||||
type_ = "contestFinalist%3A%3Dtrue"
|
||||
elif args.get("projects").lower() == "all":
|
||||
type_ = ''
|
||||
|
||||
split_path = path.split('/')
|
||||
|
||||
category = "category%3A%3D" + split_path[1] if len(split_path) > 1 and split_path[1] != '' and split_path[1] != 'projects' and not split_path[1].startswith("?x") else ''
|
||||
if not type_ == '':
|
||||
category = "+%26%26+" + category
|
||||
|
||||
channel = "channel%3A%3D" + split_path[2] if len(split_path) > 2 and split_path[2] != '' and split_path[2] != 'projects' and not split_path[2].startswith("?x") else ''
|
||||
if not type_ == '' or not category == '':
|
||||
channel = "+%26%26+" + channel
|
||||
|
||||
page = 1
|
||||
if args.get("page"):
|
||||
page = args.get("page")
|
||||
|
||||
|
||||
|
||||
search_url = f"https://www.instructables.com/api_proxy/search/collections/projects/documents/search?q={query}&query_by=title%2CstepBody%2CscreenName&page={page}&sort_by={sort_by}%3Adesc&include_fields=title%2CurlString%2CcoverImageUrl%2CscreenName%2Cfavorites%2Cviews%2CprimaryClassification%2CfeatureFlag%2CprizeLevel%2CIMadeItCount&filter_by={type_}{category}{channel}&per_page=60"
|
||||
search_data = requests.get(search_url, headers={"X-Typesense-API-Key": typesense_key})
|
||||
|
||||
if search_data.status_code != 200:
|
||||
return Response(render_template(str(search_data.status_code) + ".html"), status=search_data.status_code)
|
||||
|
||||
json_data = json.loads(search_data.text)
|
||||
|
||||
ibles = []
|
||||
for document in json_data["hits"]:
|
||||
ible = document["document"]
|
||||
link = "/" + ible["urlString"] + "/"
|
||||
img = proxy(ible["coverImageUrl"])
|
||||
|
||||
title = ible["title"]
|
||||
author = ible["screenName"]
|
||||
author_link = "/member/" + quote(author)
|
||||
channel = ible["primaryClassification"].split("/")[-1].title()
|
||||
channel_link = "/" + ible["primaryClassification"]
|
||||
|
||||
views = ible["views"]
|
||||
favorites = ible["favorites"]
|
||||
imadeits = ible["IMadeItCount"]
|
||||
|
||||
ibles.append([link, img, title, author_link, author, channel_link, channel, views, favorites, imadeits])
|
||||
return (ibles, int(page), ceil(int(json_data["found"]) / 60))
|
||||
|
||||
def teachers_page(path, name):
|
||||
data = requests.get("https://www.instructables.com" + path)
|
||||
if data.status_code != 200:
|
||||
return Response(render_template(str(data.status_code) + ".html"), status=data.status_code)
|
||||
|
@ -89,7 +153,7 @@ def category_page(path, name, teachers=False):
|
|||
channels = []
|
||||
for card in soup.select("div.scrollable-cards-inner div.scrollable-card"):
|
||||
link = card.a["href"]
|
||||
img = proxy(card.select(f"a{' noscript' if teachers else ''} img")[0].get("src"))
|
||||
img = proxy(card.select(f"a noscript img")[0].get("src"))
|
||||
title = card.select("a img")[0].get("alt")
|
||||
|
||||
channels.append([link, title, img])
|
||||
|
@ -124,37 +188,30 @@ def category_page(path, name, teachers=False):
|
|||
|
||||
contests.append([link, img, title])
|
||||
|
||||
return render_template("category.html", data=[name, channels, ibles, contests, path])
|
||||
return render_template("teachers.html", data=[name, channels, ibles, contests, path])
|
||||
|
||||
def project_list(path, head, sort=''):
|
||||
def project_list(path, head, args=None, realpath=None):
|
||||
if not realpath:
|
||||
realpath = path
|
||||
data = requests.get("https://www.instructables.com" + path)
|
||||
if data.status_code != 200:
|
||||
return Response(render_template(str(data.status_code) + ".html"), status=data.status_code)
|
||||
print(data.text)
|
||||
head = f"{head + ' ' if head != '' else ''}Projects" + sort
|
||||
path_ = path.rsplit('/', 1)[0]
|
||||
|
||||
head = f"{head + ' ' if head != '' else ''}Projects"
|
||||
soup = BeautifulSoup(data.text, "html.parser")
|
||||
|
||||
searched = search(path, args)
|
||||
|
||||
ibles = []
|
||||
for ible in soup.select("div[class^=cards__] div[class^=ibleCard__]"):
|
||||
print(ible)
|
||||
link = ible.select("div a")[0].get("href")
|
||||
img = proxy(ible.select("div a img")[0].get("src"))
|
||||
if type(searched) == Response:
|
||||
return searched
|
||||
|
||||
info = ible.select("div div[class^=description__]")[0]
|
||||
title = info.select("strong a[^=title__]")[0].text
|
||||
author = info.select("a")[0].get("href")
|
||||
author_link = info.select("a")[0].text
|
||||
channel = info.select("a")[1].get("href")
|
||||
channel_link = info.select("a")[1].text
|
||||
ibles = searched[0]
|
||||
page = searched[1]
|
||||
pages = searched[2]
|
||||
|
||||
stats = ible.select("div[class^=footer__] div[class^=stats__]")[0]
|
||||
views = stats.select("div")[1].text
|
||||
favorites = stats.select("div")[0].text
|
||||
return render_template("projects.html", data=[head, ibles, realpath, page, pages], sub=re.sub)
|
||||
|
||||
ibles.append([link, img, title, author, author_link, channel, channel_link, views, favorites])
|
||||
|
||||
return render_template("projects.html", data=[head, ibles, path_])
|
||||
|
||||
app = Flask(__name__, template_folder="templates", static_folder="static")
|
||||
|
||||
|
@ -299,55 +356,43 @@ def route_contests():
|
|||
|
||||
@app.route('/<category>/<channel>/projects/')
|
||||
def route_channel_projects(category, channel):
|
||||
return project_list(f"/{category}/{channel}/projects/", channel.title())
|
||||
|
||||
@app.route('/<category>/<channel>/projects/<sort>/')
|
||||
def route_channel_projects_sort(category, channel, sort):
|
||||
return project_list(f"/{category}/{channel}/projects/{sort}", channel.title(), " Sorted by " + sort.title())
|
||||
return project_list(f"/{category}/{channel}/projects/?x", channel.title(), request.args, request.full_path)
|
||||
|
||||
@app.route('/<category>/projects/')
|
||||
def route_category_projects(category):
|
||||
return project_list(f"/{category}/projects/", category.title())
|
||||
|
||||
@app.route('/<category>/projects/<sort>/')
|
||||
def route_category_projects_sort(category, sort):
|
||||
return project_list(f"/{category}/projects/{sort}", category.title(), " Sorted by " + sort.title())
|
||||
return project_list(f"/{category}/projects/?x", category.title(), request.args, request.full_path)
|
||||
|
||||
@app.route('/projects/')
|
||||
def route_projects():
|
||||
return project_list("/projects/", '')
|
||||
|
||||
@app.route('/projects/<sort>/')
|
||||
def route_projects_sort(sort):
|
||||
return project_list(f"/projects/{sort}", '', " Sorted by " + sort.title())
|
||||
return project_list("/projects/?x", '', request.args, request.full_path)
|
||||
|
||||
@app.route('/circuits/')
|
||||
def route_circuits():
|
||||
return category_page("/circuits/", "Circuits")
|
||||
return project_list("/circuits/?x", "Circuits", request.args, request.full_path)
|
||||
|
||||
@app.route('/workshop/')
|
||||
def route_workshop():
|
||||
return category_page("/workshop/", "Workshop")
|
||||
return project_list("/workshop/?x", "Workshop", request.args, request.full_path)
|
||||
|
||||
@app.route('/craft/')
|
||||
def route_craft():
|
||||
return category_page("/craft/", "Craft")
|
||||
return project_list("/craft/?x", "Craft", request.args, request.full_path)
|
||||
|
||||
@app.route('/cooking/')
|
||||
def route_cooking():
|
||||
return category_page("/cooking/", "Cooking")
|
||||
return project_list("/cooking/?x", "Cooking", request.args, request.full_path)
|
||||
|
||||
@app.route('/living/')
|
||||
def route_living():
|
||||
return category_page("/living/", "Living")
|
||||
return project_list("/living/?x", "Living", request.args, request.full_path)
|
||||
|
||||
@app.route('/outside/')
|
||||
def route_outside():
|
||||
return category_page("/outside/", "Outside")
|
||||
return project_list("/outside/?x", "Outside", request.args, request.full_path)
|
||||
|
||||
@app.route('/teachers/')
|
||||
def route_teachers():
|
||||
return category_page("/teachers/", "Teachers", True)
|
||||
return teachers_page("/teachers/?x", "Teachers")
|
||||
|
||||
@app.route('/member/<member>/instructables/')
|
||||
def route_member_instructables(member):
|
||||
|
|
|
@ -11,11 +11,15 @@
|
|||
{% include "header.html" %}
|
||||
<center>
|
||||
<h1>{{ data[0] }}</h1>
|
||||
<span><a href="{{ data[2] }}/">Featured</a></span>
|
||||
<span><a href="{{ data[2] }}/recent/">Recent</a></span>
|
||||
<span><a href="{{ data[2] }}/popular/">Popular</a></span>
|
||||
<span><a href="{{ data[2] }}/views/">Views</a></span>
|
||||
<span><a href="{{ data[2] }}/winners/">Winners</a></span>
|
||||
<span><a href="{{ sub("[&?]projects=[^&]*", '', data[2]) }}&projects=all">All</a></span>
|
||||
<span><a href="{{ sub("[&?]projects=[^&]*", '', data[2]) }}&projects=featured">Featured</a></span>
|
||||
<span><a href="{{ sub("[&?]projects=[^&]*", '', data[2]) }}&projects=winners">Winners</a></span>
|
||||
<br>
|
||||
<span>Sort by:</span>
|
||||
<span><a href="{{ sub("[&?]sort=[^&]*", '', data[2]) }}&sort=Newest">Date</a></span>
|
||||
<span><a href="{{ sub("[&?]sort=[^&]*", '', data[2]) }}&sort=Views">Views</a></span>
|
||||
<span><a href="{{ sub("[&?]sort=[^&]*", '', data[2]) }}&sort=Favorites">Favorites</a></span>
|
||||
<span><a href="{{ sub("[&?]sort=[^&]*", '', data[2]) }}&sort=I+Made+Its">I Made Its</a></span>
|
||||
<br>
|
||||
|
||||
<div style="max-width:90%;">
|
||||
|
@ -26,10 +30,31 @@
|
|||
<p>{{ ible[2] }}</p>
|
||||
</a>
|
||||
<p>by <a href="{{ ible[3] }}">{{ ible[4] }}</a> in <a href="{{ ible[5] }}">{{ ible[6] }}</a></p>
|
||||
<p>{{ ible[7] }} Views, {{ ible[8] }} Favorites</p>
|
||||
<p>{{ ible[7] }} Views, {{ ible[8] }} Favorites, {{ ible[9] }} I Made Its</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
{% if data[3] == 1 %}
|
||||
<li class="arrow arrow-prev disabled"><a>Previous</a></li>
|
||||
{% else %}
|
||||
<li class="arrow arrow-prev"><a href="{{ data[2] }}&page={{ data[3] - 1 }}">Previous</a></li>
|
||||
{% endif %}
|
||||
{% for page in range(1, data[4] + 1) %}
|
||||
{% if ((data[3] - page < 3) and (data[3] - page > -3)) or (page == 1 or page == data[4]) %}
|
||||
{% if page != data[3] %}
|
||||
<li><a href="{{ data[2] }}&page={{ page }}">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="active"><a>{{ page }}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if data[3] == data[4] %}
|
||||
<li class="arrow arrow-next disabled"><a>Next</a></li>
|
||||
{% else %}
|
||||
<li class="arrow arrow-next"><a href="{{ data[2] }}&page={{ data[3] + 1 }}">Next</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</center>
|
||||
{% include "footer.html" %}
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue